edb_engine/eval/handlers/
mod.rs

1// EDB - Ethereum Debugger
2// Copyright (C) 2024 Zhuo Zhang and Wuqi Zhang
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Affero General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Affero General Public License for more details.
13//
14// You should have received a copy of the GNU Affero General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17//! Handler traits and types for the expression evaluator.
18//!
19//! This module defines the handler traits that allow the expression evaluator to
20//! interact with different data sources and execution contexts. The handler pattern
21//! enables flexible evaluation of Solidity-like expressions against various backends
22//! such as debug snapshots, EVM state, or simulation environments.
23//!
24//! # Handler Types
25//!
26//! - [`VariableHandler`] - Resolves variable values by name
27//! - [`MappingArrayHandler`] - Handles mapping and array access operations
28//! - [`FunctionCallHandler`] - Executes function calls and built-in functions
29//! - [`MemberAccessHandler`] - Resolves member access on values (e.g., struct fields)
30//! - [`MsgHandler`] - Provides transaction context (`msg.sender`, `msg.value`)
31//! - [`TxHandler`] - Provides transaction globals (`tx.origin`)
32//! - [`BlockHandler`] - Provides block context (`block.number`, `block.timestamp`)
33//! - [`ValidationHandler`] - Validates final expression results
34//!
35//! # Usage
36//!
37//! Handlers are typically used through [`EvaluatorHandlers`], which aggregates
38//! all handler types and can be configured with different implementations:
39//!
40//! ```rust,ignore
41//! let handlers = EvaluatorHandlers::new()
42//!     .with_variable_handler(Box::new(my_variable_handler))
43//!     .with_function_call_handler(Box::new(my_function_handler));
44//! ```
45
46use alloy_dyn_abi::DynSolValue;
47use eyre::Result;
48
49/// Handler trait for variable value resolution.
50///
51/// Implementations resolve variable names to their values in a specific execution context.
52/// This includes local variables, state variables, and special variables like `this`.
53pub trait VariableHandler {
54    /// Get the value of a variable by name.
55    ///
56    /// # Arguments
57    /// * `name` - The variable name to resolve
58    /// * `snapshot_id` - The execution context identifier
59    ///
60    /// # Returns
61    /// The variable's value as a [`DynSolValue`], or an error if the variable doesn't exist
62    fn get_variable_value(&self, name: &str, snapshot_id: usize) -> Result<DynSolValue>;
63}
64
65/// Handler trait for mapping and array access operations.
66///
67/// Handles indexing operations like `mapping[key]`, `array[index]`, and nested access
68/// like `mapping[key1][key2]`. Supports both storage-based mappings and in-memory arrays.
69pub trait MappingArrayHandler {
70    /// Access a mapping or array with the given indices.
71    ///
72    /// # Arguments
73    /// * `root` - The base value being indexed (mapping, array, or ABI info)
74    /// * `indices` - Vector of index values for nested access
75    /// * `snapshot_id` - The execution context identifier
76    ///
77    /// # Returns
78    /// The value at the specified indices, or an error if access fails
79    fn get_mapping_or_array_value(
80        &self,
81        root: DynSolValue,
82        indices: Vec<DynSolValue>,
83        snapshot_id: usize,
84    ) -> Result<DynSolValue>;
85}
86
87/// Handler trait for function calls and built-in functions.
88///
89/// Executes function calls including contract functions, built-in functions (like `keccak256`),
90/// and EDB-specific functions (like `edb_sload`).
91pub trait FunctionCallHandler {
92    /// Call a function with the given arguments.
93    ///
94    /// # Arguments
95    /// * `name` - The function name to call
96    /// * `args` - Function arguments as [`DynSolValue`] array
97    /// * `callee` - Optional target address for the call (None uses current context)
98    /// * `snapshot_id` - The execution context identifier
99    ///
100    /// # Returns
101    /// The function's return value, or an error if the call fails
102    fn call_function(
103        &self,
104        name: &str,
105        args: &[DynSolValue],
106        callee: Option<&DynSolValue>,
107        snapshot_id: usize,
108    ) -> Result<DynSolValue>;
109}
110
111/// Handler trait for member access operations.
112///
113/// Handles dot notation access like `struct.field`, `array.length`, or `address.balance`.
114/// Works with both storage state and computed properties.
115pub trait MemberAccessHandler {
116    /// Access a member of the given value.
117    ///
118    /// # Arguments
119    /// * `value` - The base value whose member is being accessed
120    /// * `member` - The member name to access
121    /// * `snapshot_id` - The execution context identifier
122    ///
123    /// # Returns
124    /// The member's value, or an error if the member doesn't exist
125    fn access_member(
126        &self,
127        value: DynSolValue,
128        member: &str,
129        snapshot_id: usize,
130    ) -> Result<DynSolValue>;
131}
132
133/// Handler trait for `msg` global variables.
134///
135/// Provides access to transaction context variables like `msg.sender` and `msg.value`.
136pub trait MsgHandler {
137    /// Get the message sender address (`msg.sender`).
138    ///
139    /// # Arguments
140    /// * `snapshot_id` - The execution context identifier
141    ///
142    /// # Returns
143    /// The sender address as a [`DynSolValue::Address`]
144    fn get_msg_sender(&self, snapshot_id: usize) -> Result<DynSolValue>;
145
146    /// Get the message value (`msg.value`).
147    ///
148    /// # Arguments
149    /// * `snapshot_id` - The execution context identifier
150    ///
151    /// # Returns
152    /// The message value in wei as a [`DynSolValue::Uint`]
153    fn get_msg_value(&self, snapshot_id: usize) -> Result<DynSolValue>;
154}
155
156/// Handler trait for `tx` global variables.
157///
158/// Provides access to transaction-level context like `tx.origin`.
159pub trait TxHandler {
160    /// Get the transaction origin address (`tx.origin`).
161    ///
162    /// # Arguments
163    /// * `snapshot_id` - The execution context identifier
164    ///
165    /// # Returns
166    /// The origin address as a [`DynSolValue::Address`]
167    fn get_tx_origin(&self, snapshot_id: usize) -> Result<DynSolValue>;
168}
169
170/// Handler trait for final expression validation.
171///
172/// Validates and potentially transforms the final result of expression evaluation.
173/// Used to enforce constraints or convert placeholder values to concrete values.
174pub trait ValidationHandler {
175    /// Validate and potentially transform a final expression value.
176    ///
177    /// # Arguments
178    /// * `value` - The value to validate
179    ///
180    /// # Returns
181    /// The validated (possibly transformed) value, or an error if invalid
182    fn validate_value(&self, value: DynSolValue) -> Result<DynSolValue>;
183}
184
185/// Handler trait for `block` global variables.
186///
187/// Provides access to blockchain context like block number and timestamp.
188pub trait BlockHandler {
189    /// Get the current block number (`block.number`).
190    ///
191    /// # Arguments
192    /// * `snapshot_id` - The execution context identifier
193    ///
194    /// # Returns
195    /// The block number as a [`DynSolValue::Uint`]
196    fn get_block_number(&self, snapshot_id: usize) -> Result<DynSolValue>;
197
198    /// Get the current block timestamp (`block.timestamp`).
199    ///
200    /// # Arguments
201    /// * `snapshot_id` - The execution context identifier
202    ///
203    /// # Returns
204    /// The block timestamp as a [`DynSolValue::Uint`]
205    fn get_block_timestamp(&self, snapshot_id: usize) -> Result<DynSolValue>;
206}
207
208/// Combined handlers struct for the expression evaluator.
209///
210/// Aggregates all handler types needed for expression evaluation. Each handler
211/// is optional, allowing for partial implementations where only certain features
212/// are needed.
213///
214/// # Example
215///
216/// ```rust,ignore
217/// let handlers = EvaluatorHandlers::new()
218///     .with_variable_handler(Box::new(MyVariableHandler))
219///     .with_function_call_handler(Box::new(MyFunctionHandler))
220///     .with_msg_handler(Box::new(MyMsgHandler));
221/// ```
222#[derive(Default)]
223pub struct EvaluatorHandlers {
224    /// Handler for variable resolution
225    pub variable_handler: Option<Box<dyn VariableHandler>>,
226    /// Handler for mapping and array access
227    pub mapping_array_handler: Option<Box<dyn MappingArrayHandler>>,
228    /// Handler for function calls
229    pub function_call_handler: Option<Box<dyn FunctionCallHandler>>,
230    /// Handler for member access operations
231    pub member_access_handler: Option<Box<dyn MemberAccessHandler>>,
232    /// Handler for `msg` global variables
233    pub msg_handler: Option<Box<dyn MsgHandler>>,
234    /// Handler for `tx` global variables
235    pub tx_handler: Option<Box<dyn TxHandler>>,
236    /// Handler for `block` global variables
237    pub block_handler: Option<Box<dyn BlockHandler>>,
238    /// Handler for final value validation
239    pub validation_handler: Option<Box<dyn ValidationHandler>>,
240}
241
242impl Clone for EvaluatorHandlers {
243    /// Clone the handlers struct.
244    ///
245    /// Note: This creates a new empty handlers struct since trait objects
246    /// cannot be cloned. If handlers need to be cloned with their state,
247    /// they would need to implement a custom clone method.
248    fn clone(&self) -> Self {
249        Self::default()
250    }
251}
252
253impl EvaluatorHandlers {
254    /// Create a new empty handlers collection.
255    ///
256    /// All handlers are initially `None` and can be set using the `with_*` methods.
257    pub fn new() -> Self {
258        Self::default()
259    }
260
261    /// Set the variable handler.
262    ///
263    /// # Arguments
264    /// * `handler` - The variable handler implementation
265    ///
266    /// # Returns
267    /// Self for method chaining
268    pub fn with_variable_handler(mut self, handler: Box<dyn VariableHandler>) -> Self {
269        self.variable_handler = Some(handler);
270        self
271    }
272
273    /// Set the mapping/array handler.
274    ///
275    /// # Arguments
276    /// * `handler` - The mapping/array handler implementation
277    ///
278    /// # Returns
279    /// Self for method chaining
280    pub fn with_mapping_array_handler(mut self, handler: Box<dyn MappingArrayHandler>) -> Self {
281        self.mapping_array_handler = Some(handler);
282        self
283    }
284
285    /// Set the function call handler.
286    ///
287    /// # Arguments
288    /// * `handler` - The function call handler implementation
289    ///
290    /// # Returns
291    /// Self for method chaining
292    pub fn with_function_call_handler(mut self, handler: Box<dyn FunctionCallHandler>) -> Self {
293        self.function_call_handler = Some(handler);
294        self
295    }
296
297    /// Set the member access handler.
298    ///
299    /// # Arguments
300    /// * `handler` - The member access handler implementation
301    ///
302    /// # Returns
303    /// Self for method chaining
304    pub fn with_member_access_handler(mut self, handler: Box<dyn MemberAccessHandler>) -> Self {
305        self.member_access_handler = Some(handler);
306        self
307    }
308
309    /// Set the msg handler.
310    ///
311    /// # Arguments
312    /// * `handler` - The msg handler implementation
313    ///
314    /// # Returns
315    /// Self for method chaining
316    pub fn with_msg_handler(mut self, handler: Box<dyn MsgHandler>) -> Self {
317        self.msg_handler = Some(handler);
318        self
319    }
320
321    /// Set the tx handler.
322    ///
323    /// # Arguments
324    /// * `handler` - The tx handler implementation
325    ///
326    /// # Returns
327    /// Self for method chaining
328    pub fn with_tx_handler(mut self, handler: Box<dyn TxHandler>) -> Self {
329        self.tx_handler = Some(handler);
330        self
331    }
332
333    /// Set the block handler.
334    ///
335    /// # Arguments
336    /// * `handler` - The block handler implementation
337    ///
338    /// # Returns
339    /// Self for method chaining
340    pub fn with_block_handler(mut self, handler: Box<dyn BlockHandler>) -> Self {
341        self.block_handler = Some(handler);
342        self
343    }
344
345    /// Set the validation handler.
346    ///
347    /// # Arguments
348    /// * `handler` - The validation handler implementation
349    ///
350    /// # Returns
351    /// Self for method chaining
352    pub fn with_validation_handler(mut self, handler: Box<dyn ValidationHandler>) -> Self {
353        self.validation_handler = Some(handler);
354        self
355    }
356}
357
358/// Debug handler implementations for testing and simulation
359pub mod debug;
360/// EDB handler implementations for real debug snapshots
361pub mod edb;