ethers_core/types/
opcode.rs

1use num_enum::TryFromPrimitive;
2use serde::{Deserialize, Serialize};
3use strum::{AsRefStr, Display, EnumCount, EnumIter, EnumString, VariantNames};
4
5// opcode descriptions taken from evm.codes https://github.com/comitylabs/evm.codes/blob/bc7f102808055d88365559d40c190c5bd6d164c3/opcodes.json
6// https://github.com/ethereum/go-ethereum/blob/2b1299b1c006077c56ecbad32e79fc16febe3dd6/core/vm/opcodes.go
7
8/// An [EVM Opcode](https://evm.codes).
9#[derive(
10    Clone,
11    Copy,
12    Debug,
13    PartialEq,
14    Eq,
15    PartialOrd,
16    Ord,
17    Hash,
18    AsRefStr,
19    Display,
20    EnumString,
21    VariantNames,
22    EnumIter,
23    EnumCount,
24    TryFromPrimitive,
25    Serialize,
26    Deserialize,
27)]
28#[repr(u8)]
29pub enum Opcode {
30    // 0x0 range - arithmetic ops.
31    /// Opcode 0x0 - Halts execution
32    STOP = 0x00,
33    /// Opcode 0x1 - Addition operation
34    ADD,
35    /// Opcode 0x2 - Multiplication operation
36    MUL,
37    /// Opcode 0x3 - Subtraction operation
38    SUB,
39    /// Opcode 0x4 - Integer division operation
40    DIV,
41    /// Opcode 0x5 - Signed integer division operation (truncated)
42    SDIV,
43    /// Opcode 0x6 - Modulo remainder operation
44    MOD,
45    /// Opcode 0x7 - Signed modulo remainder operation
46    SMOD,
47    /// Opcode 0x8 - Modulo addition operation
48    ADDMOD,
49    /// Opcode 0x9 - Modulo multiplication operation
50    MULMOD,
51    /// Opcode 0xA - Exponential operation
52    EXP,
53    /// Opcode 0xB - Extend length of two’s complement signed integer
54    SIGNEXTEND,
55
56    // 0x0C - 0x0F are invalid
57
58    // 0x10 range - comparison ops.
59    /// Opcode 0x10 - Less-than comparison
60    LT = 0x10,
61    /// Opcode 0x11 - Greater-than comparison
62    GT,
63    /// Opcode 0x12 - Signed less-than comparison
64    SLT,
65    /// Opcode 0x13 - Signed greater-than comparison
66    SGT,
67    /// Opcode 0x14 - Equality comparison
68    EQ,
69    /// Opcode 0x15 - Simple not operator
70    ISZERO,
71    /// Opcode 0x16 - Bitwise AND operation
72    AND,
73    /// Opcode 0x17 - Bitwise OR operation
74    OR,
75    /// Opcode 0x18 - Bitwise XOR operation
76    XOR,
77    /// Opcode 0x19 - Bitwise NOT operation
78    NOT,
79    /// Opcode 0x1A - Retrieve single byte from word
80    BYTE,
81    /// Opcode 0x1B - Left shift operation
82    SHL,
83    /// Opcode 0x1C - Logical right shift operation
84    SHR,
85    /// Opcode 0x1D - Arithmetic (signed) right shift operation
86    SAR,
87
88    // 0x1E - 0x1F are invalid
89
90    // 0x20 range - crypto.
91    /// Opcode 0x20 - Compute Keccak-256 hash
92    #[serde(alias = "KECCAK256")]
93    SHA3 = 0x20,
94
95    // 0x21 - 0x2F are invalid
96
97    // 0x30 range - closure state.
98    /// Opcode 0x30 - Get address of currently executing account
99    ADDRESS = 0x30,
100    /// Opcode 0x31 - Get address of currently executing account
101    BALANCE,
102    /// Opcode 0x32 - Get execution origination address
103    ORIGIN,
104    /// Opcode 0x33 - Get caller address
105    CALLER,
106    /// Opcode 0x34 - Get deposited value by the instruction/transaction responsible for this
107    /// execution
108    CALLVALUE,
109    /// Opcode 0x35 - Get input data of current environment
110    CALLDATALOAD,
111    /// Opcode 0x36 - Get size of input data in current environment
112    CALLDATASIZE,
113    /// Opcode 0x37 - Copy input data in current environment to memory
114    CALLDATACOPY,
115    /// Opcode 0x38 - Get size of code running in current environment
116    CODESIZE,
117    /// Opcode 0x39 - Copy code running in current environment to memory
118    CODECOPY,
119    /// Opcode 0x3A - Get price of gas in current environment
120    GASPRICE,
121    /// Opcode 0x3B - Get size of an account’s code
122    EXTCODESIZE,
123    /// Opcode 0x3C - Copy an account’s code to memory
124    EXTCODECOPY,
125    /// Opcode 0x3D - Get size of output data from the previous call from the current environment
126    RETURNDATASIZE,
127    /// Opcode 0x3E - Copy output data from the previous call to memory
128    RETURNDATACOPY,
129    /// Opcode 0x3F - Get hash of an account’s code
130    EXTCODEHASH,
131
132    // 0x40 range - block operations.
133    /// Opcode 0x40 - Get the hash of one of the 256 most recent complete blocks
134    BLOCKHASH = 0x40,
135    /// Opcode 0x41 - Get the block’s beneficiary address
136    COINBASE,
137    /// Opcode 0x42 - Get the block’s timestamp
138    TIMESTAMP,
139    /// Opcode 0x43 - Get the block’s number
140    NUMBER,
141    /// Opcode 0x44 - Get the block’s difficulty
142    #[serde(alias = "PREVRANDAO", alias = "RANDOM")]
143    #[strum(to_string = "DIFFICULTY", serialize = "PREVRANDAO", serialize = "RANDOM")]
144    DIFFICULTY,
145    /// Opcode 0x45 - Get the block’s gas limit
146    GASLIMIT,
147    /// Opcode 0x46 - Get the chain ID
148    CHAINID,
149    /// Opcode 0x47 - Get balance of currently executing account
150    SELFBALANCE,
151    /// Opcode 0x48 - Get the base fee
152    BASEFEE,
153
154    // 0x49 - 0x4F are invalid
155
156    // 0x50 range - 'storage' and execution.
157    /// Opcode 0x50 - Remove item from stack
158    POP = 0x50,
159    /// Opcode 0x51 - Load word from memory
160    MLOAD,
161    /// Opcode 0x52 - Save word to memory
162    MSTORE,
163    /// Opcode 0x53 - Save byte to memory
164    MSTORE8,
165    /// Opcode 0x54 - Load word from storage
166    SLOAD,
167    /// Opcode 0x55 - Save word to storage
168    SSTORE,
169    /// Opcode 0x56 - Alter the program counter
170    JUMP,
171    /// Opcode 0x57 - Conditionally alter the program counter
172    JUMPI,
173    /// Opcode 0x58 - Get the value of the program counter prior to the increment corresponding to
174    /// this instruction
175    PC,
176    /// Opcode 0x59 - Get the size of active memory in bytes
177    MSIZE,
178    /// Opcode 0x5A - Get the amount of available gas, including the corresponding reduction for
179    /// the cost of this instruction
180    GAS,
181    /// Opcode 0x5B - Mark a valid destination for jumps
182    JUMPDEST,
183
184    // 0x5C - 0x5E are invalid
185
186    // 0x5F range - pushes.
187    /// Opcode 0x5F - Place the constant value 0 on stack
188    PUSH0 = 0x5f,
189    /// Opcode 0x60 - Place 1 byte item on stack
190    PUSH1 = 0x60,
191    /// Opcode 0x61 - Place 2 byte item on stack
192    PUSH2,
193    /// Opcode 0x62 - Place 3 byte item on stack
194    PUSH3,
195    /// Opcode 0x63 - Place 4 byte item on stack
196    PUSH4,
197    /// Opcode 0x64 - Place 5 byte item on stack
198    PUSH5,
199    /// Opcode 0x65 - Place 6 byte item on stack
200    PUSH6,
201    /// Opcode 0x66 - Place 7 byte item on stack
202    PUSH7,
203    /// Opcode 0x67 - Place 8 byte item on stack
204    PUSH8,
205    /// Opcode 0x68 - Place 9 byte item on stack
206    PUSH9,
207    /// Opcode 0x69 - Place 10 byte item on stack
208    PUSH10,
209    /// Opcode 0x6A - Place 11 byte item on stack
210    PUSH11,
211    /// Opcode 0x6B - Place 12 byte item on stack
212    PUSH12,
213    /// Opcode 0x6C - Place 13 byte item on stack
214    PUSH13,
215    /// Opcode 0x6D - Place 14 byte item on stack
216    PUSH14,
217    /// Opcode 0x6E - Place 15 byte item on stack
218    PUSH15,
219    /// Opcode 0x6F - Place 16 byte item on stack
220    PUSH16,
221    /// Opcode 0x70 - Place 17 byte item on stack
222    PUSH17,
223    /// Opcode 0x71 - Place 18 byte item on stack
224    PUSH18,
225    /// Opcode 0x72 - Place 19 byte item on stack
226    PUSH19,
227    /// Opcode 0x73 - Place 20 byte item on stack
228    PUSH20,
229    /// Opcode 0x74 - Place 21 byte item on stack
230    PUSH21,
231    /// Opcode 0x75 - Place 22 byte item on stack
232    PUSH22,
233    /// Opcode 0x76 - Place 23 byte item on stack
234    PUSH23,
235    /// Opcode 0x77 - Place 24 byte item on stack
236    PUSH24,
237    /// Opcode 0x78 - Place 25 byte item on stack
238    PUSH25,
239    /// Opcode 0x79 - Place 26 byte item on stack
240    PUSH26,
241    /// Opcode 0x7A - Place 27 byte item on stack
242    PUSH27,
243    /// Opcode 0x7B - Place 28 byte item on stack
244    PUSH28,
245    /// Opcode 0x7C - Place 29 byte item on stack
246    PUSH29,
247    /// Opcode 0x7D - Place 30 byte item on stack
248    PUSH30,
249    /// Opcode 0x7E - Place 31 byte item on stack
250    PUSH31,
251    /// Opcode 0x7F - Place 32 byte item on stack
252    PUSH32,
253
254    // 0x80 range - dups.
255    /// Opcode 0x80 - Duplicate 1st stack item
256    DUP1 = 0x80,
257    /// Opcode 0x81 - Duplicate 2nd stack item
258    DUP2,
259    /// Opcode 0x82 - Duplicate 3rd stack item
260    DUP3,
261    /// Opcode 0x83 - Duplicate 4th stack item
262    DUP4,
263    /// Opcode 0x84 - Duplicate 5th stack item
264    DUP5,
265    /// Opcode 0x85 - Duplicate 6th stack item
266    DUP6,
267    /// Opcode 0x86 - Duplicate 7th stack item
268    DUP7,
269    /// Opcode 0x87 - Duplicate 8th stack item
270    DUP8,
271    /// Opcode 0x88 - Duplicate 9th stack item
272    DUP9,
273    /// Opcode 0x89 - Duplicate 10th stack item
274    DUP10,
275    /// Opcode 0x8A - Duplicate 11th stack item
276    DUP11,
277    /// Opcode 0x8B - Duplicate 12th stack item
278    DUP12,
279    /// Opcode 0x8C - Duplicate 13th stack item
280    DUP13,
281    /// Opcode 0x8D - Duplicate 14th stack item
282    DUP14,
283    /// Opcode 0x8E - Duplicate 15th stack item
284    DUP15,
285    /// Opcode 0x8F - Duplicate 16th stack item
286    DUP16,
287
288    // 0x90 range - swaps.
289    /// Opcode 0x90 - Exchange 1st and 2nd stack items
290    SWAP1 = 0x90,
291    /// Opcode 0x91 - Exchange 1st and 3rd stack items
292    SWAP2,
293    /// Opcode 0x92 - Exchange 1st and 4th stack items
294    SWAP3,
295    /// Opcode 0x93 - Exchange 1st and 5th stack items
296    SWAP4,
297    /// Opcode 0x94 - Exchange 1st and 6th stack items
298    SWAP5,
299    /// Opcode 0x95 - Exchange 1st and 7th stack items
300    SWAP6,
301    /// Opcode 0x96 - Exchange 1st and 8th stack items
302    SWAP7,
303    /// Opcode 0x97 - Exchange 1st and 9th stack items
304    SWAP8,
305    /// Opcode 0x98 - Exchange 1st and 10th stack items
306    SWAP9,
307    /// Opcode 0x99 - Exchange 1st and 11th stack items
308    SWAP10,
309    /// Opcode 0x9A - Exchange 1st and 12th stack items
310    SWAP11,
311    /// Opcode 0x9B - Exchange 1st and 13th stack items
312    SWAP12,
313    /// Opcode 0x9C - Exchange 1st and 14th stack items
314    SWAP13,
315    /// Opcode 0x9D - Exchange 1st and 15th stack items
316    SWAP14,
317    /// Opcode 0x9E - Exchange 1st and 16th stack items
318    SWAP15,
319    /// Opcode 0x9F - Exchange 1st and 17th stack items
320    SWAP16,
321
322    // 0xA0 range - logging ops.
323    /// Opcode 0xA0 - Append log record with one topic
324    LOG0 = 0xa0,
325    /// Opcode 0xA1 - Append log record with two topics
326    LOG1,
327    /// Opcode 0xA2 - Append log record with three topics
328    LOG2,
329    /// Opcode 0xA3 - Append log record with four topics
330    LOG3,
331    /// Opcode 0xA4 - Append log record with five topics
332    LOG4,
333
334    // 0xA5 - 0xEF are invalid
335
336    // 0xF0 range - closures.
337    /// Opcode 0xF0 - Create a new account with associated code
338    CREATE = 0xf0,
339    /// Opcode 0xF1 - Message-call into an account
340    CALL,
341    /// Opcode 0xF2 - Message-call into this account with alternative account’s code
342    CALLCODE,
343    /// Opcode 0xF3 - Halt execution returning output data
344    RETURN,
345    /// Opcode 0xF4 - Message-call into this account with an alternative account’s code, but
346    /// persisting the current values for sender and value
347    DELEGATECALL,
348    /// Opcode 0xF5 - Create a new account with associated code at a predictable address
349    CREATE2,
350
351    // 0xF6 - 0xF9 are invalid
352
353    // 0xFA range - closures
354    /// Opcode 0xFA - Static message-call into an account
355    STATICCALL = 0xfa,
356
357    // 0xFB - 0xFC are invalid
358
359    // 0xfd range - closures
360    /// Opcode 0xFD - Halt execution reverting state changes but returning data and remaining gas
361    REVERT = 0xfd,
362    /// Opcode 0xFE - Designated invalid instruction
363    INVALID = 0xfe,
364    /// Opcode 0xFF - Halt execution and register account for later deletion
365    SELFDESTRUCT = 0xff,
366}
367
368// See comment in ./chain.rs
369#[allow(clippy::derivable_impls)]
370impl Default for Opcode {
371    fn default() -> Self {
372        Opcode::INVALID
373    }
374}
375
376impl From<Opcode> for u8 {
377    fn from(value: Opcode) -> Self {
378        value as u8
379    }
380}
381
382#[cfg(test)]
383mod tests {
384    use super::*;
385    use serde::de::{value::StrDeserializer, IntoDeserializer};
386    use std::collections::HashSet;
387
388    // Taken from REVM:
389    // https://github.com/bluealloy/revm/blob/f8ff6b330dce126ab9359ab8dde02ba1d09b9306/crates/interpreter/src/instructions/opcode.rs#L184
390    const OPCODE_JUMPMAP: [Option<&'static str>; 256] = [
391        /* 0x00 */ Some("STOP"),
392        /* 0x01 */ Some("ADD"),
393        /* 0x02 */ Some("MUL"),
394        /* 0x03 */ Some("SUB"),
395        /* 0x04 */ Some("DIV"),
396        /* 0x05 */ Some("SDIV"),
397        /* 0x06 */ Some("MOD"),
398        /* 0x07 */ Some("SMOD"),
399        /* 0x08 */ Some("ADDMOD"),
400        /* 0x09 */ Some("MULMOD"),
401        /* 0x0a */ Some("EXP"),
402        /* 0x0b */ Some("SIGNEXTEND"),
403        /* 0x0c */ None,
404        /* 0x0d */ None,
405        /* 0x0e */ None,
406        /* 0x0f */ None,
407        /* 0x10 */ Some("LT"),
408        /* 0x11 */ Some("GT"),
409        /* 0x12 */ Some("SLT"),
410        /* 0x13 */ Some("SGT"),
411        /* 0x14 */ Some("EQ"),
412        /* 0x15 */ Some("ISZERO"),
413        /* 0x16 */ Some("AND"),
414        /* 0x17 */ Some("OR"),
415        /* 0x18 */ Some("XOR"),
416        /* 0x19 */ Some("NOT"),
417        /* 0x1a */ Some("BYTE"),
418        /* 0x1b */ Some("SHL"),
419        /* 0x1c */ Some("SHR"),
420        /* 0x1d */ Some("SAR"),
421        /* 0x1e */ None,
422        /* 0x1f */ None,
423        /* 0x20 */ Some("SHA3"),
424        /* 0x21 */ None,
425        /* 0x22 */ None,
426        /* 0x23 */ None,
427        /* 0x24 */ None,
428        /* 0x25 */ None,
429        /* 0x26 */ None,
430        /* 0x27 */ None,
431        /* 0x28 */ None,
432        /* 0x29 */ None,
433        /* 0x2a */ None,
434        /* 0x2b */ None,
435        /* 0x2c */ None,
436        /* 0x2d */ None,
437        /* 0x2e */ None,
438        /* 0x2f */ None,
439        /* 0x30 */ Some("ADDRESS"),
440        /* 0x31 */ Some("BALANCE"),
441        /* 0x32 */ Some("ORIGIN"),
442        /* 0x33 */ Some("CALLER"),
443        /* 0x34 */ Some("CALLVALUE"),
444        /* 0x35 */ Some("CALLDATALOAD"),
445        /* 0x36 */ Some("CALLDATASIZE"),
446        /* 0x37 */ Some("CALLDATACOPY"),
447        /* 0x38 */ Some("CODESIZE"),
448        /* 0x39 */ Some("CODECOPY"),
449        /* 0x3a */ Some("GASPRICE"),
450        /* 0x3b */ Some("EXTCODESIZE"),
451        /* 0x3c */ Some("EXTCODECOPY"),
452        /* 0x3d */ Some("RETURNDATASIZE"),
453        /* 0x3e */ Some("RETURNDATACOPY"),
454        /* 0x3f */ Some("EXTCODEHASH"),
455        /* 0x40 */ Some("BLOCKHASH"),
456        /* 0x41 */ Some("COINBASE"),
457        /* 0x42 */ Some("TIMESTAMP"),
458        /* 0x43 */ Some("NUMBER"),
459        /* 0x44 */ Some("DIFFICULTY"),
460        /* 0x45 */ Some("GASLIMIT"),
461        /* 0x46 */ Some("CHAINID"),
462        /* 0x47 */ Some("SELFBALANCE"),
463        /* 0x48 */ Some("BASEFEE"),
464        /* 0x49 */ None,
465        /* 0x4a */ None,
466        /* 0x4b */ None,
467        /* 0x4c */ None,
468        /* 0x4d */ None,
469        /* 0x4e */ None,
470        /* 0x4f */ None,
471        /* 0x50 */ Some("POP"),
472        /* 0x51 */ Some("MLOAD"),
473        /* 0x52 */ Some("MSTORE"),
474        /* 0x53 */ Some("MSTORE8"),
475        /* 0x54 */ Some("SLOAD"),
476        /* 0x55 */ Some("SSTORE"),
477        /* 0x56 */ Some("JUMP"),
478        /* 0x57 */ Some("JUMPI"),
479        /* 0x58 */ Some("PC"),
480        /* 0x59 */ Some("MSIZE"),
481        /* 0x5a */ Some("GAS"),
482        /* 0x5b */ Some("JUMPDEST"),
483        /* 0x5c */ None,
484        /* 0x5d */ None,
485        /* 0x5e */ None,
486        /* 0x5f */ Some("PUSH0"),
487        /* 0x60 */ Some("PUSH1"),
488        /* 0x61 */ Some("PUSH2"),
489        /* 0x62 */ Some("PUSH3"),
490        /* 0x63 */ Some("PUSH4"),
491        /* 0x64 */ Some("PUSH5"),
492        /* 0x65 */ Some("PUSH6"),
493        /* 0x66 */ Some("PUSH7"),
494        /* 0x67 */ Some("PUSH8"),
495        /* 0x68 */ Some("PUSH9"),
496        /* 0x69 */ Some("PUSH10"),
497        /* 0x6a */ Some("PUSH11"),
498        /* 0x6b */ Some("PUSH12"),
499        /* 0x6c */ Some("PUSH13"),
500        /* 0x6d */ Some("PUSH14"),
501        /* 0x6e */ Some("PUSH15"),
502        /* 0x6f */ Some("PUSH16"),
503        /* 0x70 */ Some("PUSH17"),
504        /* 0x71 */ Some("PUSH18"),
505        /* 0x72 */ Some("PUSH19"),
506        /* 0x73 */ Some("PUSH20"),
507        /* 0x74 */ Some("PUSH21"),
508        /* 0x75 */ Some("PUSH22"),
509        /* 0x76 */ Some("PUSH23"),
510        /* 0x77 */ Some("PUSH24"),
511        /* 0x78 */ Some("PUSH25"),
512        /* 0x79 */ Some("PUSH26"),
513        /* 0x7a */ Some("PUSH27"),
514        /* 0x7b */ Some("PUSH28"),
515        /* 0x7c */ Some("PUSH29"),
516        /* 0x7d */ Some("PUSH30"),
517        /* 0x7e */ Some("PUSH31"),
518        /* 0x7f */ Some("PUSH32"),
519        /* 0x80 */ Some("DUP1"),
520        /* 0x81 */ Some("DUP2"),
521        /* 0x82 */ Some("DUP3"),
522        /* 0x83 */ Some("DUP4"),
523        /* 0x84 */ Some("DUP5"),
524        /* 0x85 */ Some("DUP6"),
525        /* 0x86 */ Some("DUP7"),
526        /* 0x87 */ Some("DUP8"),
527        /* 0x88 */ Some("DUP9"),
528        /* 0x89 */ Some("DUP10"),
529        /* 0x8a */ Some("DUP11"),
530        /* 0x8b */ Some("DUP12"),
531        /* 0x8c */ Some("DUP13"),
532        /* 0x8d */ Some("DUP14"),
533        /* 0x8e */ Some("DUP15"),
534        /* 0x8f */ Some("DUP16"),
535        /* 0x90 */ Some("SWAP1"),
536        /* 0x91 */ Some("SWAP2"),
537        /* 0x92 */ Some("SWAP3"),
538        /* 0x93 */ Some("SWAP4"),
539        /* 0x94 */ Some("SWAP5"),
540        /* 0x95 */ Some("SWAP6"),
541        /* 0x96 */ Some("SWAP7"),
542        /* 0x97 */ Some("SWAP8"),
543        /* 0x98 */ Some("SWAP9"),
544        /* 0x99 */ Some("SWAP10"),
545        /* 0x9a */ Some("SWAP11"),
546        /* 0x9b */ Some("SWAP12"),
547        /* 0x9c */ Some("SWAP13"),
548        /* 0x9d */ Some("SWAP14"),
549        /* 0x9e */ Some("SWAP15"),
550        /* 0x9f */ Some("SWAP16"),
551        /* 0xa0 */ Some("LOG0"),
552        /* 0xa1 */ Some("LOG1"),
553        /* 0xa2 */ Some("LOG2"),
554        /* 0xa3 */ Some("LOG3"),
555        /* 0xa4 */ Some("LOG4"),
556        /* 0xa5 */ None,
557        /* 0xa6 */ None,
558        /* 0xa7 */ None,
559        /* 0xa8 */ None,
560        /* 0xa9 */ None,
561        /* 0xaa */ None,
562        /* 0xab */ None,
563        /* 0xac */ None,
564        /* 0xad */ None,
565        /* 0xae */ None,
566        /* 0xaf */ None,
567        /* 0xb0 */ None,
568        /* 0xb1 */ None,
569        /* 0xb2 */ None,
570        /* 0xb3 */ None,
571        /* 0xb4 */ None,
572        /* 0xb5 */ None,
573        /* 0xb6 */ None,
574        /* 0xb7 */ None,
575        /* 0xb8 */ None,
576        /* 0xb9 */ None,
577        /* 0xba */ None,
578        /* 0xbb */ None,
579        /* 0xbc */ None,
580        /* 0xbd */ None,
581        /* 0xbe */ None,
582        /* 0xbf */ None,
583        /* 0xc0 */ None,
584        /* 0xc1 */ None,
585        /* 0xc2 */ None,
586        /* 0xc3 */ None,
587        /* 0xc4 */ None,
588        /* 0xc5 */ None,
589        /* 0xc6 */ None,
590        /* 0xc7 */ None,
591        /* 0xc8 */ None,
592        /* 0xc9 */ None,
593        /* 0xca */ None,
594        /* 0xcb */ None,
595        /* 0xcc */ None,
596        /* 0xcd */ None,
597        /* 0xce */ None,
598        /* 0xcf */ None,
599        /* 0xd0 */ None,
600        /* 0xd1 */ None,
601        /* 0xd2 */ None,
602        /* 0xd3 */ None,
603        /* 0xd4 */ None,
604        /* 0xd5 */ None,
605        /* 0xd6 */ None,
606        /* 0xd7 */ None,
607        /* 0xd8 */ None,
608        /* 0xd9 */ None,
609        /* 0xda */ None,
610        /* 0xdb */ None,
611        /* 0xdc */ None,
612        /* 0xdd */ None,
613        /* 0xde */ None,
614        /* 0xdf */ None,
615        /* 0xe0 */ None,
616        /* 0xe1 */ None,
617        /* 0xe2 */ None,
618        /* 0xe3 */ None,
619        /* 0xe4 */ None,
620        /* 0xe5 */ None,
621        /* 0xe6 */ None,
622        /* 0xe7 */ None,
623        /* 0xe8 */ None,
624        /* 0xe9 */ None,
625        /* 0xea */ None,
626        /* 0xeb */ None,
627        /* 0xec */ None,
628        /* 0xed */ None,
629        /* 0xee */ None,
630        /* 0xef */ None,
631        /* 0xf0 */ Some("CREATE"),
632        /* 0xf1 */ Some("CALL"),
633        /* 0xf2 */ Some("CALLCODE"),
634        /* 0xf3 */ Some("RETURN"),
635        /* 0xf4 */ Some("DELEGATECALL"),
636        /* 0xf5 */ Some("CREATE2"),
637        /* 0xf6 */ None,
638        /* 0xf7 */ None,
639        /* 0xf8 */ None,
640        /* 0xf9 */ None,
641        /* 0xfa */ Some("STATICCALL"),
642        /* 0xfb */ None,
643        /* 0xfc */ None,
644        /* 0xfd */ Some("REVERT"),
645        /* 0xfe */ Some("INVALID"),
646        /* 0xff */ Some("SELFDESTRUCT"),
647    ];
648
649    #[test]
650    fn all() {
651        let len = Opcode::COUNT;
652        let mut found = HashSet::with_capacity(len);
653
654        for (i, mnemonic) in OPCODE_JUMPMAP.iter().enumerate() {
655            let Some(mnemonic) = *mnemonic else { continue };
656            let parsed = mnemonic.parse::<Opcode>().unwrap();
657            if !found.insert(parsed) {
658                panic!("Duplicate Opcode: {mnemonic:?} => {parsed}")
659            }
660
661            assert_eq!(i, parsed as usize);
662            assert_eq!(Opcode::try_from(i as u8).unwrap(), parsed);
663            assert_eq!(OPCODE_JUMPMAP[i].unwrap(), mnemonic);
664
665            // strum
666            assert_eq!(parsed.as_ref(), mnemonic);
667            assert_eq!(parsed.to_string(), mnemonic);
668
669            // serde
670            let de: StrDeserializer<'_, serde::de::value::Error> = mnemonic.into_deserializer();
671            let serde = Opcode::deserialize(de).unwrap();
672            assert_eq!(serde, parsed);
673            assert_eq!(serde_json::to_string(&serde).unwrap(), format!("\"{mnemonic}\""));
674        }
675
676        assert_eq!(found.len(), len);
677    }
678}