foundry_evm/executors/
trace.rs

1use crate::executors::{Executor, ExecutorBuilder};
2use alloy_primitives::Address;
3use foundry_compilers::artifacts::EvmVersion;
4use foundry_config::{utils::evm_spec_id, Chain, Config};
5use foundry_evm_core::{backend::Backend, fork::CreateFork, opts::EvmOpts};
6use foundry_evm_traces::TraceMode;
7use revm::primitives::{Env, SpecId};
8use std::ops::{Deref, DerefMut};
9
10/// A default executor with tracing enabled
11pub struct TracingExecutor {
12    executor: Executor,
13}
14
15impl TracingExecutor {
16    pub fn new(
17        env: revm::primitives::Env,
18        fork: Option<CreateFork>,
19        version: Option<EvmVersion>,
20        trace_mode: TraceMode,
21        odyssey: bool,
22        create2_deployer: Address,
23    ) -> eyre::Result<Self> {
24        let db = Backend::spawn(fork)?;
25        Ok(Self {
26            // configures a bare version of the evm executor: no cheatcode inspector is enabled,
27            // tracing will be enabled only for the targeted transaction
28            executor: ExecutorBuilder::new()
29                .inspectors(|stack| {
30                    stack.trace_mode(trace_mode).odyssey(odyssey).create2_deployer(create2_deployer)
31                })
32                .spec_id(evm_spec_id(version.unwrap_or_default(), odyssey))
33                .build(env, db),
34        })
35    }
36
37    /// Returns the spec id of the executor
38    pub fn spec_id(&self) -> SpecId {
39        self.executor.spec_id()
40    }
41
42    /// uses the fork block number from the config
43    pub async fn get_fork_material(
44        config: &Config,
45        mut evm_opts: EvmOpts,
46    ) -> eyre::Result<(Env, Option<CreateFork>, Option<Chain>, bool)> {
47        evm_opts.fork_url = Some(config.get_rpc_url_or_localhost_http()?.into_owned());
48        evm_opts.fork_block_number = config.fork_block_number;
49
50        let env = evm_opts.evm_env().await?;
51
52        let fork = evm_opts.get_fork(config, env.clone());
53
54        Ok((env, fork, evm_opts.get_remote_chain_id().await, evm_opts.odyssey))
55    }
56}
57
58impl Deref for TracingExecutor {
59    type Target = Executor;
60
61    fn deref(&self) -> &Self::Target {
62        &self.executor
63    }
64}
65
66impl DerefMut for TracingExecutor {
67    fn deref_mut(&mut self) -> &mut Self::Target {
68        &mut self.executor
69    }
70}