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 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}