Skip to main content

espresso_types/v0/v0_1/
chain_config.rs

1use alloy::primitives::{Address, U256};
2use alloy_compat::ethers_serde;
3use committable::{Commitment, Committable};
4use derive_more::{Deref, Display, From, Into};
5use itertools::Either;
6use serde::{Deserialize, Serialize};
7
8use crate::{FeeAccount, FeeAmount};
9
10#[derive(Default, Hash, Copy, Clone, Debug, Display, PartialEq, Eq, From, Into)]
11#[cfg_attr(
12    feature = "rlp",
13    derive(alloy_rlp::RlpEncodableWrapper, alloy_rlp::RlpDecodableWrapper)
14)]
15#[display("{_0}")]
16pub struct ChainId(pub U256);
17
18/// Chain id of the Espresso mainnet.
19pub const MAINNET_CHAIN_ID: ChainId = ChainId(U256::ONE);
20
21/// Chain id of the Decaf testnet. Used to gate Decaf-specific light-client behavior.
22pub const DECAF_CHAIN_ID: ChainId = ChainId(U256::from_limbs([0xdecaf, 0, 0, 0]));
23
24#[derive(Hash, Copy, Clone, Debug, Default, Display, PartialEq, Eq, From, Into, Deref)]
25#[display("{_0}")]
26pub struct BlockSize(pub(crate) u64);
27
28/// Global variables for an Espresso blockchain.
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
30pub struct ChainConfig {
31    /// Espresso chain ID
32    pub chain_id: ChainId,
33
34    /// Maximum size in bytes of a block
35    pub max_block_size: BlockSize,
36
37    /// Minimum fee in WEI per byte of payload
38    pub base_fee: FeeAmount,
39
40    /// Fee contract address on L1.
41    ///
42    /// This is optional so that fees can easily be toggled on/off, with no need to deploy a
43    /// contract when they are off. In a future release, after fees are switched on and thoroughly
44    /// tested, this may be made mandatory.
45    #[serde(with = "ethers_serde::option_address")]
46    pub fee_contract: Option<Address>,
47
48    /// Account that receives sequencing fees.
49    ///
50    /// This account in the Espresso fee ledger will always receive every fee paid in Espresso,
51    /// regardless of whether or not their is a `fee_contract` deployed. Once deployed, the fee
52    /// contract can decide what to do with tokens locked in this account in Espresso.
53    pub fee_recipient: FeeAccount,
54}
55
56#[derive(Clone, Debug, Copy, PartialEq, Deserialize, Serialize, Eq, Hash)]
57pub struct ResolvableChainConfig {
58    pub(crate) chain_config: Either<ChainConfig, Commitment<ChainConfig>>,
59}
60
61impl Committable for ChainConfig {
62    fn tag() -> String {
63        "CHAIN_CONFIG".to_string()
64    }
65
66    fn commit(&self) -> Commitment<Self> {
67        let comm = committable::RawCommitmentBuilder::new(&Self::tag())
68            .fixed_size_field("chain_id", &self.chain_id.to_fixed_bytes())
69            .u64_field("max_block_size", *self.max_block_size)
70            .fixed_size_field("base_fee", &self.base_fee.to_fixed_bytes())
71            .fixed_size_field("fee_recipient", &self.fee_recipient.to_fixed_bytes());
72        let comm = if let Some(addr) = self.fee_contract {
73            comm.u64_field("fee_contract", 1).fixed_size_bytes(&addr.0)
74        } else {
75            comm.u64_field("fee_contract", 0)
76        };
77        comm.finalize()
78    }
79}
80
81impl ResolvableChainConfig {
82    pub fn commit(&self) -> Commitment<ChainConfig> {
83        match self.chain_config {
84            Either::Left(config) => config.commit(),
85            Either::Right(commitment) => commitment,
86        }
87    }
88    pub fn resolve(self) -> Option<ChainConfig> {
89        match self.chain_config {
90            Either::Left(config) => Some(config),
91            Either::Right(_) => None,
92        }
93    }
94}
95
96impl From<Commitment<ChainConfig>> for ResolvableChainConfig {
97    fn from(value: Commitment<ChainConfig>) -> Self {
98        Self {
99            chain_config: Either::Right(value),
100        }
101    }
102}
103
104impl From<ChainConfig> for ResolvableChainConfig {
105    fn from(value: ChainConfig) -> Self {
106        Self {
107            chain_config: Either::Left(value),
108        }
109    }
110}
111
112impl Default for ChainConfig {
113    fn default() -> Self {
114        Self {
115            chain_id: U256::from(35353).into(), // arbitrarily chosen chain ID
116            max_block_size: 30720.into(),
117            base_fee: 0.into(),
118            fee_contract: None,
119            fee_recipient: Default::default(),
120        }
121    }
122}