edb_common/
opcode.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
17use revm::bytecode::OpCode;
18
19/// Extended trait for EVM opcode analysis
20///
21/// Provides additional methods for determining what types of EVM state
22/// an opcode will modify when executed. This is useful for:
23/// - Debugging tools that need to track state changes
24/// - Optimization of state snapshots and memory sharing
25/// - Security analysis of contract execution
26pub trait OpcodeTr {
27    /// Check if this opcode modifies persistent EVM state
28    ///
29    /// Returns `true` if the opcode will modify any persistent state including:
30    /// - Storage (via SSTORE)
31    /// - Account state (via CREATE, CREATE2, SELFDESTRUCT)
32    /// - Account balances (via CALL, CALLCODE with value transfer)
33    /// - Event logs (via LOG0-LOG4)
34    ///
35    /// Note: This does NOT include temporary state like memory or stack,
36    /// only state that persists beyond the current transaction execution.
37    ///
38    /// # Example
39    /// ```rust
40    /// use revm::bytecode::OpCode;
41    /// use edb_common::OpcodeTr;
42    ///
43    /// assert!(OpCode::SSTORE.modifies_evm_state());
44    /// assert!(OpCode::CREATE.modifies_evm_state());
45    /// assert!(!OpCode::ADD.modifies_evm_state());
46    /// assert!(!OpCode::MSTORE.modifies_evm_state()); // Only modifies memory
47    /// ```
48    fn modifies_evm_state(&self) -> bool;
49
50    /// Check if this opcode modifies transient storage (EIP-1153)
51    ///
52    /// Transient storage is temporary storage that exists only for the
53    /// duration of a transaction and is cleared when the transaction ends.
54    ///
55    /// Returns `true` only for:
56    /// - `TSTORE` (0x5C): Write to transient storage
57    ///
58    /// Note: `TLOAD` (0x5D) only reads transient storage and doesn't modify it.
59    ///
60    /// # Example
61    /// ```rust
62    /// use revm::bytecode::OpCode;
63    /// use edb_common::OpcodeTr;
64    ///
65    /// assert!(OpCode::TSTORE.modifies_transient_storage());
66    /// assert!(!OpCode::TLOAD.modifies_transient_storage());
67    /// assert!(!OpCode::SSTORE.modifies_transient_storage());
68    /// ```
69    fn modifies_transient_storage(&self) -> bool;
70
71    /// Check if this opcode is a call instruction
72    fn is_call(&self) -> bool;
73}
74
75impl OpcodeTr for OpCode {
76    fn modifies_evm_state(&self) -> bool {
77        matches!(
78            *self,
79            // Storage modifications - writes to persistent contract storage
80            Self::SSTORE |
81
82            // Account state changes - create/destroy accounts
83            Self::CREATE |     // Create new contract account
84            Self::CREATE2 |    // Create new contract with deterministic address
85            Self::SELFDESTRUCT | // Destroy current contract and transfer balance
86
87            // Balance transfers - modify account balances
88            Self::CALL |       // External call that can transfer ETH
89            Self::CALLCODE |   // Call with current account context (deprecated)
90
91            // Log emissions - add entries to transaction receipt logs
92            Self::LOG0 | Self::LOG1 | Self::LOG2 | Self::LOG3 | Self::LOG4
93        )
94    }
95
96    fn modifies_transient_storage(&self) -> bool {
97        matches!(
98            *self,
99            Self::TSTORE // Write to transient storage (EIP-1153)
100        )
101    }
102
103    fn is_call(&self) -> bool {
104        matches!(
105            *self,
106            Self::CREATE
107                | Self::CREATE2
108                | Self::CALL
109                | Self::CALLCODE
110                | Self::DELEGATECALL
111                | Self::STATICCALL
112        )
113    }
114}