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}