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(output) = frame_start(ctx, inspector, &mut frame_input) {
103 return Ok(ItemOrResult::Result(output));
104 }
105 let mut ret = self.first_frame_init(evm, frame_input.clone());
106
107 if let Ok(ItemOrResult::Item(frame)) = &mut ret {
109 let (context, inspector) = evm.ctx_inspector();
110 inspector.initialize_interp(frame.interpreter(), context);
111 } else if let Ok(ItemOrResult::Result(result)) = &mut ret {
112 let (context, inspector) = evm.ctx_inspector();
113 frame_end(context, inspector, &frame_input, result);
114 }
115 ret
116 }
117
118 #[inline]
125 fn inspect_frame_call(
126 &mut self,
127 frame: &mut Self::Frame,
128 evm: &mut Self::Evm,
129 ) -> Result<FrameInitOrResult<Self::Frame>, Self::Error> {
130 frame.run_inspect(evm)
131 }
132
133 fn inspect_run_exec_loop(
143 &mut self,
144 evm: &mut Self::Evm,
145 frame: Self::Frame,
146 ) -> Result<FrameResult, Self::Error> {
147 let mut frame_stack: Vec<Self::Frame> = vec![frame];
148 loop {
149 let frame = frame_stack.last_mut().unwrap();
150 let call_or_result = self.inspect_frame_call(frame, evm)?;
151
152 let result = match call_or_result {
153 ItemOrResult::Item(mut init) => {
154 let (context, inspector) = evm.ctx_inspector();
155 if let Some(output) = frame_start(context, inspector, &mut init) {
156 output
157 } else {
158 match self.frame_init(frame, evm, init.clone())? {
159 ItemOrResult::Item(mut new_frame) => {
160 let (context, inspector) = evm.ctx_inspector();
162 inspector.initialize_interp(new_frame.interpreter(), context);
163 frame_stack.push(new_frame);
164 continue;
165 }
166 ItemOrResult::Result(mut result) => {
168 let (context, inspector) = evm.ctx_inspector();
169 frame_end(context, inspector, &init, &mut result);
170 result
171 }
172 }
173 }
174 }
175 ItemOrResult::Result(mut result) => {
176 let (context, inspector) = evm.ctx_inspector();
177 frame_end(context, inspector, frame.frame_input(), &mut result);
178
179 frame_stack.pop();
181 result
182 }
183 };
184
185 let Some(frame) = frame_stack.last_mut() else {
186 return Ok(result);
187 };
188
189 self.frame_return_result(frame, evm, result)?;
190 }
191 }
192}
193
194pub fn frame_start<CTX, INTR: InterpreterTypes>(
195 context: &mut CTX,
196 inspector: &mut impl Inspector<CTX, INTR>,
197 frame_input: &mut FrameInput,
198) -> Option<FrameResult> {
199 match frame_input {
200 FrameInput::Call(i) => {
201 if let Some(output) = inspector.call(context, i) {
202 return Some(FrameResult::Call(output));
203 }
204 }
205 FrameInput::Create(i) => {
206 if let Some(output) = inspector.create(context, i) {
207 return Some(FrameResult::Create(output));
208 }
209 }
210 FrameInput::EOFCreate(i) => {
211 if let Some(output) = inspector.eofcreate(context, i) {
212 return Some(FrameResult::EOFCreate(output));
213 }
214 }
215 }
216 None
217}
218
219pub fn frame_end<CTX, INTR: InterpreterTypes>(
220 context: &mut CTX,
221 inspector: &mut impl Inspector<CTX, INTR>,
222 frame_input: &FrameInput,
223 frame_output: &mut FrameResult,
224) {
225 match frame_output {
226 FrameResult::Call(outcome) => {
227 let FrameInput::Call(i) = frame_input else {
228 panic!("FrameInput::Call expected");
229 };
230 inspector.call_end(context, i, outcome);
231 }
232 FrameResult::Create(outcome) => {
233 let FrameInput::Create(i) = frame_input else {
234 panic!("FrameInput::Create expected");
235 };
236 inspector.create_end(context, i, outcome);
237 }
238 FrameResult::EOFCreate(outcome) => {
239 let FrameInput::EOFCreate(i) = frame_input else {
240 panic!("FrameInput::EofCreate expected");
241 };
242 inspector.eofcreate_end(context, i, outcome);
243 }
244 }
245}
246
247pub fn inspect_instructions<CTX, IT>(
253 context: &mut CTX,
254 interpreter: &mut Interpreter<IT>,
255 mut inspector: impl Inspector<CTX, IT>,
256 instructions: &InstructionTable<IT, CTX>,
257) -> InterpreterAction
258where
259 CTX: ContextTr<Journal: JournalExt> + Host,
260 IT: InterpreterTypes,
261{
262 interpreter.reset_control();
263
264 let mut log_num = context.journal().logs().len();
265 while interpreter.control.instruction_result().is_continue() {
267 let opcode = interpreter.bytecode.opcode();
269
270 inspector.step(interpreter, context);
272 if interpreter.control.instruction_result() != InstructionResult::Continue {
273 break;
274 }
275
276 interpreter.bytecode.relative_jump(1);
280
281 instructions[opcode as usize](interpreter, context);
283
284 let new_log = context.journal().logs().len();
286 if log_num < new_log {
287 let log = context.journal().logs().last().unwrap().clone();
289 inspector.log(interpreter, context, log);
290 log_num = new_log;
291 }
292
293 inspector.step_end(interpreter, context);
295 }
296
297 let next_action = interpreter.take_next_action();
298
299 if let InterpreterAction::Return { result } = &next_action {
301 if result.result == InstructionResult::SelfDestruct {
302 match context.journal().last_journal().last() {
303 Some(JournalEntry::AccountDestroyed {
304 address,
305 target,
306 had_balance,
307 ..
308 }) => {
309 inspector.selfdestruct(*address, *target, *had_balance);
310 }
311 Some(JournalEntry::BalanceTransfer {
312 from, to, balance, ..
313 }) => {
314 inspector.selfdestruct(*from, *to, *balance);
315 }
316 _ => {}
317 }
318 }
319 }
320
321 next_action
322}