revm_context/
cfg.rs

1pub use context_interface::Cfg;
2
3use interpreter::MAX_CODE_SIZE;
4use specification::hardfork::SpecId;
5use std::{vec, vec::Vec};
6
7/// EVM configuration
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[derive(Clone, Debug, Eq, PartialEq)]
10#[non_exhaustive]
11pub struct CfgEnv<SPEC = SpecId> {
12    /// Chain ID of the EVM
13    ///
14    /// `chain_id` will be compared to the transaction's Chain ID.
15    ///
16    /// Chain ID is introduced EIP-155.
17    pub chain_id: u64,
18    /// Specification for EVM represent the hardfork
19    pub spec: SPEC,
20    /// If some it will effects EIP-170: Contract code size limit.
21    ///
22    /// Useful to increase this because of tests.
23    ///
24    /// By default it is `0x6000` (~25kb).
25    pub limit_contract_code_size: Option<usize>,
26    /// Skips the nonce validation against the account's nonce
27    pub disable_nonce_check: bool,
28    /// Blob target count. EIP-7840 Add blob schedule to EL config files.
29    ///
30    /// Note : Items must be sorted by `SpecId`.
31    pub blob_target_and_max_count: Vec<(SpecId, u8, u8)>,
32    /// A hard memory limit in bytes beyond which
33    /// [OutOfGasError::Memory][context_interface::result::OutOfGasError::Memory] cannot be resized.
34    ///
35    /// In cases where the gas limit may be extraordinarily high, it is recommended to set this to
36    /// a sane value to prevent memory allocation panics.
37    ///
38    /// Defaults to `2^32 - 1` bytes per EIP-1985.
39    #[cfg(feature = "memory_limit")]
40    pub memory_limit: u64,
41    /// Skip balance checks if `true`
42    ///
43    /// Adds transaction cost to balance to ensure execution doesn't fail.
44    ///
45    /// By default, it is set to `false`.
46    #[cfg(feature = "optional_balance_check")]
47    pub disable_balance_check: bool,
48    /// There are use cases where it's allowed to provide a gas limit that's higher than a block's gas limit.
49    ///
50    /// To that end, you can disable the block gas limit validation.
51    ///
52    /// By default, it is set to `false`.
53    #[cfg(feature = "optional_block_gas_limit")]
54    pub disable_block_gas_limit: bool,
55    /// EIP-3607 rejects transactions from senders with deployed code
56    ///
57    /// In development, it can be desirable to simulate calls from contracts, which this setting allows.
58    ///
59    /// By default, it is set to `false`.
60    #[cfg(feature = "optional_eip3607")]
61    pub disable_eip3607: bool,
62    /// Disables all gas refunds
63    ///
64    /// This is useful when using chains that have gas refunds disabled, e.g. Avalanche.
65    ///
66    /// Reasoning behind removing gas refunds can be found in EIP-3298.
67    ///
68    /// By default, it is set to `false`.
69    #[cfg(feature = "optional_gas_refund")]
70    pub disable_gas_refund: bool,
71    /// Disables base fee checks for EIP-1559 transactions
72    ///
73    /// This is useful for testing method calls with zero gas price.
74    ///
75    /// By default, it is set to `false`.
76    #[cfg(feature = "optional_no_base_fee")]
77    pub disable_base_fee: bool,
78}
79
80impl CfgEnv {
81    /// Creates new `CfgEnv` with default values.
82    pub fn new() -> Self {
83        Self::default()
84    }
85}
86
87impl<SPEC> CfgEnv<SPEC> {
88    pub fn with_chain_id(mut self, chain_id: u64) -> Self {
89        self.chain_id = chain_id;
90        self
91    }
92
93    pub fn with_spec<OSPEC: Into<SpecId>>(self, spec: OSPEC) -> CfgEnv<OSPEC> {
94        CfgEnv {
95            chain_id: self.chain_id,
96            limit_contract_code_size: self.limit_contract_code_size,
97            spec,
98            disable_nonce_check: self.disable_nonce_check,
99            blob_target_and_max_count: self.blob_target_and_max_count,
100            #[cfg(feature = "memory_limit")]
101            memory_limit: self.memory_limit,
102            #[cfg(feature = "optional_balance_check")]
103            disable_balance_check: self.disable_balance_check,
104            #[cfg(feature = "optional_block_gas_limit")]
105            disable_block_gas_limit: self.disable_block_gas_limit,
106            #[cfg(feature = "optional_eip3607")]
107            disable_eip3607: self.disable_eip3607,
108            #[cfg(feature = "optional_gas_refund")]
109            disable_gas_refund: self.disable_gas_refund,
110            #[cfg(feature = "optional_no_base_fee")]
111            disable_base_fee: self.disable_base_fee,
112        }
113    }
114
115    /// Sets the blob target and max count over hardforks.
116    pub fn set_blob_max_and_target_count(&mut self, mut vec: Vec<(SpecId, u8, u8)>) {
117        vec.sort_by_key(|(id, _, _)| *id);
118        self.blob_target_and_max_count = vec;
119    }
120}
121
122impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
123    type Spec = SPEC;
124
125    fn chain_id(&self) -> u64 {
126        self.chain_id
127    }
128
129    fn spec(&self) -> Self::Spec {
130        self.spec
131    }
132
133    #[inline]
134    fn blob_max_count(&self, spec_id: SpecId) -> u8 {
135        self.blob_target_and_max_count
136            .iter()
137            .rev()
138            .find_map(|(id, _, max)| {
139                if spec_id as u8 >= *id as u8 {
140                    return Some(*max);
141                }
142                None
143            })
144            .unwrap_or(6)
145    }
146
147    fn max_code_size(&self) -> usize {
148        self.limit_contract_code_size.unwrap_or(MAX_CODE_SIZE)
149    }
150
151    fn is_eip3607_disabled(&self) -> bool {
152        cfg_if::cfg_if! {
153            if #[cfg(feature = "optional_eip3607")] {
154                self.disable_eip3607
155            } else {
156                false
157            }
158        }
159    }
160
161    fn is_balance_check_disabled(&self) -> bool {
162        cfg_if::cfg_if! {
163            if #[cfg(feature = "optional_balance_check")] {
164                self.disable_balance_check
165            } else {
166                false
167            }
168        }
169    }
170
171    fn is_gas_refund_disabled(&self) -> bool {
172        cfg_if::cfg_if! {
173            if #[cfg(feature = "optional_gas_refund")] {
174                self.disable_gas_refund
175            } else {
176                false
177            }
178        }
179    }
180
181    fn is_block_gas_limit_disabled(&self) -> bool {
182        cfg_if::cfg_if! {
183            if #[cfg(feature = "optional_block_gas_limit")] {
184                self.disable_block_gas_limit
185            } else {
186                false
187            }
188        }
189    }
190
191    fn is_nonce_check_disabled(&self) -> bool {
192        self.disable_nonce_check
193    }
194
195    fn is_base_fee_check_disabled(&self) -> bool {
196        cfg_if::cfg_if! {
197            if #[cfg(feature = "optional_no_base_fee")] {
198                self.disable_base_fee
199            } else {
200                false
201            }
202        }
203    }
204}
205
206impl<SPEC: Default> Default for CfgEnv<SPEC> {
207    fn default() -> Self {
208        Self {
209            chain_id: 1,
210            limit_contract_code_size: None,
211            spec: Default::default(),
212            disable_nonce_check: false,
213            blob_target_and_max_count: vec![(SpecId::CANCUN, 3, 6), (SpecId::PRAGUE, 6, 9)],
214            #[cfg(feature = "memory_limit")]
215            memory_limit: (1 << 32) - 1,
216            #[cfg(feature = "optional_balance_check")]
217            disable_balance_check: false,
218            #[cfg(feature = "optional_block_gas_limit")]
219            disable_block_gas_limit: false,
220            #[cfg(feature = "optional_eip3607")]
221            disable_eip3607: false,
222            #[cfg(feature = "optional_gas_refund")]
223            disable_gas_refund: false,
224            #[cfg(feature = "optional_no_base_fee")]
225            disable_base_fee: false,
226        }
227    }
228}
229
230#[cfg(test)]
231mod test {
232    use super::*;
233
234    #[test]
235    fn blob_max_and_target_count() {
236        let cfg: CfgEnv = Default::default();
237        assert_eq!(cfg.blob_max_count(SpecId::BERLIN), (6));
238        assert_eq!(cfg.blob_max_count(SpecId::CANCUN), (6));
239        assert_eq!(cfg.blob_max_count(SpecId::PRAGUE), (9));
240        assert_eq!(cfg.blob_max_count(SpecId::OSAKA), (9));
241    }
242}