foundry_evm_core/evm/
eth.rs1use 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 chain_id = evm_env.cfg_env.chain_id;
49 let timestamp = evm_env.block_env.timestamp.saturating_to();
50 let mut eth_evm = Self::default().create_evm_with_inspector(db, evm_env, inspector);
51 eth_evm.cfg.tx_chain_id_check = true;
52 let networks = eth_evm.inspector().get_networks();
53 networks.inject_precompiles(eth_evm.precompiles_mut());
54 networks.inject_chain_precompiles(eth_evm.precompiles_mut(), chain_id, timestamp);
55 eth_evm
56 }
57
58 fn create_foundry_nested_evm<'db>(
59 &self,
60 db: &'db mut dyn DatabaseExt<Self>,
61 evm_env: EvmEnv,
62 inspector: &'db mut dyn FoundryInspectorExt<Self::FoundryContext<'db>>,
63 ) -> Box<dyn NestedEvm<Spec = SpecId, Block = BlockEnv, Tx = TxEnv> + 'db> {
64 Box::new(self.create_foundry_evm_with_inspector(db, evm_env, inspector).into_inner())
65 }
66}
67
68impl<'db, I: FoundryInspectorExt<EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>> NestedEvm
69 for EthRevmEvm<'db, I>
70{
71 type Spec = SpecId;
72 type Block = BlockEnv;
73 type Tx = TxEnv;
74
75 fn journal_inner_mut(&mut self) -> &mut JournaledState {
76 &mut self.ctx_mut().journaled_state.inner
77 }
78
79 fn run_execution(&mut self, frame: FrameInput) -> Result<FrameResult, EVMError<DatabaseError>> {
80 let mut handler = EthEvmHandler::<I>::default();
81 let reservoir = frame.reservoir();
82
83 let memory =
85 SharedMemory::new_with_buffer(self.ctx_ref().local().shared_memory_buffer().clone());
86 let first_frame_input = FrameInit { depth: 0, memory, frame_input: frame };
87
88 let mut frame_result = handler.inspect_run_exec_loop(self, first_frame_input)?;
90
91 handler.last_frame_result(self, reservoir, &mut frame_result)?;
93
94 Ok(frame_result)
95 }
96
97 fn transact_raw(&mut self, tx: Self::Tx) -> Result<ResultAndState, EVMError<DatabaseError>> {
98 self.set_tx(tx);
99
100 let result = EthEvmHandler::<I>::default().inspect_run(self)?;
101
102 Ok(ResultAndState::new(result, self.ctx.journaled_state.inner.state.clone()))
103 }
104
105 fn to_evm_env(&self) -> EvmEnv<Self::Spec, Self::Block> {
106 self.ctx_ref().evm_clone()
107 }
108}