trevm/evm/
has_cfg.rs

1use crate::{helpers::Ctx, Cfg, EvmErrored, HasCfg, Trevm};
2use revm::{context::ContextTr, Database, Inspector};
3
4impl<Db, Insp, TrevmState> Trevm<Db, Insp, TrevmState>
5where
6    Db: Database,
7    Insp: Inspector<Ctx<Db>>,
8    TrevmState: HasCfg,
9{
10    /// Set the [EIP-170] contract code size limit. By default this is set to
11    /// 0x6000 bytes (~25KiB). Contracts whose bytecode is larger than this
12    /// limit cannot be deployed and will produce a [`CreateInitCodeSizeLimit`]
13    /// error.
14    ///
15    /// [`CreateInitCodeSizeLimit`]: revm::context::result::InvalidTransaction::CreateInitCodeSizeLimit
16    /// [`Eip-170`]: https://eips.ethereum.org/EIPS/eip-170
17    pub fn set_code_size_limit(&mut self, limit: usize) -> Option<usize> {
18        let mut csl = None;
19        self.inner.ctx.modify_cfg(|cfg| {
20            csl = cfg.limit_contract_code_size.replace(limit);
21        });
22        csl
23    }
24
25    /// Disable the [EIP-170] contract code size limit, returning the previous
26    /// setting.
27    ///
28    /// [`Eip-170`]: https://eips.ethereum.org/EIPS/eip-170
29    pub fn disable_code_size_limit(&mut self) -> Option<usize> {
30        let mut csl = None;
31        self.inner.ctx.modify_cfg(|cfg| csl = cfg.limit_contract_code_size.take());
32        csl
33    }
34
35    /// Run a closure with the code size limit disabled, then restore the
36    /// previous setting.
37    pub fn without_code_size_limit<F, NewState: HasCfg>(mut self, f: F) -> Trevm<Db, Insp, NewState>
38    where
39        F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
40    {
41        let limit = self.disable_code_size_limit();
42        let mut new = f(self);
43        if let Some(limit) = limit {
44            new.set_code_size_limit(limit);
45        }
46        new
47    }
48
49    /// Set the [EIP-170] contract code size limit to the default value of
50    /// 0x6000 bytes (~25KiB), returning the previous setting. Contracts whose
51    /// bytecode is larger than this limit cannot be deployed and will produce
52    /// a [`CreateInitCodeSizeLimit`] error.
53    ///
54    /// [`CreateInitCodeSizeLimit`]: revm::context::result::InvalidTransaction::CreateInitCodeSizeLimit
55    /// [`Eip-170`]: https://eips.ethereum.org/EIPS/eip-170
56    pub fn set_default_code_size_limit(&mut self) -> Option<usize> {
57        self.set_code_size_limit(0x6000)
58    }
59
60    /// Disable the [EIP-155] chain ID check.
61    ///
62    /// [`EIP-155`]: https://eips.ethereum.org/EIPS/eip-155
63    pub fn disable_chain_id_check(&mut self) {
64        self.inner.ctx.modify_cfg(|cfg| cfg.tx_chain_id_check = false);
65    }
66
67    /// Enable the [EIP-155] chain ID check.
68    ///
69    /// [`EIP-155`]: https://eips.ethereum.org/EIPS/eip-155
70    pub fn enable_chain_id_check(&mut self) {
71        self.inner.ctx.modify_cfg(|cfg| cfg.tx_chain_id_check = true);
72    }
73
74    /// Run a closure with the chain ID check disabled, then restore the previous
75    /// setting.
76    ///
77    /// [`EIP-155`]: https://eips.ethereum.org/EIPS/eip-155
78    pub fn without_chain_id_check<F, NewState: HasCfg>(mut self, f: F) -> Trevm<Db, Insp, NewState>
79    where
80        F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
81    {
82        let previous = self.inner.cfg().tx_chain_id_check;
83        self.disable_chain_id_check();
84        let mut new = f(self);
85        new.inner.ctx.modify_cfg(|cfg| cfg.tx_chain_id_check = previous);
86        new
87    }
88
89    /// Run a function with the provided configuration, then restore the
90    /// previous configuration. This will not affect the block and tx, if those
91    /// have been filled.
92    pub fn with_cfg<C, F, NewState>(mut self, cfg: &C, f: F) -> Trevm<Db, Insp, NewState>
93    where
94        C: Cfg,
95        F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
96        NewState: HasCfg,
97    {
98        let previous = self.inner.cfg().clone();
99        cfg.fill_cfg(&mut self.inner);
100
101        let mut this = f(self);
102        this.inner.ctx.modify_cfg(|cfg| *cfg = previous);
103        this
104    }
105
106    /// Run a fallible function with the provided configuration, then restore the
107    /// previous configuration. This will not affect the block and tx, if those
108    /// have been filled.
109    pub fn try_with_cfg<C, F, NewState, E>(
110        mut self,
111        cfg: &C,
112        f: F,
113    ) -> Result<Trevm<Db, Insp, NewState>, EvmErrored<Db, Insp, E>>
114    where
115        C: Cfg,
116        F: FnOnce(Self) -> Result<Trevm<Db, Insp, NewState>, EvmErrored<Db, Insp, E>>,
117        NewState: HasCfg,
118    {
119        let previous = self.inner.cfg().clone();
120        cfg.fill_cfg(&mut self.inner);
121
122        match f(self) {
123            Ok(mut evm) => {
124                evm.inner.modify_cfg(|cfg| *cfg = previous);
125                Ok(evm)
126            }
127            Err(mut evm) => {
128                evm.inner.modify_cfg(|cfg| *cfg = previous);
129                Err(evm)
130            }
131        }
132    }
133
134    /// Set a limit beyond which a callframe's memory cannot be resized.
135    /// Attempting to resize beyond this limit will result in a
136    /// [OutOfGasError::Memory] error.
137    ///
138    /// In cases where the gas limit may be extraordinarily high, it is
139    /// recommended to set this to a sane value to prevent memory allocation
140    /// panics. Defaults to `2^32 - 1` bytes per EIP-1985.
141    ///
142    /// [OutOfGasError::Memory]: revm::context::result::OutOfGasError::Memory
143    #[cfg(feature = "memory_limit")]
144    pub fn set_memory_limit(&mut self, new_limit: u64) -> u64 {
145        let mut ml = 0;
146        self.inner.ctx.modify_cfg(|cfg| ml = core::mem::replace(&mut cfg.memory_limit, new_limit));
147        ml
148    }
149
150    /// Disable balance checks. If the sender does not have enough balance to
151    /// cover the transaction, the sender will be given enough ether to ensure
152    /// execution doesn't fail.
153    #[cfg(feature = "optional_balance_check")]
154    pub fn disable_balance_check(&mut self) {
155        self.inner.ctx.modify_cfg(|cfg| cfg.disable_balance_check = true)
156    }
157
158    /// Enable balance checks. See [`Self::disable_balance_check`].
159    #[cfg(feature = "optional_balance_check")]
160    pub fn enable_balance_check(&mut self) {
161        self.inner.ctx.modify_cfg(|cfg| cfg.disable_balance_check = false)
162    }
163
164    /// Run a closure with balance checks disabled, then restore the previous
165    /// setting.
166    #[cfg(feature = "optional_balance_check")]
167    pub fn without_balance_check<F, NewState: HasCfg>(mut self, f: F) -> Trevm<Db, Insp, NewState>
168    where
169        F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
170    {
171        let previous = self.inner.cfg().disable_balance_check;
172        self.disable_balance_check();
173        let mut new = f(self);
174        new.inner.ctx.modify_cfg(|cfg| cfg.disable_balance_check = previous);
175        new
176    }
177
178    /// Disable block gas limits. This allows transactions to execute even if
179    /// they gas needs exceed the block gas limit. This is useful for
180    /// simulating large transactions like forge scripts.
181    #[cfg(feature = "optional_block_gas_limit")]
182    pub fn disable_block_gas_limit(&mut self) {
183        self.inner.ctx.modify_cfg(|cfg| cfg.disable_block_gas_limit = true);
184    }
185
186    /// Enable block gas limits. See [`Self::disable_block_gas_limit`].
187    #[cfg(feature = "optional_block_gas_limit")]
188    pub fn enable_block_gas_limit(&mut self) {
189        self.inner.ctx.modify_cfg(|cfg| cfg.disable_block_gas_limit = false);
190    }
191
192    /// Run a closure with block gas limits disabled, then restore the previous
193    /// setting.
194    #[cfg(feature = "optional_block_gas_limit")]
195    pub fn without_block_gas_limit<F, NewState: HasCfg>(mut self, f: F) -> Trevm<Db, Insp, NewState>
196    where
197        F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
198    {
199        let previous = self.inner.cfg().disable_block_gas_limit;
200        self.disable_block_gas_limit();
201        let mut new = f(self);
202        new.inner.ctx.modify_cfg(|cfg| cfg.disable_block_gas_limit = previous);
203        new
204    }
205
206    /// Disable [EIP-3607]. This allows transactions to originate from accounts
207    /// that contain code. This is useful for simulating smart-contract calls.
208    ///
209    /// [EIP-3607]: https://eips.ethereum.org/EIPS/eip-3607
210    #[cfg(feature = "optional_eip3607")]
211    pub fn disable_eip3607(&mut self) {
212        self.inner.ctx.modify_cfg(|cfg| cfg.disable_eip3607 = true);
213    }
214
215    /// Enable [EIP-3607]. See [`Self::disable_eip3607`].
216    ///
217    /// [EIP-3607]: https://eips.ethereum.org/EIPS/eip-3607
218    #[cfg(feature = "optional_eip3607")]
219    pub fn enable_eip3607(&mut self) {
220        self.inner.ctx.modify_cfg(|cfg| cfg.disable_eip3607 = false);
221    }
222
223    /// Run a closure with [EIP-3607] disabled, then restore the previous
224    /// setting.
225    #[cfg(feature = "optional_eip3607")]
226    pub fn without_eip3607<F, NewState: HasCfg>(mut self, f: F) -> Trevm<Db, Insp, NewState>
227    where
228        F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
229    {
230        let previous = self.inner.cfg().disable_eip3607;
231        self.disable_eip3607();
232
233        let mut new = f(self);
234        new.inner.ctx.modify_cfg(|cfg| cfg.disable_eip3607 = previous);
235        new
236    }
237
238    /// Disables [EIP-1559] base fee checks. This is useful for testing method
239    /// calls with zero gas price.
240    ///
241    /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
242    #[cfg(feature = "optional_no_base_fee")]
243    pub fn disable_base_fee(&mut self) {
244        self.inner.ctx.modify_cfg(|cfg| cfg.disable_base_fee = true)
245    }
246
247    /// Enable [EIP-1559] base fee checks. See [`Self::disable_base_fee`].
248    ///
249    /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
250    #[cfg(feature = "optional_no_base_fee")]
251    pub fn enable_base_fee(&mut self) {
252        self.inner.ctx.modify_cfg(|cfg| cfg.disable_base_fee = false)
253    }
254
255    /// Run a closure with [EIP-1559] base fee checks disabled, then restore the
256    /// previous setting.
257    ///
258    /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
259    #[cfg(feature = "optional_no_base_fee")]
260    pub fn without_base_fee<F, NewState: HasCfg>(mut self, f: F) -> Trevm<Db, Insp, NewState>
261    where
262        F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
263    {
264        let previous = self.inner.cfg().disable_base_fee;
265        self.disable_base_fee();
266
267        let mut new = f(self);
268        new.inner.ctx.modify_cfg(|cfg| cfg.disable_base_fee = previous);
269        new
270    }
271
272    /// Disable nonce checks. This allows transactions to be sent with
273    /// incorrect nonces, and is useful for things like system transactions.
274    pub fn disable_nonce_check(&mut self) {
275        self.inner.ctx.modify_cfg(|cfg| cfg.disable_nonce_check = true)
276    }
277
278    /// Enable nonce checks. See [`Self::disable_nonce_check`].
279    pub fn enable_nonce_check(&mut self) {
280        self.inner.ctx.modify_cfg(|cfg| cfg.disable_nonce_check = false)
281    }
282
283    /// Run a closure with nonce checks disabled, then restore the previous
284    /// setting. This will not affect the block and tx, if those have been
285    /// filled.
286    pub fn without_nonce_check<F, NewState: HasCfg>(mut self, f: F) -> Trevm<Db, Insp, NewState>
287    where
288        F: FnOnce(Self) -> Trevm<Db, Insp, NewState>,
289    {
290        let previous = self.inner.cfg().disable_nonce_check;
291        self.disable_nonce_check();
292
293        let mut new = f(self);
294        new.inner.ctx.modify_cfg(|cfg| cfg.disable_nonce_check = previous);
295        new
296    }
297}
298
299// Some code above and documentation is adapted from the revm crate, and is
300// reproduced here under the terms of the MIT license.
301//
302// MIT License
303//
304// Copyright (c) 2021-2024 draganrakita
305//
306// Permission is hereby granted, free of charge, to any person obtaining a copy
307// of this software and associated documentation files (the "Software"), to deal
308// in the Software without restriction, including without limitation the rights
309// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
310// copies of the Software, and to permit persons to whom the Software is
311// furnished to do so, subject to the following conditions:
312//
313// The above copyright notice and this permission notice shall be included in all
314// copies or substantial portions of the Software.
315//
316// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
317// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
318// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
319// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
320// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
321// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
322// SOFTWARE.
323
324// Some code above is reproduced from `reth`. It is reused here under the MIT
325// license.
326//
327// The MIT License (MIT)
328//
329// Copyright (c) 2022-2024 Reth Contributors
330//
331// Permission is hereby granted, free of charge, to any person obtaining a copy
332// of this software and associated documentation files (the "Software"), to deal
333// in the Software without restriction, including without limitation the rights
334// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
335// copies of the Software, and to permit persons to whom the Software is
336// furnished to do so, subject to the following conditions:
337//
338// The above copyright notice and this permission notice shall be included in
339// all copies or substantial portions of the Software.
340//
341// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
342// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
343// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
344// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
345// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
346// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
347// THE SOFTWARE.