foundry_evm_core/evm/
eth.rs1use alloy_evm::{
2 EthEvm, EthEvmFactory, Evm, EvmEnv, EvmFactory, eth::EthEvmContext, precompiles::PrecompilesMap,
3};
4use alloy_network::Ethereum;
5use foundry_evm_networks::apply_bsc_p256_precompile;
6use foundry_fork_db::DatabaseError;
7use revm::{
8 context::{
9 BlockEnv, Evm as RevmEvm, Journal, TxEnv,
10 result::{EVMError, HaltReason, ResultAndState},
11 },
12 handler::{EthFrame, EvmTr, FrameResult, MainnetHandler, instructions::EthInstructions},
13 inspector::InspectorHandler,
14 interpreter::{FrameInput, InstructionResult, interpreter::EthInterpreter},
15 primitives::hardfork::SpecId,
16};
17
18use crate::{
19 FoundryContextExt, FoundryInspectorExt,
20 backend::{DatabaseExt, JournaledState},
21 evm::{
22 FoundryEvmFactory, FoundryEvmNetwork, IntoInstructionResult, NestedEvm, NestedEvmFor,
23 run_inspected_frame,
24 },
25};
26
27#[derive(Clone, Copy, Debug, Default)]
28pub struct EthEvmNetwork;
29impl FoundryEvmNetwork for EthEvmNetwork {
30 type Network = Ethereum;
31 type EvmFactory = EthEvmFactory;
32}
33
34type EthEvmHandler<'db, I> = MainnetHandler<EthRevmEvm<'db, I>, EVMError<DatabaseError>, EthFrame>;
35
36pub type EthRevmEvm<'db, I> = RevmEvm<
37 EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>,
38 I,
39 EthInstructions<EthInterpreter, EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>,
40 PrecompilesMap,
41 EthFrame,
42>;
43
44impl IntoInstructionResult for HaltReason {
45 fn into_instruction_result(self) -> InstructionResult {
46 self.into()
47 }
48}
49
50impl FoundryEvmFactory for EthEvmFactory {
51 type Chain = ();
52 type FoundryContext<'db> = EthEvmContext<&'db mut dyn DatabaseExt<Self>>;
53
54 type FoundryEvm<'db, I: FoundryInspectorExt<Self::FoundryContext<'db>>> =
55 EthEvm<&'db mut dyn DatabaseExt<Self>, I, Self::Precompiles>;
56
57 fn create_foundry_evm_with_inspector<'db, I: FoundryInspectorExt<Self::FoundryContext<'db>>>(
58 &self,
59 db: &'db mut dyn DatabaseExt<Self>,
60 evm_env: EvmEnv,
61 inspector: I,
62 ) -> Self::FoundryEvm<'db, I> {
63 let chain_id = evm_env.cfg_env.chain_id;
64 let timestamp = evm_env.block_env.timestamp.saturating_to();
65 let mut eth_evm = Self::default().create_evm_with_inspector(db, evm_env, inspector);
66 eth_evm.cfg.tx_chain_id_check = true;
67 let networks = eth_evm.inspector().get_networks();
68 networks.inject_precompiles(eth_evm.precompiles_mut());
69 apply_bsc_p256_precompile(eth_evm.precompiles_mut(), chain_id, timestamp);
70 eth_evm
71 }
72
73 fn create_nested_evm_with_inspector<'db, I>(
74 &self,
75 db: &'db mut dyn DatabaseExt<Self>,
76 evm_env: EvmEnv,
77 inspector: I,
78 ) -> NestedEvmFor<'db, Self>
79 where
80 I: FoundryInspectorExt<Self::FoundryContext<'db>> + 'db,
81 {
82 Box::new(self.create_foundry_evm_with_inspector(db, evm_env, inspector).into_inner())
83 }
84}
85
86impl<'db, I: FoundryInspectorExt<EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>> NestedEvm
87 for EthRevmEvm<'db, I>
88{
89 type Spec = SpecId;
90 type Block = BlockEnv;
91 type Tx = TxEnv;
92 type Chain = ();
93 type Journal = Journal<&'db mut dyn DatabaseExt<EthEvmFactory>>;
94
95 fn tx_mut(&mut self) -> &mut Self::Tx {
96 self.ctx_mut().tx_mut()
97 }
98
99 fn journal_inner_mut(&mut self) -> &mut JournaledState {
100 &mut self.ctx_mut().journaled_state.inner
101 }
102
103 fn chain_mut(&mut self) -> &mut Self::Chain {
104 &mut self.ctx_mut().chain
105 }
106
107 fn precompiles_mut(&mut self) -> &mut alloy_evm::precompiles::PrecompilesMap {
108 &mut self.precompiles
109 }
110
111 fn journal_mut(&mut self) -> &mut Self::Journal {
112 &mut self.ctx_mut().journaled_state
113 }
114
115 fn run_execution(&mut self, frame: FrameInput) -> Result<FrameResult, EVMError<DatabaseError>> {
116 run_inspected_frame(self, EthEvmHandler::<I>::default(), frame)
117 }
118
119 fn transact_raw(&mut self, tx: Self::Tx) -> eyre::Result<ResultAndState> {
120 self.set_tx(tx);
121
122 let result = EthEvmHandler::<I>::default().inspect_run(self)?;
123
124 Ok(ResultAndState::new(result, self.ctx.journaled_state.inner.state.clone()))
125 }
126
127 fn to_evm_env(&self) -> EvmEnv<Self::Spec, Self::Block> {
128 self.ctx_ref().evm_clone()
129 }
130}