Skip to main content

foundry_evm/executors/
trace.rs

1use crate::{
2    Env,
3    executors::{Executor, ExecutorBuilder},
4};
5use alloy_primitives::{Address, U256, map::HashMap};
6use alloy_rpc_types::state::StateOverride;
7use eyre::Context;
8use foundry_compilers::artifacts::EvmVersion;
9use foundry_config::{Chain, Config, utils::evm_spec_id};
10use foundry_evm_core::{backend::Backend, fork::CreateFork, opts::EvmOpts};
11use foundry_evm_traces::TraceMode;
12use revm::{primitives::hardfork::SpecId, state::Bytecode};
13use std::ops::{Deref, DerefMut};
14
15use super::ExecutorStrategy;
16
17/// A default executor with tracing enabled
18pub struct TracingExecutor {
19    executor: Executor,
20}
21
22impl TracingExecutor {
23    #[allow(clippy::too_many_arguments)]
24    pub fn new(
25        env: Env,
26        fork: Option<CreateFork>,
27        version: Option<EvmVersion>,
28        trace_mode: TraceMode,
29        odyssey: bool,
30        create2_deployer: Address,
31        state_overrides: Option<StateOverride>,
32        strategy: ExecutorStrategy,
33    ) -> eyre::Result<Self> {
34        let db =
35            Backend::spawn(fork, strategy.runner.new_backend_strategy(strategy.context.as_ref()))?;
36        // configures a bare version of the evm executor: no cheatcode inspector is enabled,
37        // tracing will be enabled only for the targeted transaction
38        let mut executor = ExecutorBuilder::new()
39            .inspectors(|stack| {
40                stack.trace_mode(trace_mode).odyssey(odyssey).create2_deployer(create2_deployer)
41            })
42            .spec_id(evm_spec_id(version.unwrap_or_default(), odyssey))
43            .build(env, db, strategy);
44
45        // Apply the state overrides.
46        if let Some(state_overrides) = state_overrides {
47            for (address, overrides) in state_overrides {
48                if let Some(balance) = overrides.balance {
49                    executor.set_balance(address, balance)?;
50                }
51                if let Some(nonce) = overrides.nonce {
52                    executor.set_nonce(address, nonce)?;
53                }
54                if let Some(code) = overrides.code {
55                    let bytecode = Bytecode::new_raw_checked(code)
56                        .wrap_err("invalid bytecode in state override")?;
57                    executor.set_code(address, bytecode)?;
58                }
59                if let Some(state) = overrides.state {
60                    let state: HashMap<U256, U256> = state
61                        .into_iter()
62                        .map(|(slot, value)| (slot.into(), value.into()))
63                        .collect();
64                    executor.set_storage(address, state)?;
65                }
66                if let Some(state_diff) = overrides.state_diff {
67                    for (slot, value) in state_diff {
68                        executor.set_storage_slot(address, slot.into(), value.into())?;
69                    }
70                }
71            }
72        }
73
74        Ok(Self { executor })
75    }
76
77    /// Returns the spec id of the executor
78    pub fn spec_id(&self) -> SpecId {
79        self.executor.spec_id()
80    }
81
82    /// uses the fork block number from the config
83    pub async fn get_fork_material(
84        config: &Config,
85        mut evm_opts: EvmOpts,
86    ) -> eyre::Result<(Env, Option<CreateFork>, Option<Chain>, bool)> {
87        evm_opts.fork_url = Some(config.get_rpc_url_or_localhost_http()?.into_owned());
88        evm_opts.fork_block_number = config.fork_block_number;
89
90        let env = evm_opts.evm_env().await?;
91
92        let fork = evm_opts.get_fork(config, env.clone());
93
94        Ok((env, fork, evm_opts.get_remote_chain_id().await, evm_opts.odyssey))
95    }
96}
97
98impl Deref for TracingExecutor {
99    type Target = Executor;
100
101    fn deref(&self) -> &Self::Target {
102        &self.executor
103    }
104}
105
106impl DerefMut for TracingExecutor {
107    fn deref_mut(&mut self) -> &mut Self::Target {
108        &mut self.executor
109    }
110}