foundry_evm/executors/
builder.rs

1use crate::{executors::Executor, inspectors::InspectorStackBuilder};
2use foundry_evm_core::backend::Backend;
3use revm::primitives::{Env, EnvWithHandlerCfg, SpecId};
4
5/// The builder that allows to configure an evm [`Executor`] which a stack of optional
6/// [`revm::Inspector`]s, such as [`Cheatcodes`].
7///
8/// By default, the [`Executor`] will be configured with an empty [`InspectorStack`].
9///
10/// [`Cheatcodes`]: super::Cheatcodes
11/// [`InspectorStack`]: super::InspectorStack
12#[derive(Clone, Debug)]
13#[must_use = "builders do nothing unless you call `build` on them"]
14pub struct ExecutorBuilder {
15    /// The configuration used to build an `InspectorStack`.
16    stack: InspectorStackBuilder,
17    /// The gas limit.
18    gas_limit: Option<u64>,
19    /// The spec ID.
20    spec_id: SpecId,
21    legacy_assertions: bool,
22}
23
24impl Default for ExecutorBuilder {
25    #[inline]
26    fn default() -> Self {
27        Self {
28            stack: InspectorStackBuilder::new(),
29            gas_limit: None,
30            spec_id: SpecId::LATEST,
31            legacy_assertions: false,
32        }
33    }
34}
35
36impl ExecutorBuilder {
37    /// Create a new executor builder.
38    #[inline]
39    pub fn new() -> Self {
40        Self::default()
41    }
42
43    /// Modify the inspector stack.
44    #[inline]
45    pub fn inspectors(
46        mut self,
47        f: impl FnOnce(InspectorStackBuilder) -> InspectorStackBuilder,
48    ) -> Self {
49        self.stack = f(self.stack);
50        self
51    }
52
53    /// Sets the EVM spec to use.
54    #[inline]
55    pub fn spec_id(mut self, spec: SpecId) -> Self {
56        self.spec_id = spec;
57        self
58    }
59
60    /// Sets the executor gas limit.
61    #[inline]
62    pub fn gas_limit(mut self, gas_limit: u64) -> Self {
63        self.gas_limit = Some(gas_limit);
64        self
65    }
66
67    /// Sets the `legacy_assertions` flag.
68    #[inline]
69    pub fn legacy_assertions(mut self, legacy_assertions: bool) -> Self {
70        self.legacy_assertions = legacy_assertions;
71        self
72    }
73
74    /// Builds the executor as configured.
75    #[inline]
76    pub fn build(self, env: Env, db: Backend) -> Executor {
77        let Self { mut stack, gas_limit, spec_id, legacy_assertions } = self;
78        if stack.block.is_none() {
79            stack.block = Some(env.block.clone());
80        }
81        if stack.gas_price.is_none() {
82            stack.gas_price = Some(env.tx.gas_price);
83        }
84        let gas_limit = gas_limit.unwrap_or_else(|| env.block.gas_limit.saturating_to());
85        let env = EnvWithHandlerCfg::new_with_spec_id(Box::new(env), spec_id);
86        Executor::new(db, env, stack.build(), gas_limit, legacy_assertions)
87    }
88}