1use crate::{Inspector, InspectorEvmTr, InspectorFrame, JournalExt};
2use context::{result::ResultAndState, ContextTr, JournalEntry, Transaction};
3use handler::{EvmTr, Frame, FrameInitOrResult, FrameOrResult, FrameResult, Handler, ItemOrResult};
4use interpreter::{
5 instructions::InstructionTable,
6 interpreter_types::{Jumps, LoopControl},
7 FrameInput, Host, InitialAndFloorGas, InstructionResult, Interpreter, InterpreterAction,
8 InterpreterTypes,
9};
10
11use std::{vec, vec::Vec};
12
13pub trait InspectorHandler: Handler
30where
31 Self::Evm:
32 InspectorEvmTr<Inspector: Inspector<<<Self as Handler>::Evm as EvmTr>::Context, Self::IT>>,
33 Self::Frame: InspectorFrame<IT = Self::IT>,
34{
35 type IT: InterpreterTypes;
36
37 fn inspect_run(
41 &mut self,
42 evm: &mut Self::Evm,
43 ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
44 match self.inspect_run_without_catch_error(evm) {
45 Ok(output) => Ok(output),
46 Err(e) => self.catch_error(evm, e),
47 }
48 }
49
50 fn inspect_run_without_catch_error(
54 &mut self,
55 evm: &mut Self::Evm,
56 ) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
57 let init_and_floor_gas = self.validate(evm)?;
58 let eip7702_refund = self.pre_execution(evm)? as i64;
59 let exec_result = self.inspect_execution(evm, &init_and_floor_gas);
60 self.post_execution(evm, exec_result?, init_and_floor_gas, eip7702_refund)
61 }
62
63 fn inspect_execution(
67 &mut self,
68 evm: &mut Self::Evm,
69 init_and_floor_gas: &InitialAndFloorGas,
70 ) -> Result<FrameResult, Self::Error> {
71 let gas_limit = evm.ctx().tx().gas_limit() - init_and_floor_gas.initial_gas;
72
73 let first_frame_input = self.first_frame_input(evm, gas_limit)?;
75 let first_frame = self.inspect_first_frame_init(evm, first_frame_input)?;
76
77 let mut frame_result = match first_frame {
78 ItemOrResult::Item(frame) => self.inspect_run_exec_loop(evm, frame)?,
79 ItemOrResult::Result(result) => result,
80 };
81
82 self.last_frame_result(evm, &mut frame_result)?;
83 Ok(frame_result)
84 }
85
86 fn inspect_first_frame_init(
97 &mut self,
98 evm: &mut Self::Evm,
99 mut frame_input: <Self::Frame as Frame>::FrameInit,
100 ) -> Result<FrameOrResult<Self::Frame>, Self::Error> {
101 let (ctx, inspector) = evm.ctx_inspector();
102 if let Some(mut output) = frame_start(ctx, inspector, &mut frame_input) {
103 frame_end(ctx, inspector, &frame_input, &mut output);
104 return Ok(ItemOrResult::Result(output));
105 }
106 let mut ret = self.first_frame_init(evm, frame_input.clone());
107
108 if let Ok(ItemOrResult::Item(frame)) = &mut ret {
110 let (context, inspector) = evm.ctx_inspector();
111 inspector.initialize_interp(frame.interpreter(), context);
112 } else if let Ok(ItemOrResult::Result(result)) = &mut ret {
113 let (context, inspector) = evm.ctx_inspector();
114 frame_end(context, inspector, &frame_input, result);
115 }
116 ret
117 }
118
119 #[inline]
126 fn inspect_frame_call(
127 &mut self,
128 frame: &mut Self::Frame,
129 evm: &mut Self::Evm,
130 ) -> Result<FrameInitOrResult<Self::Frame>, Self::Error> {
131 frame.run_inspect(evm)
132 }
133
134 fn inspect_run_exec_loop(
144 &mut self,
145 evm: &mut Self::Evm,
146 frame: Self::Frame,
147 ) -> Result<FrameResult, Self::Error> {
148 let mut frame_stack: Vec<Self::Frame> = vec![frame];
149 loop {
150 let frame = frame_stack.last_mut().unwrap();
151 let call_or_result = self.inspect_frame_call(frame, evm)?;
152
153 let result = match call_or_result {
154 ItemOrResult::Item(mut init) => {
155 let (context, inspector) = evm.ctx_inspector();
156 if let Some(mut output) = frame_start(context, inspector, &mut init) {
157 frame_end(context, inspector, &init, &mut output);
158 output
159 } else {
160 match self.frame_init(frame, evm, init.clone())? {
161 ItemOrResult::Item(mut new_frame) => {
162 let (context, inspector) = evm.ctx_inspector();
164 inspector.initialize_interp(new_frame.interpreter(), context);
165 frame_stack.push(new_frame);
166 continue;
167 }
168 ItemOrResult::Result(mut result) => {
170 let (context, inspector) = evm.ctx_inspector();
171 frame_end(context, inspector, &init, &mut result);
172 result
173 }
174 }
175 }
176 }
177 ItemOrResult::Result(mut result) => {
178 let (context, inspector) = evm.ctx_inspector();
179 frame_end(context, inspector, frame.frame_input(), &mut result);
180
181 frame_stack.pop();
183 result
184 }
185 };
186
187 let Some(frame) = frame_stack.last_mut() else {
188 return Ok(result);
189 };
190
191 self.frame_return_result(frame, evm, result)?;
192 }
193 }
194}
195
196pub fn frame_start<CTX, INTR: InterpreterTypes>(
197 context: &mut CTX,
198 inspector: &mut impl Inspector<CTX, INTR>,
199 frame_input: &mut FrameInput,
200) -> Option<FrameResult> {
201 match frame_input {
202 FrameInput::Call(i) => {
203 if let Some(output) = inspector.call(context, i) {
204 return Some(FrameResult::Call(output));
205 }
206 }
207 FrameInput::Create(i) => {
208 if let Some(output) = inspector.create(context, i) {
209 return Some(FrameResult::Create(output));
210 }
211 }
212 FrameInput::EOFCreate(i) => {
213 if let Some(output) = inspector.eofcreate(context, i) {
214 return Some(FrameResult::EOFCreate(output));
215 }
216 }
217 }
218 None
219}
220
221pub fn frame_end<CTX, INTR: InterpreterTypes>(
222 context: &mut CTX,
223 inspector: &mut impl Inspector<CTX, INTR>,
224 frame_input: &FrameInput,
225 frame_output: &mut FrameResult,
226) {
227 match frame_output {
228 FrameResult::Call(outcome) => {
229 let FrameInput::Call(i) = frame_input else {
230 panic!("FrameInput::Call expected");
231 };
232 inspector.call_end(context, i, outcome);
233 }
234 FrameResult::Create(outcome) => {
235 let FrameInput::Create(i) = frame_input else {
236 panic!("FrameInput::Create expected");
237 };
238 inspector.create_end(context, i, outcome);
239 }
240 FrameResult::EOFCreate(outcome) => {
241 let FrameInput::EOFCreate(i) = frame_input else {
242 panic!("FrameInput::EofCreate expected");
243 };
244 inspector.eofcreate_end(context, i, outcome);
245 }
246 }
247}
248
249pub fn inspect_instructions<CTX, IT>(
255 context: &mut CTX,
256 interpreter: &mut Interpreter<IT>,
257 mut inspector: impl Inspector<CTX, IT>,
258 instructions: &InstructionTable<IT, CTX>,
259) -> InterpreterAction
260where
261 CTX: ContextTr<Journal: JournalExt> + Host,
262 IT: InterpreterTypes,
263{
264 interpreter.reset_control();
265
266 let mut log_num = context.journal().logs().len();
267 while interpreter.control.instruction_result().is_continue() {
269 let opcode = interpreter.bytecode.opcode();
271
272 inspector.step(interpreter, context);
274 if interpreter.control.instruction_result() != InstructionResult::Continue {
275 break;
276 }
277
278 interpreter.bytecode.relative_jump(1);
282
283 instructions[opcode as usize](interpreter, context);
285
286 let new_log = context.journal().logs().len();
288 if log_num < new_log {
289 let log = context.journal().logs().last().unwrap().clone();
291 inspector.log(interpreter, context, log);
292 log_num = new_log;
293 }
294
295 inspector.step_end(interpreter, context);
297 }
298
299 let next_action = interpreter.take_next_action();
300
301 if let InterpreterAction::Return { result } = &next_action {
303 if result.result == InstructionResult::SelfDestruct {
304 match context.journal().journal().last() {
305 Some(JournalEntry::AccountDestroyed {
306 address,
307 target,
308 had_balance,
309 ..
310 }) => {
311 inspector.selfdestruct(*address, *target, *had_balance);
312 }
313 Some(JournalEntry::BalanceTransfer {
314 from, to, balance, ..
315 }) => {
316 inspector.selfdestruct(*from, *to, *balance);
317 }
318 _ => {}
319 }
320 }
321 }
322
323 next_action
324}