Skip to main content

foundry_evm/executors/
builder.rs

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