foundry_evm/inspectors/
chisel_state.rs

1use alloy_primitives::U256;
2use foundry_evm_core::backend::DatabaseError;
3use revm::{
4    Database, Inspector,
5    context::ContextTr,
6    inspector::JournalExt,
7    interpreter::{
8        InstructionResult, Interpreter,
9        interpreter::EthInterpreter,
10        interpreter_types::{Jumps, LoopControl},
11    },
12};
13
14/// An inspector for Chisel
15#[derive(Clone, Debug, Default)]
16pub struct ChiselState {
17    /// The PC of the final instruction
18    pub final_pc: usize,
19    /// The final state of the REPL contract call
20    pub state: Option<(Vec<U256>, Vec<u8>, Option<InstructionResult>)>,
21}
22
23impl ChiselState {
24    /// Create a new Chisel state inspector.
25    #[inline]
26    pub fn new(final_pc: usize) -> Self {
27        Self { final_pc, state: None }
28    }
29}
30
31impl<CTX, D> Inspector<CTX, EthInterpreter> for ChiselState
32where
33    D: Database<Error = DatabaseError>,
34    CTX: ContextTr<Db = D>,
35    CTX::Journal: JournalExt,
36{
37    #[cold]
38    fn step_end(&mut self, interpreter: &mut Interpreter, _context: &mut CTX) {
39        // If we are at the final pc of the REPL contract execution, set the state.
40        // Subtraction can't overflow because `pc` is always at least 1 in `step_end`.
41        if self.final_pc == interpreter.bytecode.pc() - 1 {
42            self.state = Some((
43                interpreter.stack.data().clone(),
44                interpreter.memory.context_memory().to_vec(),
45                interpreter.bytecode.instruction_result(),
46            ))
47        }
48    }
49}