1use super::*;
2
3type OpEvmHandler<'db, I> = OpHandler<
4 OpRevmEvm<'db, I>,
5 EVMError<DatabaseError, OpTransactionError>,
6 EthFrame<EthInterpreter>,
7>;
8
9pub type OpRevmEvm<'db, I> = op_revm::OpEvm<
10 OpContext<&'db mut dyn DatabaseExt<OpEvmFactory>>,
11 I,
12 EthInstructions<EthInterpreter, OpContext<&'db mut dyn DatabaseExt<OpEvmFactory>>>,
13 PrecompilesMap,
14>;
15
16pub struct OpFoundryEvm<
19 'db,
20 I: FoundryInspectorExt<OpContext<&'db mut dyn DatabaseExt<OpEvmFactory>>>,
21> {
22 pub inner: OpRevmEvm<'db, I>,
23}
24
25impl FoundryEvmFactory for OpEvmFactory {
26 type FoundryContext<'db> = OpContext<&'db mut dyn DatabaseExt<Self>>;
27
28 type FoundryEvm<'db, I: FoundryInspectorExt<Self::FoundryContext<'db>>> = OpFoundryEvm<'db, I>;
29
30 fn create_foundry_evm_with_inspector<'db, I: FoundryInspectorExt<Self::FoundryContext<'db>>>(
31 &self,
32 db: &'db mut dyn DatabaseExt<Self>,
33 evm_env: EvmEnv<Self::Spec, Self::BlockEnv>,
34 inspector: I,
35 ) -> Self::FoundryEvm<'db, I> {
36 let spec_id = *evm_env.spec_id();
37 let inner = Context::mainnet()
38 .with_tx(OpTx(OpTransaction::builder().build_fill()))
39 .with_cfg(CfgEnv::new_with_spec(OpSpecId::BEDROCK))
40 .with_chain(L1BlockInfo::default())
41 .with_db(db)
42 .with_block(evm_env.block_env)
43 .with_cfg(evm_env.cfg_env);
44 let mut inner = OpEvm::new(inner, inspector).with_precompiles(PrecompilesMap::from_static(
45 OpPrecompiles::new_with_spec(spec_id).precompiles(),
46 ));
47 inner.ctx_mut().cfg.tx_chain_id_check = true;
48
49 let mut evm: OpFoundryEvm<'_, I> = OpFoundryEvm { inner };
50 let networks = Evm::inspector(&evm).get_networks();
51 networks.inject_precompiles(evm.precompiles_mut());
52 evm
53 }
54
55 fn create_foundry_nested_evm<'db>(
56 &self,
57 db: &'db mut dyn DatabaseExt<Self>,
58 evm_env: EvmEnv<Self::Spec, Self::BlockEnv>,
59 inspector: &'db mut dyn FoundryInspectorExt<Self::FoundryContext<'db>>,
60 ) -> Box<dyn NestedEvm<Spec = OpSpecId, Block = BlockEnv, Tx = OpTx> + 'db> {
61 Box::new(self.create_foundry_evm_with_inspector(db, evm_env, inspector).inner)
62 }
63}
64
65impl<'db, I: FoundryInspectorExt<OpContext<&'db mut dyn DatabaseExt<OpEvmFactory>>>> Evm
66 for OpFoundryEvm<'db, I>
67{
68 type Precompiles = PrecompilesMap;
69 type Inspector = I;
70 type DB = &'db mut dyn DatabaseExt<OpEvmFactory>;
71 type Error = EVMError<DatabaseError>;
72 type HaltReason = OpHaltReason;
73 type Spec = OpSpecId;
74 type Tx = OpTx;
75 type BlockEnv = BlockEnv;
76
77 fn block(&self) -> &BlockEnv {
78 &self.inner.ctx_ref().block
79 }
80
81 fn chain_id(&self) -> u64 {
82 self.inner.ctx_ref().cfg.chain_id
83 }
84
85 fn components(&self) -> (&Self::DB, &Self::Inspector, &Self::Precompiles) {
86 let (ctx, _, precompiles, _, inspector) = self.inner.all_inspector();
87 (&ctx.journaled_state.database, inspector, precompiles)
88 }
89
90 fn components_mut(&mut self) -> (&mut Self::DB, &mut Self::Inspector, &mut Self::Precompiles) {
91 let (ctx, _, precompiles, _, inspector) = self.inner.all_mut_inspector();
92 (&mut ctx.journaled_state.database, inspector, precompiles)
93 }
94
95 fn set_inspector_enabled(&mut self, _enabled: bool) {
96 unimplemented!("OpFoundryEvm is always inspecting")
97 }
98
99 fn transact_raw(
100 &mut self,
101 tx: Self::Tx,
102 ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
103 self.inner.ctx().set_tx(tx);
104
105 let mut handler = OpEvmHandler::<I>::new();
106 let result = handler.inspect_run(&mut self.inner).map_err(|e| match e {
108 EVMError::Transaction(tx_error) => EVMError::Transaction(match tx_error {
109 OpTransactionError::Base(invalid_transaction) => invalid_transaction,
110 OpTransactionError::DepositSystemTxPostRegolith => {
111 InvalidTransaction::Str("DepositSystemTxPostRegolith".into())
112 }
113 OpTransactionError::HaltedDepositPostRegolith => {
114 InvalidTransaction::Str("HaltedDepositPostRegolith".into())
115 }
116 OpTransactionError::MissingEnvelopedTx => {
117 InvalidTransaction::Str("MissingEnvelopedTx".into())
118 }
119 }),
120 EVMError::Header(invalid_header) => EVMError::Header(invalid_header),
121 EVMError::Database(db_error) => EVMError::Database(db_error),
122 EVMError::Custom(custom_error) => EVMError::Custom(custom_error),
123 EVMError::CustomAny(custom_any_error) => EVMError::CustomAny(custom_any_error),
124 })?;
125
126 Ok(ResultAndState::new(result, self.inner.ctx_ref().journaled_state.inner.state.clone()))
127 }
128
129 fn transact_system_call(
130 &mut self,
131 _caller: Address,
132 _contract: Address,
133 _data: Bytes,
134 ) -> Result<ExecResultAndState<ExecutionResult<Self::HaltReason>>, Self::Error> {
135 unimplemented!()
136 }
137
138 fn finish(self) -> (Self::DB, EvmEnv<Self::Spec>)
139 where
140 Self: Sized,
141 {
142 let Context { block: block_env, cfg: cfg_env, journaled_state, .. } = self.inner.0.ctx;
143 (journaled_state.database, EvmEnv { block_env, cfg_env })
144 }
145}
146
147impl<'db, I: FoundryInspectorExt<OpContext<&'db mut dyn DatabaseExt<OpEvmFactory>>>> Deref
148 for OpFoundryEvm<'db, I>
149{
150 type Target = OpContext<&'db mut dyn DatabaseExt<OpEvmFactory>>;
151
152 fn deref(&self) -> &Self::Target {
153 &self.inner.0.ctx
154 }
155}
156
157impl<'db, I: FoundryInspectorExt<OpContext<&'db mut dyn DatabaseExt<OpEvmFactory>>>> DerefMut
158 for OpFoundryEvm<'db, I>
159{
160 fn deref_mut(&mut self) -> &mut Self::Target {
161 &mut self.inner.0.ctx
162 }
163}
164
165fn map_op_error(e: EVMError<DatabaseError, OpTransactionError>) -> EVMError<DatabaseError> {
167 match e {
168 EVMError::Database(db) => EVMError::Database(db),
169 EVMError::Header(h) => EVMError::Header(h),
170 EVMError::Custom(s) => EVMError::Custom(s),
171 EVMError::Transaction(t) => EVMError::Custom(format!("op transaction error: {t}")),
172 EVMError::CustomAny(custom_any_error) => EVMError::CustomAny(custom_any_error),
173 }
174}
175
176impl<'db, I: FoundryInspectorExt<OpContext<&'db mut dyn DatabaseExt<OpEvmFactory>>>> NestedEvm
177 for OpRevmEvm<'db, I>
178{
179 type Spec = OpSpecId;
180 type Block = BlockEnv;
181 type Tx = OpTx;
182
183 fn journal_inner_mut(&mut self) -> &mut JournaledState {
184 &mut self.ctx().journaled_state.inner
185 }
186
187 fn run_execution(&mut self, frame: FrameInput) -> Result<FrameResult, EVMError<DatabaseError>> {
188 let mut handler = OpEvmHandler::<I>::new();
189
190 let memory =
191 SharedMemory::new_with_buffer(self.ctx_ref().local.shared_memory_buffer().clone());
192 let first_frame_input = FrameInit { depth: 0, memory, frame_input: frame };
193
194 let mut frame_result =
195 handler.inspect_run_exec_loop(self, first_frame_input).map_err(map_op_error)?;
196
197 handler.last_frame_result(self, &mut frame_result).map_err(map_op_error)?;
198
199 Ok(frame_result)
200 }
201
202 fn transact_raw(
203 &mut self,
204 tx: Self::Tx,
205 ) -> Result<ResultAndState<HaltReason>, EVMError<DatabaseError>> {
206 self.ctx().set_tx(tx);
207
208 let mut handler = OpEvmHandler::<I>::new();
209 let result = handler.inspect_run(self).map_err(map_op_error)?;
210
211 let result = result.map_haltreason(|h| match h {
212 OpHaltReason::Base(eth) => eth,
213 _ => HaltReason::PrecompileError,
214 });
215
216 Ok(ResultAndState::new(result, self.ctx_ref().journaled_state.inner.state.clone()))
217 }
218
219 fn to_evm_env(&self) -> EvmEnv<Self::Spec, Self::Block> {
220 EvmEnv::new(self.ctx_ref().cfg.clone(), self.ctx_ref().block.clone())
221 }
222}