foundry_evm/inspectors/
custom_printer.rs1use foundry_common::sh_println;
5use revm::{
6 Inspector,
7 bytecode::opcode::OpCode,
8 context::{ContextTr, JournalTr},
9 inspector::inspectors::GasInspector,
10 interpreter::{
11 CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter,
12 interpreter_types::{Jumps, MemoryTr},
13 },
14 primitives::{Address, U256},
15};
16
17#[derive(Clone, Debug, Default)]
21pub struct CustomPrintTracer {
22 gas_inspector: GasInspector,
23}
24
25impl<CTX: ContextTr> Inspector<CTX> for CustomPrintTracer {
26 fn initialize_interp(&mut self, interp: &mut Interpreter, _context: &mut CTX) {
27 self.gas_inspector.initialize_interp(&interp.gas);
28 }
29
30 fn step(&mut self, interp: &mut Interpreter, context: &mut CTX) {
33 let opcode = interp.bytecode.opcode();
34 let name = OpCode::name_by_op(opcode);
35
36 let gas_remaining = self.gas_inspector.gas_remaining();
37
38 let memory_size = interp.memory.size();
39
40 let _ = sh_println!(
41 "depth:{}, PC:{}, gas:{:#x}({}), OPCODE: {:?}({:?}) refund:{:#x}({}) Stack:{:?}, Data size:{}",
42 context.journal().depth(),
43 interp.bytecode.pc(),
44 gas_remaining,
45 gas_remaining,
46 name,
47 opcode,
48 interp.gas.refunded(),
49 interp.gas.refunded(),
50 interp.stack.data(),
51 memory_size,
52 );
53
54 self.gas_inspector.step(&interp.gas);
55 }
56
57 fn step_end(&mut self, interpreter: &mut Interpreter, _context: &mut CTX) {
58 self.gas_inspector.step_end(&interpreter.gas);
59 }
60
61 fn call_end(&mut self, _context: &mut CTX, _inputs: &CallInputs, outcome: &mut CallOutcome) {
62 self.gas_inspector.call_end(outcome)
63 }
64
65 fn create_end(
66 &mut self,
67 _context: &mut CTX,
68 _inputs: &CreateInputs,
69 outcome: &mut CreateOutcome,
70 ) {
71 self.gas_inspector.create_end(outcome)
72 }
73
74 fn call(&mut self, _context: &mut CTX, inputs: &mut CallInputs) -> Option<CallOutcome> {
75 let _ = sh_println!(
76 "SM Address: {:?}, caller:{:?},target:{:?} is_static:{:?}, transfer:{:?}, input_size:{:?}",
77 inputs.bytecode_address,
78 inputs.caller,
79 inputs.target_address,
80 inputs.is_static,
81 inputs.value,
82 inputs.input.len(),
83 );
84 None
85 }
86
87 fn create(&mut self, _context: &mut CTX, inputs: &mut CreateInputs) -> Option<CreateOutcome> {
88 let _ = sh_println!(
89 "CREATE CALL: caller:{:?}, scheme:{:?}, value:{:?}, init_code:{:?}, gas:{:?}",
90 inputs.caller(),
91 inputs.scheme(),
92 inputs.value(),
93 inputs.init_code(),
94 inputs.gas_limit()
95 );
96 None
97 }
98
99 fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {
100 let _ = sh_println!(
101 "SELFDESTRUCT: contract: {:?}, refund target: {:?}, value {:?}",
102 contract,
103 target,
104 value
105 );
106 }
107}