revm_context/
cfg.rs

1//! This module contains [`CfgEnv`] and implements [`Cfg`] trait for it.
2pub use context_interface::Cfg;
3
4use primitives::{eip170::MAX_CODE_SIZE, 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, u64, u64)>,
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 base fee checks for EIP-1559 transactions
63    ///
64    /// This is useful for testing method calls with zero gas price.
65    ///
66    /// By default, it is set to `false`.
67    #[cfg(feature = "optional_no_base_fee")]
68    pub disable_base_fee: bool,
69}
70
71impl CfgEnv {
72    /// Creates new `CfgEnv` with default values.
73    pub fn new() -> Self {
74        Self::default()
75    }
76}
77
78impl<SPEC> CfgEnv<SPEC> {
79    /// Create new `CfgEnv` with default values and specified spec.
80    pub fn new_with_spec(spec: SPEC) -> Self {
81        Self {
82            chain_id: 1,
83            limit_contract_code_size: None,
84            spec,
85            disable_nonce_check: false,
86            blob_target_and_max_count: vec![(SpecId::CANCUN, 3, 6), (SpecId::PRAGUE, 6, 9)],
87            #[cfg(feature = "memory_limit")]
88            memory_limit: (1 << 32) - 1,
89            #[cfg(feature = "optional_balance_check")]
90            disable_balance_check: false,
91            #[cfg(feature = "optional_block_gas_limit")]
92            disable_block_gas_limit: false,
93            #[cfg(feature = "optional_eip3607")]
94            disable_eip3607: false,
95            #[cfg(feature = "optional_no_base_fee")]
96            disable_base_fee: false,
97        }
98    }
99
100    /// Consumes `self` and returns a new `CfgEnv` with the specified chain ID.
101    pub fn with_chain_id(mut self, chain_id: u64) -> Self {
102        self.chain_id = chain_id;
103        self
104    }
105
106    /// Consumes `self` and returns a new `CfgEnv` with the specified spec.
107    pub fn with_spec<OSPEC: Into<SpecId>>(self, spec: OSPEC) -> CfgEnv<OSPEC> {
108        CfgEnv {
109            chain_id: self.chain_id,
110            limit_contract_code_size: self.limit_contract_code_size,
111            spec,
112            disable_nonce_check: self.disable_nonce_check,
113            blob_target_and_max_count: self.blob_target_and_max_count,
114            #[cfg(feature = "memory_limit")]
115            memory_limit: self.memory_limit,
116            #[cfg(feature = "optional_balance_check")]
117            disable_balance_check: self.disable_balance_check,
118            #[cfg(feature = "optional_block_gas_limit")]
119            disable_block_gas_limit: self.disable_block_gas_limit,
120            #[cfg(feature = "optional_eip3607")]
121            disable_eip3607: self.disable_eip3607,
122            #[cfg(feature = "optional_no_base_fee")]
123            disable_base_fee: self.disable_base_fee,
124        }
125    }
126
127    /// Sets the blob target and max count over hardforks.
128    pub fn with_blob_max_and_target_count(mut self, blob_params: Vec<(SpecId, u64, u64)>) -> Self {
129        self.set_blob_max_and_target_count(blob_params);
130        self
131    }
132
133    /// Sets the blob target and max count over hardforks.
134    pub fn set_blob_max_and_target_count(&mut self, mut blob_params: Vec<(SpecId, u64, u64)>) {
135        blob_params.sort_by_key(|(id, _, _)| *id);
136        self.blob_target_and_max_count = blob_params;
137    }
138}
139
140impl<SPEC: Into<SpecId> + Copy> Cfg for CfgEnv<SPEC> {
141    type Spec = SPEC;
142
143    fn chain_id(&self) -> u64 {
144        self.chain_id
145    }
146
147    fn spec(&self) -> Self::Spec {
148        self.spec
149    }
150
151    #[inline]
152    fn blob_max_count(&self, spec_id: SpecId) -> u64 {
153        self.blob_target_and_max_count
154            .iter()
155            .rev()
156            .find_map(|(id, _, max)| {
157                if spec_id as u8 >= *id as u8 {
158                    return Some(*max);
159                }
160                None
161            })
162            .unwrap_or(6)
163    }
164
165    fn max_code_size(&self) -> usize {
166        self.limit_contract_code_size.unwrap_or(MAX_CODE_SIZE)
167    }
168
169    fn is_eip3607_disabled(&self) -> bool {
170        cfg_if::cfg_if! {
171            if #[cfg(feature = "optional_eip3607")] {
172                self.disable_eip3607
173            } else {
174                false
175            }
176        }
177    }
178
179    fn is_balance_check_disabled(&self) -> bool {
180        cfg_if::cfg_if! {
181            if #[cfg(feature = "optional_balance_check")] {
182                self.disable_balance_check
183            } else {
184                false
185            }
186        }
187    }
188
189    /// Returns `true` if the block gas limit is disabled.
190    fn is_block_gas_limit_disabled(&self) -> bool {
191        cfg_if::cfg_if! {
192            if #[cfg(feature = "optional_block_gas_limit")] {
193                self.disable_block_gas_limit
194            } else {
195                false
196            }
197        }
198    }
199
200    fn is_nonce_check_disabled(&self) -> bool {
201        self.disable_nonce_check
202    }
203
204    fn is_base_fee_check_disabled(&self) -> bool {
205        cfg_if::cfg_if! {
206            if #[cfg(feature = "optional_no_base_fee")] {
207                self.disable_base_fee
208            } else {
209                false
210            }
211        }
212    }
213}
214
215impl<SPEC: Default> Default for CfgEnv<SPEC> {
216    fn default() -> Self {
217        Self::new_with_spec(SPEC::default())
218    }
219}
220
221#[cfg(test)]
222mod test {
223    use super::*;
224
225    #[test]
226    fn blob_max_and_target_count() {
227        let cfg: CfgEnv = Default::default();
228        assert_eq!(cfg.blob_max_count(SpecId::BERLIN), (6));
229        assert_eq!(cfg.blob_max_count(SpecId::CANCUN), (6));
230        assert_eq!(cfg.blob_max_count(SpecId::PRAGUE), (9));
231        assert_eq!(cfg.blob_max_count(SpecId::OSAKA), (9));
232    }
233}