Skip to main content

foundry_evm_core/evm/
eth.rs

1use super::*;
2
3type EthEvmHandler<'db, I> =
4    MainnetHandler<EthRevmEvm<'db, I>, EVMError<DatabaseError>, EthFrame<EthInterpreter>>;
5
6pub type EthRevmEvm<'db, I> = RevmEvm<
7    EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>,
8    I,
9    EthInstructions<EthInterpreter, EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>,
10    PrecompilesMap,
11    EthFrame<EthInterpreter>,
12>;
13
14pub struct EthFoundryEvm<
15    'db,
16    I: FoundryInspectorExt<EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>,
17> {
18    pub inner: EthRevmEvm<'db, I>,
19}
20
21impl<'db, I: FoundryInspectorExt<EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>> Evm
22    for EthFoundryEvm<'db, I>
23{
24    type Precompiles = PrecompilesMap;
25    type Inspector = I;
26    type DB = &'db mut dyn DatabaseExt<EthEvmFactory>;
27    type Error = EVMError<DatabaseError>;
28    type HaltReason = HaltReason;
29    type Spec = SpecId;
30    type Tx = TxEnv;
31    type BlockEnv = BlockEnv;
32
33    fn block(&self) -> &BlockEnv {
34        &self.inner.block
35    }
36
37    fn chain_id(&self) -> u64 {
38        self.inner.ctx.cfg.chain_id
39    }
40
41    fn components(&self) -> (&Self::DB, &Self::Inspector, &Self::Precompiles) {
42        (&self.inner.ctx.journaled_state.database, &self.inner.inspector, &self.inner.precompiles)
43    }
44
45    fn components_mut(&mut self) -> (&mut Self::DB, &mut Self::Inspector, &mut Self::Precompiles) {
46        (
47            &mut self.inner.ctx.journaled_state.database,
48            &mut self.inner.inspector,
49            &mut self.inner.precompiles,
50        )
51    }
52
53    fn set_inspector_enabled(&mut self, _enabled: bool) {
54        unimplemented!("FoundryEvm is always inspecting")
55    }
56
57    fn transact_raw(
58        &mut self,
59        tx: Self::Tx,
60    ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
61        self.inner.set_tx(tx);
62
63        let result = EthEvmHandler::<I>::default().inspect_run(&mut self.inner)?;
64
65        Ok(ResultAndState::new(result, self.inner.ctx.journaled_state.inner.state.clone()))
66    }
67
68    fn transact_system_call(
69        &mut self,
70        _caller: Address,
71        _contract: Address,
72        _data: Bytes,
73    ) -> Result<ExecResultAndState<ExecutionResult>, Self::Error> {
74        unimplemented!()
75    }
76
77    fn finish(self) -> (Self::DB, EvmEnv<Self::Spec>)
78    where
79        Self: Sized,
80    {
81        let Context { block: block_env, cfg: cfg_env, journaled_state, .. } = self.inner.ctx;
82
83        (journaled_state.database, EvmEnv { block_env, cfg_env })
84    }
85}
86
87impl<'db, I: FoundryInspectorExt<EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>> Deref
88    for EthFoundryEvm<'db, I>
89{
90    type Target = EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>;
91
92    fn deref(&self) -> &Self::Target {
93        &self.inner.ctx
94    }
95}
96
97impl<'db, I: FoundryInspectorExt<EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>> DerefMut
98    for EthFoundryEvm<'db, I>
99{
100    fn deref_mut(&mut self) -> &mut Self::Target {
101        &mut self.inner.ctx
102    }
103}
104
105impl FoundryEvmFactory for EthEvmFactory {
106    type FoundryContext<'db> = EthEvmContext<&'db mut dyn DatabaseExt<Self>>;
107
108    type FoundryEvm<'db, I: FoundryInspectorExt<Self::FoundryContext<'db>>> = EthFoundryEvm<'db, I>;
109
110    fn create_foundry_evm_with_inspector<'db, I: FoundryInspectorExt<Self::FoundryContext<'db>>>(
111        &self,
112        db: &'db mut dyn DatabaseExt<Self>,
113        evm_env: EvmEnv,
114        inspector: I,
115    ) -> Self::FoundryEvm<'db, I> {
116        let eth_evm = Self::default().create_evm_with_inspector(db, evm_env, inspector);
117        let mut inner = eth_evm.into_inner();
118        inner.ctx.cfg.tx_chain_id_check = true;
119
120        let mut evm = EthFoundryEvm { inner };
121        evm.inspector().get_networks().inject_precompiles(evm.precompiles_mut());
122        evm
123    }
124
125    fn create_foundry_nested_evm<'db>(
126        &self,
127        db: &'db mut dyn DatabaseExt<Self>,
128        evm_env: EvmEnv,
129        inspector: &'db mut dyn FoundryInspectorExt<Self::FoundryContext<'db>>,
130    ) -> Box<dyn NestedEvm<Spec = SpecId, Block = BlockEnv, Tx = TxEnv> + 'db> {
131        Box::new(self.create_foundry_evm_with_inspector(db, evm_env, inspector).inner)
132    }
133}
134
135impl<'db, I: FoundryInspectorExt<EthEvmContext<&'db mut dyn DatabaseExt<EthEvmFactory>>>> NestedEvm
136    for EthRevmEvm<'db, I>
137{
138    type Spec = SpecId;
139    type Block = BlockEnv;
140    type Tx = TxEnv;
141
142    fn journal_inner_mut(&mut self) -> &mut JournaledState {
143        &mut self.ctx_mut().journaled_state.inner
144    }
145
146    fn run_execution(&mut self, frame: FrameInput) -> Result<FrameResult, EVMError<DatabaseError>> {
147        let mut handler = EthEvmHandler::<I>::default();
148
149        // Create first frame
150        let memory =
151            SharedMemory::new_with_buffer(self.ctx().local().shared_memory_buffer().clone());
152        let first_frame_input = FrameInit { depth: 0, memory, frame_input: frame };
153
154        // Run execution loop
155        let mut frame_result = handler.inspect_run_exec_loop(self, first_frame_input)?;
156
157        // Handle last frame result
158        handler.last_frame_result(self, &mut frame_result)?;
159
160        Ok(frame_result)
161    }
162
163    fn transact_raw(
164        &mut self,
165        tx: Self::Tx,
166    ) -> Result<ResultAndState<HaltReason>, EVMError<DatabaseError>> {
167        self.set_tx(tx);
168
169        let result = EthEvmHandler::<I>::default().inspect_run(self)?;
170
171        Ok(ResultAndState::new(result, self.ctx.journaled_state.inner.state.clone()))
172    }
173
174    fn to_evm_env(&self) -> EvmEnv<Self::Spec, Self::Block> {
175        self.ctx_ref().evm_clone()
176    }
177}