arbiter_core/database/
inspector.rs

1//! This module contains an extensible [`Inspector`] called
2//! [`ArbiterInspector`]. It is currently configurable in order to allow
3//! for users to set configuration to see logs generated in Solidity contracts
4//! and or enforce gas payment.
5
6use revm::{
7    inspectors::GasInspector,
8    interpreter::{CreateInputs, CreateOutcome, Interpreter},
9};
10
11use super::*;
12use crate::console::ConsoleLogs;
13
14/// An configurable [`Inspector`] that collects information about the
15/// execution of the [`Interpreter`]. Depending on whether which or both
16/// features are enabled, it collects information about the gas used by each
17/// opcode and the `console2.log`s emitted during execution. It ensures gas
18/// payments are made when `gas` is enabled.
19#[derive(Debug, Clone)]
20pub struct ArbiterInspector {
21    /// Whether to collect `console2.log`s.
22    pub console_log: Option<ConsoleLogs>,
23
24    /// Whether to collect gas usage information.
25    pub gas: Option<GasInspector>,
26}
27
28impl ArbiterInspector {
29    /// Create a new [`ArbiterInspector`] with the given configuration.
30    pub fn new(console_log: bool, gas: bool) -> Self {
31        let console_log = if console_log {
32            Some(ConsoleLogs::default())
33        } else {
34            None
35        };
36        let gas = if gas {
37            Some(GasInspector::default())
38        } else {
39            None
40        };
41        Self { console_log, gas }
42    }
43}
44
45impl Inspector<ArbiterDB> for ArbiterInspector {
46    #[inline]
47    fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext<ArbiterDB>) {
48        if let Some(gas) = &mut self.gas {
49            gas.initialize_interp(interp, context);
50        }
51    }
52
53    #[inline]
54    fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext<ArbiterDB>) {
55        if let Some(gas) = &mut self.gas {
56            gas.step_end(interp, context);
57        }
58    }
59
60    #[inline]
61    fn call(
62        &mut self,
63        context: &mut EvmContext<ArbiterDB>,
64        inputs: &mut CallInputs,
65    ) -> Option<CallOutcome> {
66        if let Some(console_log) = &mut self.console_log {
67            console_log.call(context, inputs)
68        } else {
69            None
70        }
71    }
72
73    #[inline]
74    fn call_end(
75        &mut self,
76        context: &mut EvmContext<ArbiterDB>,
77        inputs: &CallInputs,
78        outcome: CallOutcome,
79    ) -> CallOutcome {
80        if let Some(gas) = &mut self.gas {
81            gas.call_end(context, inputs, outcome)
82        } else {
83            outcome
84        }
85    }
86
87    #[inline]
88    fn create_end(
89        &mut self,
90        _context: &mut EvmContext<ArbiterDB>,
91        _inputs: &CreateInputs,
92        outcome: CreateOutcome,
93    ) -> CreateOutcome {
94        outcome
95    }
96}