Skip to main content

soldb_ethdebug/
opcodes.rs

1//! EVM opcode mnemonics, for naming the instructions of legacy bytecode.
2//!
3//! Legacy source maps carry no mnemonics, so adapting one to the ETHDebug model means
4//! naming each instruction from its byte. The table is the opcode set REVM knows, so the
5//! names match what an execution backend records for the same steps and a `JUMPDEST` in an
6//! artifact is a `JUMPDEST` in a trace. A byte with no mnemonic is an invalid instruction.
7
8/// The mnemonic of `opcode`, or `None` for a byte that is not an instruction.
9#[must_use]
10pub fn mnemonic(opcode: u8) -> Option<&'static str> {
11    MNEMONICS[usize::from(opcode)]
12}
13
14/// The number of immediate bytes following `opcode` in legacy bytecode: `n` for `PUSHn`
15/// and zero for everything else.
16#[must_use]
17pub fn immediate_size(opcode: u8) -> usize {
18    if (0x60..=0x7f).contains(&opcode) {
19        usize::from(opcode - 0x5f)
20    } else {
21        0
22    }
23}
24
25const MNEMONICS: [Option<&str>; 256] = [
26    Some("STOP"),           // 0x00
27    Some("ADD"),            // 0x01
28    Some("MUL"),            // 0x02
29    Some("SUB"),            // 0x03
30    Some("DIV"),            // 0x04
31    Some("SDIV"),           // 0x05
32    Some("MOD"),            // 0x06
33    Some("SMOD"),           // 0x07
34    Some("ADDMOD"),         // 0x08
35    Some("MULMOD"),         // 0x09
36    Some("EXP"),            // 0x0a
37    Some("SIGNEXTEND"),     // 0x0b
38    None,                   // 0x0c
39    None,                   // 0x0d
40    None,                   // 0x0e
41    None,                   // 0x0f
42    Some("LT"),             // 0x10
43    Some("GT"),             // 0x11
44    Some("SLT"),            // 0x12
45    Some("SGT"),            // 0x13
46    Some("EQ"),             // 0x14
47    Some("ISZERO"),         // 0x15
48    Some("AND"),            // 0x16
49    Some("OR"),             // 0x17
50    Some("XOR"),            // 0x18
51    Some("NOT"),            // 0x19
52    Some("BYTE"),           // 0x1a
53    Some("SHL"),            // 0x1b
54    Some("SHR"),            // 0x1c
55    Some("SAR"),            // 0x1d
56    Some("CLZ"),            // 0x1e
57    None,                   // 0x1f
58    Some("KECCAK256"),      // 0x20
59    None,                   // 0x21
60    None,                   // 0x22
61    None,                   // 0x23
62    None,                   // 0x24
63    None,                   // 0x25
64    None,                   // 0x26
65    None,                   // 0x27
66    None,                   // 0x28
67    None,                   // 0x29
68    None,                   // 0x2a
69    None,                   // 0x2b
70    None,                   // 0x2c
71    None,                   // 0x2d
72    None,                   // 0x2e
73    None,                   // 0x2f
74    Some("ADDRESS"),        // 0x30
75    Some("BALANCE"),        // 0x31
76    Some("ORIGIN"),         // 0x32
77    Some("CALLER"),         // 0x33
78    Some("CALLVALUE"),      // 0x34
79    Some("CALLDATALOAD"),   // 0x35
80    Some("CALLDATASIZE"),   // 0x36
81    Some("CALLDATACOPY"),   // 0x37
82    Some("CODESIZE"),       // 0x38
83    Some("CODECOPY"),       // 0x39
84    Some("GASPRICE"),       // 0x3a
85    Some("EXTCODESIZE"),    // 0x3b
86    Some("EXTCODECOPY"),    // 0x3c
87    Some("RETURNDATASIZE"), // 0x3d
88    Some("RETURNDATACOPY"), // 0x3e
89    Some("EXTCODEHASH"),    // 0x3f
90    Some("BLOCKHASH"),      // 0x40
91    Some("COINBASE"),       // 0x41
92    Some("TIMESTAMP"),      // 0x42
93    Some("NUMBER"),         // 0x43
94    Some("DIFFICULTY"),     // 0x44
95    Some("GASLIMIT"),       // 0x45
96    Some("CHAINID"),        // 0x46
97    Some("SELFBALANCE"),    // 0x47
98    Some("BASEFEE"),        // 0x48
99    Some("BLOBHASH"),       // 0x49
100    Some("BLOBBASEFEE"),    // 0x4a
101    Some("SLOTNUM"),        // 0x4b
102    None,                   // 0x4c
103    None,                   // 0x4d
104    None,                   // 0x4e
105    None,                   // 0x4f
106    Some("POP"),            // 0x50
107    Some("MLOAD"),          // 0x51
108    Some("MSTORE"),         // 0x52
109    Some("MSTORE8"),        // 0x53
110    Some("SLOAD"),          // 0x54
111    Some("SSTORE"),         // 0x55
112    Some("JUMP"),           // 0x56
113    Some("JUMPI"),          // 0x57
114    Some("PC"),             // 0x58
115    Some("MSIZE"),          // 0x59
116    Some("GAS"),            // 0x5a
117    Some("JUMPDEST"),       // 0x5b
118    Some("TLOAD"),          // 0x5c
119    Some("TSTORE"),         // 0x5d
120    Some("MCOPY"),          // 0x5e
121    Some("PUSH0"),          // 0x5f
122    Some("PUSH1"),          // 0x60
123    Some("PUSH2"),          // 0x61
124    Some("PUSH3"),          // 0x62
125    Some("PUSH4"),          // 0x63
126    Some("PUSH5"),          // 0x64
127    Some("PUSH6"),          // 0x65
128    Some("PUSH7"),          // 0x66
129    Some("PUSH8"),          // 0x67
130    Some("PUSH9"),          // 0x68
131    Some("PUSH10"),         // 0x69
132    Some("PUSH11"),         // 0x6a
133    Some("PUSH12"),         // 0x6b
134    Some("PUSH13"),         // 0x6c
135    Some("PUSH14"),         // 0x6d
136    Some("PUSH15"),         // 0x6e
137    Some("PUSH16"),         // 0x6f
138    Some("PUSH17"),         // 0x70
139    Some("PUSH18"),         // 0x71
140    Some("PUSH19"),         // 0x72
141    Some("PUSH20"),         // 0x73
142    Some("PUSH21"),         // 0x74
143    Some("PUSH22"),         // 0x75
144    Some("PUSH23"),         // 0x76
145    Some("PUSH24"),         // 0x77
146    Some("PUSH25"),         // 0x78
147    Some("PUSH26"),         // 0x79
148    Some("PUSH27"),         // 0x7a
149    Some("PUSH28"),         // 0x7b
150    Some("PUSH29"),         // 0x7c
151    Some("PUSH30"),         // 0x7d
152    Some("PUSH31"),         // 0x7e
153    Some("PUSH32"),         // 0x7f
154    Some("DUP1"),           // 0x80
155    Some("DUP2"),           // 0x81
156    Some("DUP3"),           // 0x82
157    Some("DUP4"),           // 0x83
158    Some("DUP5"),           // 0x84
159    Some("DUP6"),           // 0x85
160    Some("DUP7"),           // 0x86
161    Some("DUP8"),           // 0x87
162    Some("DUP9"),           // 0x88
163    Some("DUP10"),          // 0x89
164    Some("DUP11"),          // 0x8a
165    Some("DUP12"),          // 0x8b
166    Some("DUP13"),          // 0x8c
167    Some("DUP14"),          // 0x8d
168    Some("DUP15"),          // 0x8e
169    Some("DUP16"),          // 0x8f
170    Some("SWAP1"),          // 0x90
171    Some("SWAP2"),          // 0x91
172    Some("SWAP3"),          // 0x92
173    Some("SWAP4"),          // 0x93
174    Some("SWAP5"),          // 0x94
175    Some("SWAP6"),          // 0x95
176    Some("SWAP7"),          // 0x96
177    Some("SWAP8"),          // 0x97
178    Some("SWAP9"),          // 0x98
179    Some("SWAP10"),         // 0x99
180    Some("SWAP11"),         // 0x9a
181    Some("SWAP12"),         // 0x9b
182    Some("SWAP13"),         // 0x9c
183    Some("SWAP14"),         // 0x9d
184    Some("SWAP15"),         // 0x9e
185    Some("SWAP16"),         // 0x9f
186    Some("LOG0"),           // 0xa0
187    Some("LOG1"),           // 0xa1
188    Some("LOG2"),           // 0xa2
189    Some("LOG3"),           // 0xa3
190    Some("LOG4"),           // 0xa4
191    None,                   // 0xa5
192    None,                   // 0xa6
193    None,                   // 0xa7
194    None,                   // 0xa8
195    None,                   // 0xa9
196    None,                   // 0xaa
197    None,                   // 0xab
198    None,                   // 0xac
199    None,                   // 0xad
200    None,                   // 0xae
201    None,                   // 0xaf
202    None,                   // 0xb0
203    None,                   // 0xb1
204    None,                   // 0xb2
205    None,                   // 0xb3
206    None,                   // 0xb4
207    None,                   // 0xb5
208    None,                   // 0xb6
209    None,                   // 0xb7
210    None,                   // 0xb8
211    None,                   // 0xb9
212    None,                   // 0xba
213    None,                   // 0xbb
214    None,                   // 0xbc
215    None,                   // 0xbd
216    None,                   // 0xbe
217    None,                   // 0xbf
218    None,                   // 0xc0
219    None,                   // 0xc1
220    None,                   // 0xc2
221    None,                   // 0xc3
222    None,                   // 0xc4
223    None,                   // 0xc5
224    None,                   // 0xc6
225    None,                   // 0xc7
226    None,                   // 0xc8
227    None,                   // 0xc9
228    None,                   // 0xca
229    None,                   // 0xcb
230    None,                   // 0xcc
231    None,                   // 0xcd
232    None,                   // 0xce
233    None,                   // 0xcf
234    None,                   // 0xd0
235    None,                   // 0xd1
236    None,                   // 0xd2
237    None,                   // 0xd3
238    None,                   // 0xd4
239    None,                   // 0xd5
240    None,                   // 0xd6
241    None,                   // 0xd7
242    None,                   // 0xd8
243    None,                   // 0xd9
244    None,                   // 0xda
245    None,                   // 0xdb
246    None,                   // 0xdc
247    None,                   // 0xdd
248    None,                   // 0xde
249    None,                   // 0xdf
250    None,                   // 0xe0
251    None,                   // 0xe1
252    None,                   // 0xe2
253    None,                   // 0xe3
254    None,                   // 0xe4
255    None,                   // 0xe5
256    Some("DUPN"),           // 0xe6
257    Some("SWAPN"),          // 0xe7
258    Some("EXCHANGE"),       // 0xe8
259    None,                   // 0xe9
260    None,                   // 0xea
261    None,                   // 0xeb
262    None,                   // 0xec
263    None,                   // 0xed
264    None,                   // 0xee
265    None,                   // 0xef
266    Some("CREATE"),         // 0xf0
267    Some("CALL"),           // 0xf1
268    Some("CALLCODE"),       // 0xf2
269    Some("RETURN"),         // 0xf3
270    Some("DELEGATECALL"),   // 0xf4
271    Some("CREATE2"),        // 0xf5
272    None,                   // 0xf6
273    None,                   // 0xf7
274    None,                   // 0xf8
275    None,                   // 0xf9
276    Some("STATICCALL"),     // 0xfa
277    None,                   // 0xfb
278    None,                   // 0xfc
279    Some("REVERT"),         // 0xfd
280    Some("INVALID"),        // 0xfe
281    Some("SELFDESTRUCT"),   // 0xff
282];
283
284#[cfg(test)]
285mod tests {
286    use super::{immediate_size, mnemonic, MNEMONICS};
287
288    #[test]
289    fn names_the_evm_instruction_set() {
290        assert_eq!(mnemonic(0x00), Some("STOP"));
291        assert_eq!(mnemonic(0x1e), Some("CLZ"));
292        assert_eq!(mnemonic(0x20), Some("KECCAK256"));
293        assert_eq!(mnemonic(0x5b), Some("JUMPDEST"));
294        assert_eq!(mnemonic(0x5e), Some("MCOPY"));
295        assert_eq!(mnemonic(0x5f), Some("PUSH0"));
296        assert_eq!(mnemonic(0x60), Some("PUSH1"));
297        assert_eq!(mnemonic(0x7f), Some("PUSH32"));
298        assert_eq!(mnemonic(0x80), Some("DUP1"));
299        assert_eq!(mnemonic(0x8f), Some("DUP16"));
300        assert_eq!(mnemonic(0x90), Some("SWAP1"));
301        assert_eq!(mnemonic(0x9f), Some("SWAP16"));
302        assert_eq!(mnemonic(0xa4), Some("LOG4"));
303        assert_eq!(mnemonic(0xf5), Some("CREATE2"));
304        assert_eq!(mnemonic(0xfa), Some("STATICCALL"));
305        assert_eq!(mnemonic(0xff), Some("SELFDESTRUCT"));
306        assert_eq!(mnemonic(0x0c), None);
307        assert_eq!(mnemonic(0x21), None);
308        assert_eq!(mnemonic(0xef), None);
309        assert_eq!(mnemonic(0xfc), None);
310        assert_eq!(MNEMONICS.iter().filter(|name| name.is_some()).count(), 154);
311    }
312
313    #[test]
314    fn only_pushes_carry_immediates() {
315        assert_eq!(immediate_size(0x5f), 0);
316        assert_eq!(immediate_size(0x60), 1);
317        assert_eq!(immediate_size(0x7f), 32);
318        assert_eq!(immediate_size(0x80), 0);
319        assert_eq!(immediate_size(0xff), 0);
320    }
321}