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}