Skip to main content

foundry_evm_core/evm/
eth.rs

1use alloy_evm::{
2    EthEvm, EthEvmFactory, Evm, EvmEnv, EvmFactory, eth::EthEvmContext, precompiles::PrecompilesMap,
3};
4use foundry_fork_db::DatabaseError;
5use revm::{
6    context::{
7        BlockEnv, ContextTr, Evm as RevmEvm, LocalContextTr, TxEnv,
8        result::{EVMError, ResultAndState},
9    },
10    handler::{
11        EthFrame, EvmTr, FrameResult, Handler, MainnetHandler, instructions::EthInstructions,
12    },
13    inspector::InspectorHandler,
14    interpreter::{
15        FrameInput, SharedMemory, interpreter::EthInterpreter, interpreter_action::FrameInit,
16    },
17    primitives::hardfork::SpecId,
18};
19
20use crate::{
21    FoundryContextExt, FoundryInspectorExt,
22    backend::{DatabaseExt, JournaledState},
23    evm::{FoundryEvmFactory, NestedEvm},
24};
25
26type EthEvmHandler<'db, I> = MainnetHandler<EthRevmEvm<'db, I>, EVMError<DatabaseError>, EthFrame>;
27
28pub type EthRevmEvm<'db, I> = RevmEvm<
29    EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>,
30    I,
31    EthInstructions<EthInterpreter, EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>,
32    PrecompilesMap,
33    EthFrame,
34>;
35
36impl FoundryEvmFactory for EthEvmFactory {
37    type FoundryContext<'db> = EthEvmContext<&'db mut dyn DatabaseExt<Self>>;
38
39    type FoundryEvm<'db, I: FoundryInspectorExt<Self::FoundryContext<'db>>> =
40        EthEvm<&'db mut dyn DatabaseExt<Self>, I, Self::Precompiles>;
41
42    fn create_foundry_evm_with_inspector<'db, I: FoundryInspectorExt<Self::FoundryContext<'db>>>(
43        &self,
44        db: &'db mut dyn DatabaseExt<Self>,
45        evm_env: EvmEnv,
46        inspector: I,
47    ) -> Self::FoundryEvm<'db, I> {
48        let mut eth_evm = Self::default().create_evm_with_inspector(db, evm_env, inspector);
49        eth_evm.cfg.tx_chain_id_check = true;
50        eth_evm.inspector().get_networks().inject_precompiles(eth_evm.precompiles_mut());
51        eth_evm
52    }
53
54    fn create_foundry_nested_evm<'db>(
55        &self,
56        db: &'db mut dyn DatabaseExt<Self>,
57        evm_env: EvmEnv,
58        inspector: &'db mut dyn FoundryInspectorExt<Self::FoundryContext<'db>>,
59    ) -> Box<dyn NestedEvm<Spec = SpecId, Block = BlockEnv, Tx = TxEnv> + 'db> {
60        Box::new(self.create_foundry_evm_with_inspector(db, evm_env, inspector).into_inner())
61    }
62}
63
64impl<'db, I: FoundryInspectorExt<EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>> NestedEvm
65    for EthRevmEvm<'db, I>
66{
67    type Spec = SpecId;
68    type Block = BlockEnv;
69    type Tx = TxEnv;
70
71    fn journal_inner_mut(&mut self) -> &mut JournaledState {
72        &mut self.ctx_mut().journaled_state.inner
73    }
74
75    fn run_execution(&mut self, frame: FrameInput) -> Result<FrameResult, EVMError<DatabaseError>> {
76        let mut handler = EthEvmHandler::<I>::default();
77
78        // Create first frame
79        let memory =
80            SharedMemory::new_with_buffer(self.ctx_ref().local().shared_memory_buffer().clone());
81        let first_frame_input = FrameInit { depth: 0, memory, frame_input: frame };
82
83        // Run execution loop
84        let mut frame_result = handler.inspect_run_exec_loop(self, first_frame_input)?;
85
86        // Handle last frame result
87        handler.last_frame_result(self, &mut frame_result)?;
88
89        Ok(frame_result)
90    }
91
92    fn transact_raw(&mut self, tx: Self::Tx) -> Result<ResultAndState, EVMError<DatabaseError>> {
93        self.set_tx(tx);
94
95        let result = EthEvmHandler::<I>::default().inspect_run(self)?;
96
97        Ok(ResultAndState::new(result, self.ctx.journaled_state.inner.state.clone()))
98    }
99
100    fn to_evm_env(&self) -> EvmEnv<Self::Spec, Self::Block> {
101        self.ctx_ref().evm_clone()
102    }
103}