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.