1pub use self::Instruction::*;
24
25use cfx_vm_types::Spec;
26
27macro_rules! enum_with_from_u8 {
28 (
29 $( #[$enum_attr:meta] )*
30 pub enum $name:ident {
31 $( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),+,
32 }
33 ) => {
34 $( #[$enum_attr] )*
35 pub enum $name {
36 $( $( #[$variant_attr] )* $variant = $discriminator ),+,
37 }
38
39 impl $name {
40 #[doc = "Convert from u8 to the given enum"]
41 pub fn from_u8(value: u8) -> Option<Self> {
42 match value {
43 $( $discriminator => Some($variant) ),+,
44 _ => None,
45 }
46 }
47 }
48 };
49}
50
51enum_with_from_u8! {
52 #[doc = "Virtual machine bytecode instruction."]
53 #[repr(u8)]
54 #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug, Hash)]
55 pub enum Instruction {
56 #[doc = "halts execution"]
57 STOP = 0x00,
58 #[doc = "addition operation"]
59 ADD = 0x01,
60 #[doc = "multiplication operation"]
61 MUL = 0x02,
62 #[doc = "subtraction operation"]
63 SUB = 0x03,
64 #[doc = "integer division operation"]
65 DIV = 0x04,
66 #[doc = "signed integer division operation"]
67 SDIV = 0x05,
68 #[doc = "modulo remainder operation"]
69 MOD = 0x06,
70 #[doc = "signed modulo remainder operation"]
71 SMOD = 0x07,
72 #[doc = "unsigned modular addition"]
73 ADDMOD = 0x08,
74 #[doc = "unsigned modular multiplication"]
75 MULMOD = 0x09,
76 #[doc = "exponential operation"]
77 EXP = 0x0a,
78 #[doc = "extend length of signed integer"]
79 SIGNEXTEND = 0x0b,
80
81 #[doc = "less-than comparison"]
82 LT = 0x10,
83 #[doc = "greater-than comparison"]
84 GT = 0x11,
85 #[doc = "signed less-than comparison"]
86 SLT = 0x12,
87 #[doc = "signed greater-than comparison"]
88 SGT = 0x13,
89 #[doc = "equality comparison"]
90 EQ = 0x14,
91 #[doc = "simple not operator"]
92 ISZERO = 0x15,
93 #[doc = "bitwise AND operation"]
94 AND = 0x16,
95 #[doc = "bitwise OR operation"]
96 OR = 0x17,
97 #[doc = "bitwise XOR operation"]
98 XOR = 0x18,
99 #[doc = "bitwise NOT operation"]
100 NOT = 0x19,
101 #[doc = "retrieve single byte from word"]
102 BYTE = 0x1a,
103 #[doc = "shift left operation"]
104 SHL = 0x1b,
105 #[doc = "logical shift right operation"]
106 SHR = 0x1c,
107 #[doc = "arithmetic shift right operation"]
108 SAR = 0x1d,
109 #[doc = "count leading zeros"]
110 CLZ = 0x1e,
111
112 #[doc = "compute SHA3-256 hash"]
113 SHA3 = 0x20,
114
115 #[doc = "get address of currently executing account"]
116 ADDRESS = 0x30,
117 #[doc = "get balance of the given account"]
118 BALANCE = 0x31,
119 #[doc = "get execution origination address"]
120 ORIGIN = 0x32,
121 #[doc = "get caller address"]
122 CALLER = 0x33,
123 #[doc = "get deposited value by the instruction/transaction responsible for this execution"]
124 CALLVALUE = 0x34,
125 #[doc = "get input data of current environment"]
126 CALLDATALOAD = 0x35,
127 #[doc = "get size of input data in current environment"]
128 CALLDATASIZE = 0x36,
129 #[doc = "copy input data in current environment to memory"]
130 CALLDATACOPY = 0x37,
131 #[doc = "get size of code running in current environment"]
132 CODESIZE = 0x38,
133 #[doc = "copy code running in current environment to memory"]
134 CODECOPY = 0x39,
135 #[doc = "get price of gas in current environment"]
136 GASPRICE = 0x3a,
137 #[doc = "get external code size (from another contract)"]
138 EXTCODESIZE = 0x3b,
139 #[doc = "copy external code (from another contract)"]
140 EXTCODECOPY = 0x3c,
141 #[doc = "get the size of the return data buffer for the last call"]
142 RETURNDATASIZE = 0x3d,
143 #[doc = "copy return data buffer to memory"]
144 RETURNDATACOPY = 0x3e,
145 #[doc = "return the keccak256 hash of contract code"]
146 EXTCODEHASH = 0x3f,
147
148 #[doc = "get hash of most recent complete block"]
149 BLOCKHASH = 0x40,
150 #[doc = "get the block's coinbase address"]
151 COINBASE = 0x41,
152 #[doc = "get the block's timestamp"]
153 TIMESTAMP = 0x42,
154 #[doc = "get the block's number"]
155 NUMBER = 0x43,
156 #[doc = "get the block's difficulty"]
157 DIFFICULTY = 0x44,
158 #[doc = "get the block's gas limit"]
159 GASLIMIT = 0x45,
160 #[doc = "get chain ID"]
161 CHAINID = 0x46,
162 #[doc = "get balance of own account"]
163 SELFBALANCE = 0x47,
164 #[doc = "base fee for EIP-1559 (EIP-3198)"]
165 BASEFEE = 0x48,
166 #[doc = "blob hash for EIP-4844 (dummy)"]
167 BLOBHASH=0x49,
168 #[doc = "blob base fee for EIP-4844 (dummy)"]
169 BLOBBASEFEE=0x4a,
170
171 #[doc = "remove item from stack"]
172 POP = 0x50,
173 #[doc = "load word from memory"]
174 MLOAD = 0x51,
175 #[doc = "save word to memory"]
176 MSTORE = 0x52,
177 #[doc = "save byte to memory"]
178 MSTORE8 = 0x53,
179 #[doc = "load word from storage"]
180 SLOAD = 0x54,
181 #[doc = "save word to storage"]
182 SSTORE = 0x55,
183 #[doc = "alter the program counter"]
184 JUMP = 0x56,
185 #[doc = "conditionally alter the program counter"]
186 JUMPI = 0x57,
187 #[doc = "get the program counter"]
188 PC = 0x58,
189 #[doc = "get the size of active memory"]
190 MSIZE = 0x59,
191 #[doc = "get the amount of available gas"]
192 GAS = 0x5a,
193 #[doc = "set a potential jump destination"]
194 JUMPDEST = 0x5b,
195 #[doc = "Marks the entry point to a subroutine (pre cip-142). load word from transient storage (after cip-142)"]
196 #[allow(non_camel_case_types)]
197 BEGINSUB_TLOAD = 0x5c,
198 #[doc = "Returns from a subroutine (pre cip-142). store word from transient storage (after cip-142)"]
199 #[allow(non_camel_case_types)]
200 RETURNSUB_TSTORE = 0x5d,
201 #[doc = "Jumps to a defined BEGINSUB subroutine (pre cip-143). copy data from one memory range to another (after cip-143)"]
202 #[allow(non_camel_case_types)]
203 JUMPSUB_MCOPY = 0x5e,
204
205 #[doc = "place zero item on stack (EIP-3855/CIP-119)"]
206 PUSH0 = 0x5f,
207 #[doc = "place 1 byte item on stack"]
208 PUSH1 = 0x60,
209 #[doc = "place 2 byte item on stack"]
210 PUSH2 = 0x61,
211 #[doc = "place 3 byte item on stack"]
212 PUSH3 = 0x62,
213 #[doc = "place 4 byte item on stack"]
214 PUSH4 = 0x63,
215 #[doc = "place 5 byte item on stack"]
216 PUSH5 = 0x64,
217 #[doc = "place 6 byte item on stack"]
218 PUSH6 = 0x65,
219 #[doc = "place 7 byte item on stack"]
220 PUSH7 = 0x66,
221 #[doc = "place 8 byte item on stack"]
222 PUSH8 = 0x67,
223 #[doc = "place 9 byte item on stack"]
224 PUSH9 = 0x68,
225 #[doc = "place 10 byte item on stack"]
226 PUSH10 = 0x69,
227 #[doc = "place 11 byte item on stack"]
228 PUSH11 = 0x6a,
229 #[doc = "place 12 byte item on stack"]
230 PUSH12 = 0x6b,
231 #[doc = "place 13 byte item on stack"]
232 PUSH13 = 0x6c,
233 #[doc = "place 14 byte item on stack"]
234 PUSH14 = 0x6d,
235 #[doc = "place 15 byte item on stack"]
236 PUSH15 = 0x6e,
237 #[doc = "place 16 byte item on stack"]
238 PUSH16 = 0x6f,
239 #[doc = "place 17 byte item on stack"]
240 PUSH17 = 0x70,
241 #[doc = "place 18 byte item on stack"]
242 PUSH18 = 0x71,
243 #[doc = "place 19 byte item on stack"]
244 PUSH19 = 0x72,
245 #[doc = "place 20 byte item on stack"]
246 PUSH20 = 0x73,
247 #[doc = "place 21 byte item on stack"]
248 PUSH21 = 0x74,
249 #[doc = "place 22 byte item on stack"]
250 PUSH22 = 0x75,
251 #[doc = "place 23 byte item on stack"]
252 PUSH23 = 0x76,
253 #[doc = "place 24 byte item on stack"]
254 PUSH24 = 0x77,
255 #[doc = "place 25 byte item on stack"]
256 PUSH25 = 0x78,
257 #[doc = "place 26 byte item on stack"]
258 PUSH26 = 0x79,
259 #[doc = "place 27 byte item on stack"]
260 PUSH27 = 0x7a,
261 #[doc = "place 28 byte item on stack"]
262 PUSH28 = 0x7b,
263 #[doc = "place 29 byte item on stack"]
264 PUSH29 = 0x7c,
265 #[doc = "place 30 byte item on stack"]
266 PUSH30 = 0x7d,
267 #[doc = "place 31 byte item on stack"]
268 PUSH31 = 0x7e,
269 #[doc = "place 32 byte item on stack"]
270 PUSH32 = 0x7f,
271
272 #[doc = "copies the highest item in the stack to the top of the stack"]
273 DUP1 = 0x80,
274 #[doc = "copies the second highest item in the stack to the top of the stack"]
275 DUP2 = 0x81,
276 #[doc = "copies the third highest item in the stack to the top of the stack"]
277 DUP3 = 0x82,
278 #[doc = "copies the 4th highest item in the stack to the top of the stack"]
279 DUP4 = 0x83,
280 #[doc = "copies the 5th highest item in the stack to the top of the stack"]
281 DUP5 = 0x84,
282 #[doc = "copies the 6th highest item in the stack to the top of the stack"]
283 DUP6 = 0x85,
284 #[doc = "copies the 7th highest item in the stack to the top of the stack"]
285 DUP7 = 0x86,
286 #[doc = "copies the 8th highest item in the stack to the top of the stack"]
287 DUP8 = 0x87,
288 #[doc = "copies the 9th highest item in the stack to the top of the stack"]
289 DUP9 = 0x88,
290 #[doc = "copies the 10th highest item in the stack to the top of the stack"]
291 DUP10 = 0x89,
292 #[doc = "copies the 11th highest item in the stack to the top of the stack"]
293 DUP11 = 0x8a,
294 #[doc = "copies the 12th highest item in the stack to the top of the stack"]
295 DUP12 = 0x8b,
296 #[doc = "copies the 13th highest item in the stack to the top of the stack"]
297 DUP13 = 0x8c,
298 #[doc = "copies the 14th highest item in the stack to the top of the stack"]
299 DUP14 = 0x8d,
300 #[doc = "copies the 15th highest item in the stack to the top of the stack"]
301 DUP15 = 0x8e,
302 #[doc = "copies the 16th highest item in the stack to the top of the stack"]
303 DUP16 = 0x8f,
304
305 #[doc = "swaps the highest and second highest value on the stack"]
306 SWAP1 = 0x90,
307 #[doc = "swaps the highest and third highest value on the stack"]
308 SWAP2 = 0x91,
309 #[doc = "swaps the highest and 4th highest value on the stack"]
310 SWAP3 = 0x92,
311 #[doc = "swaps the highest and 5th highest value on the stack"]
312 SWAP4 = 0x93,
313 #[doc = "swaps the highest and 6th highest value on the stack"]
314 SWAP5 = 0x94,
315 #[doc = "swaps the highest and 7th highest value on the stack"]
316 SWAP6 = 0x95,
317 #[doc = "swaps the highest and 8th highest value on the stack"]
318 SWAP7 = 0x96,
319 #[doc = "swaps the highest and 9th highest value on the stack"]
320 SWAP8 = 0x97,
321 #[doc = "swaps the highest and 10th highest value on the stack"]
322 SWAP9 = 0x98,
323 #[doc = "swaps the highest and 11th highest value on the stack"]
324 SWAP10 = 0x99,
325 #[doc = "swaps the highest and 12th highest value on the stack"]
326 SWAP11 = 0x9a,
327 #[doc = "swaps the highest and 13th highest value on the stack"]
328 SWAP12 = 0x9b,
329 #[doc = "swaps the highest and 14th highest value on the stack"]
330 SWAP13 = 0x9c,
331 #[doc = "swaps the highest and 15th highest value on the stack"]
332 SWAP14 = 0x9d,
333 #[doc = "swaps the highest and 16th highest value on the stack"]
334 SWAP15 = 0x9e,
335 #[doc = "swaps the highest and 17th highest value on the stack"]
336 SWAP16 = 0x9f,
337
338 #[doc = "Makes a log entry, no topics."]
339 LOG0 = 0xa0,
340 #[doc = "Makes a log entry, 1 topic."]
341 LOG1 = 0xa1,
342 #[doc = "Makes a log entry, 2 topics."]
343 LOG2 = 0xa2,
344 #[doc = "Makes a log entry, 3 topics."]
345 LOG3 = 0xa3,
346 #[doc = "Makes a log entry, 4 topics."]
347 LOG4 = 0xa4,
348
349 #[doc = "create a new account with associated code"]
350 CREATE = 0xf0,
351 #[doc = "message-call into an account"]
352 CALL = 0xf1,
353 #[doc = "message-call with another account's code only"]
354 CALLCODE = 0xf2,
355 #[doc = "halt execution returning output data"]
356 RETURN = 0xf3,
357 #[doc = "like CALLCODE but keeps caller's value and sender"]
358 DELEGATECALL = 0xf4,
359 #[doc = "create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160"]
360 CREATE2 = 0xf5,
361 #[doc = "like CALL but it does not take value, nor modify the state"]
362 STATICCALL = 0xfa,
363 #[doc = "stop execution and revert state changes. Return output data."]
364 REVERT = 0xfd,
365
366 #[doc = "halt execution and register account for later deletion"]
369 SUICIDE = 0xff,
370 }
371}
372
373impl Instruction {
374 pub fn is_push(&self) -> bool { *self >= PUSH1 && *self <= PUSH32 }
376
377 pub fn from_u8_versioned(value: u8, spec: &Spec) -> Option<Self> {
378 let mut instruction = Instruction::from_u8(value);
379 if instruction == Some(PUSH0) && !spec.cip119 {
380 instruction = None;
381 }
382 if instruction == Some(BASEFEE) && !spec.cip1559 {
383 instruction = None;
384 }
385 if instruction == Some(CLZ) && !spec.eip7939 {
386 instruction = None;
387 }
388 return instruction;
389 }
390
391 pub fn u8(self) -> u8 { self as u8 }
392
393 pub fn push_bytes(&self) -> Option<usize> {
396 if self.is_push() {
397 Some(((*self as u8) - (PUSH1 as u8) + 1) as usize)
398 } else {
399 None
400 }
401 }
402
403 pub fn dup_position(&self) -> Option<usize> {
406 if *self >= DUP1 && *self <= DUP16 {
407 Some(((*self as u8) - (DUP1 as u8)) as usize)
408 } else {
409 None
410 }
411 }
412
413 pub fn swap_position(&self) -> Option<usize> {
416 if *self >= SWAP1 && *self <= SWAP16 {
417 Some(((*self as u8) - (SWAP1 as u8) + 1) as usize)
418 } else {
419 None
420 }
421 }
422
423 pub fn log_topics(&self) -> Option<usize> {
426 if *self >= LOG0 && *self <= LOG4 {
427 Some(((*self as u8) - (LOG0 as u8)) as usize)
428 } else {
429 None
430 }
431 }
432
433 pub fn info<const CANCUN: bool>(
435 &self, cip645: bool, eip7939: bool,
436 ) -> &InstructionInfo {
437 let instrs = if !CANCUN {
438 &*INSTRUCTIONS
439 } else if !cip645 {
440 &*INSTRUCTIONS_CANCUN
441 } else if !eip7939 {
442 &*INSTRUCTIONS_CIP645
443 } else {
444 &*INSTRUCTIONS_EIP7939
445 };
446
447 instrs[*self as usize].as_ref().expect("A instruction is defined in Instruction enum, but it is not found in InstructionInfo struct; this indicates a logic failure in the code.")
448 }
449}
450
451#[derive(PartialEq, Clone, Copy)]
452pub enum GasPriceTier {
453 Zero,
455 Base,
457 VeryLow,
459 Low,
461 Mid,
463 High,
465 Ext,
467 Special,
469}
470
471impl GasPriceTier {
472 pub const fn idx(&self) -> usize {
474 match self {
475 &GasPriceTier::Zero => 0,
476 &GasPriceTier::Base => 1,
477 &GasPriceTier::VeryLow => 2,
478 &GasPriceTier::Low => 3,
479 &GasPriceTier::Mid => 4,
480 &GasPriceTier::High => 5,
481 &GasPriceTier::Ext => 6,
482 &GasPriceTier::Special => 7,
483 }
484 }
485}
486
487#[derive(Copy, Clone)]
489pub struct InstructionInfo {
490 pub name: &'static str,
492 pub args: usize,
494 pub ret: usize,
496 pub tier: GasPriceTier,
498}
499
500impl InstructionInfo {
501 pub fn new(
503 name: &'static str, args: usize, ret: usize, tier: GasPriceTier,
504 ) -> Self {
505 InstructionInfo {
506 name,
507 args,
508 ret,
509 tier,
510 }
511 }
512}
513
514lazy_static! {
515 pub static ref INSTRUCTIONS: [Option<InstructionInfo>; 0x100] = {
517 let mut arr = [None; 0x100];
518 arr[STOP as usize] = Some(InstructionInfo::new("STOP", 0, 0, GasPriceTier::Zero));
519 arr[ADD as usize] = Some(InstructionInfo::new("ADD", 2, 1, GasPriceTier::VeryLow));
520 arr[SUB as usize] = Some(InstructionInfo::new("SUB", 2, 1, GasPriceTier::VeryLow));
521 arr[MUL as usize] = Some(InstructionInfo::new("MUL", 2, 1, GasPriceTier::Low));
522 arr[DIV as usize] = Some(InstructionInfo::new("DIV", 2, 1, GasPriceTier::Low));
523 arr[SDIV as usize] = Some(InstructionInfo::new("SDIV", 2, 1, GasPriceTier::Low));
524 arr[MOD as usize] = Some(InstructionInfo::new("MOD", 2, 1, GasPriceTier::Low));
525 arr[SMOD as usize] = Some(InstructionInfo::new("SMOD", 2, 1, GasPriceTier::Low));
526 arr[EXP as usize] = Some(InstructionInfo::new("EXP", 2, 1, GasPriceTier::Special));
527 arr[NOT as usize] = Some(InstructionInfo::new("NOT", 1, 1, GasPriceTier::VeryLow));
528 arr[LT as usize] = Some(InstructionInfo::new("LT", 2, 1, GasPriceTier::VeryLow));
529 arr[GT as usize] = Some(InstructionInfo::new("GT", 2, 1, GasPriceTier::VeryLow));
530 arr[SLT as usize] = Some(InstructionInfo::new("SLT", 2, 1, GasPriceTier::VeryLow));
531 arr[SGT as usize] = Some(InstructionInfo::new("SGT", 2, 1, GasPriceTier::VeryLow));
532 arr[EQ as usize] = Some(InstructionInfo::new("EQ", 2, 1, GasPriceTier::VeryLow));
533 arr[ISZERO as usize] = Some(InstructionInfo::new("ISZERO", 1, 1, GasPriceTier::VeryLow));
534 arr[AND as usize] = Some(InstructionInfo::new("AND", 2, 1, GasPriceTier::VeryLow));
535 arr[OR as usize] = Some(InstructionInfo::new("OR", 2, 1, GasPriceTier::VeryLow));
536 arr[XOR as usize] = Some(InstructionInfo::new("XOR", 2, 1, GasPriceTier::VeryLow));
537 arr[BYTE as usize] = Some(InstructionInfo::new("BYTE", 2, 1, GasPriceTier::VeryLow));
538 arr[SHL as usize] = Some(InstructionInfo::new("SHL", 2, 1, GasPriceTier::VeryLow));
539 arr[SHR as usize] = Some(InstructionInfo::new("SHR", 2, 1, GasPriceTier::VeryLow));
540 arr[SAR as usize] = Some(InstructionInfo::new("SAR", 2, 1, GasPriceTier::VeryLow));
541 arr[ADDMOD as usize] = Some(InstructionInfo::new("ADDMOD", 3, 1, GasPriceTier::Mid));
542 arr[MULMOD as usize] = Some(InstructionInfo::new("MULMOD", 3, 1, GasPriceTier::Mid));
543 arr[SIGNEXTEND as usize] = Some(InstructionInfo::new("SIGNEXTEND", 2, 1, GasPriceTier::Low));
544 arr[RETURNDATASIZE as usize] = Some(InstructionInfo::new("RETURNDATASIZE", 0, 1, GasPriceTier::Base));
545 arr[RETURNDATACOPY as usize] = Some(InstructionInfo::new("RETURNDATACOPY", 3, 0, GasPriceTier::VeryLow));
546 arr[SHA3 as usize] = Some(InstructionInfo::new("SHA3", 2, 1, GasPriceTier::Special));
547 arr[ADDRESS as usize] = Some(InstructionInfo::new("ADDRESS", 0, 1, GasPriceTier::Base));
548 arr[BALANCE as usize] = Some(InstructionInfo::new("BALANCE", 1, 1, GasPriceTier::Special));
549 arr[ORIGIN as usize] = Some(InstructionInfo::new("ORIGIN", 0, 1, GasPriceTier::Base));
550 arr[CALLER as usize] = Some(InstructionInfo::new("CALLER", 0, 1, GasPriceTier::Base));
551 arr[CALLVALUE as usize] = Some(InstructionInfo::new("CALLVALUE", 0, 1, GasPriceTier::Base));
552 arr[CALLDATALOAD as usize] = Some(InstructionInfo::new("CALLDATALOAD", 1, 1, GasPriceTier::VeryLow));
553 arr[CALLDATASIZE as usize] = Some(InstructionInfo::new("CALLDATASIZE", 0, 1, GasPriceTier::Base));
554 arr[CALLDATACOPY as usize] = Some(InstructionInfo::new("CALLDATACOPY", 3, 0, GasPriceTier::VeryLow));
555 arr[EXTCODEHASH as usize] = Some(InstructionInfo::new("EXTCODEHASH", 1, 1, GasPriceTier::Special));
556 arr[CODESIZE as usize] = Some(InstructionInfo::new("CODESIZE", 0, 1, GasPriceTier::Base));
557 arr[CODECOPY as usize] = Some(InstructionInfo::new("CODECOPY", 3, 0, GasPriceTier::VeryLow));
558 arr[GASPRICE as usize] = Some(InstructionInfo::new("GASPRICE", 0, 1, GasPriceTier::Base));
559 arr[EXTCODESIZE as usize] = Some(InstructionInfo::new("EXTCODESIZE", 1, 1, GasPriceTier::Special));
560 arr[EXTCODECOPY as usize] = Some(InstructionInfo::new("EXTCODECOPY", 4, 0, GasPriceTier::Special));
561 arr[BLOCKHASH as usize] = Some(InstructionInfo::new("BLOCKHASH", 1, 1, GasPriceTier::Ext));
562 arr[COINBASE as usize] = Some(InstructionInfo::new("COINBASE", 0, 1, GasPriceTier::Base));
563 arr[TIMESTAMP as usize] = Some(InstructionInfo::new("TIMESTAMP", 0, 1, GasPriceTier::Base));
564 arr[NUMBER as usize] = Some(InstructionInfo::new("NUMBER", 0, 1, GasPriceTier::Base));
565 arr[DIFFICULTY as usize] = Some(InstructionInfo::new("DIFFICULTY", 0, 1, GasPriceTier::Base));
566 arr[GASLIMIT as usize] = Some(InstructionInfo::new("GASLIMIT", 0, 1, GasPriceTier::Base));
567 arr[CHAINID as usize] = Some(InstructionInfo::new("CHAINID", 0, 1, GasPriceTier::Base));
568 arr[SELFBALANCE as usize] = Some(InstructionInfo::new("SELFBALANCE", 0, 1, GasPriceTier::Low));
569 arr[BASEFEE as usize] = Some(InstructionInfo::new("BASEFEE", 0, 1, GasPriceTier::VeryLow));
570 arr[POP as usize] = Some(InstructionInfo::new("POP", 1, 0, GasPriceTier::Base));
571 arr[MLOAD as usize] = Some(InstructionInfo::new("MLOAD", 1, 1, GasPriceTier::VeryLow));
572 arr[MSTORE as usize] = Some(InstructionInfo::new("MSTORE", 2, 0, GasPriceTier::VeryLow));
573 arr[MSTORE8 as usize] = Some(InstructionInfo::new("MSTORE8", 2, 0, GasPriceTier::VeryLow));
574 arr[SLOAD as usize] = Some(InstructionInfo::new("SLOAD", 1, 1, GasPriceTier::Special));
575 arr[SSTORE as usize] = Some(InstructionInfo::new("SSTORE", 2, 0, GasPriceTier::Special));
576 arr[JUMP as usize] = Some(InstructionInfo::new("JUMP", 1, 0, GasPriceTier::Mid));
577 arr[JUMPI as usize] = Some(InstructionInfo::new("JUMPI", 2, 0, GasPriceTier::High));
578 arr[PC as usize] = Some(InstructionInfo::new("PC", 0, 1, GasPriceTier::Base));
579 arr[MSIZE as usize] = Some(InstructionInfo::new("MSIZE", 0, 1, GasPriceTier::Base));
580 arr[GAS as usize] = Some(InstructionInfo::new("GAS", 0, 1, GasPriceTier::Base));
581 arr[JUMPDEST as usize] = Some(InstructionInfo::new("JUMPDEST", 0, 0, GasPriceTier::Special));
582 arr[PUSH0 as usize] = Some(InstructionInfo::new("PUSH0", 0, 1, GasPriceTier::Base));
583 arr[PUSH1 as usize] = Some(InstructionInfo::new("PUSH1", 0, 1, GasPriceTier::VeryLow));
584 arr[PUSH2 as usize] = Some(InstructionInfo::new("PUSH2", 0, 1, GasPriceTier::VeryLow));
585 arr[PUSH3 as usize] = Some(InstructionInfo::new("PUSH3", 0, 1, GasPriceTier::VeryLow));
586 arr[PUSH4 as usize] = Some(InstructionInfo::new("PUSH4", 0, 1, GasPriceTier::VeryLow));
587 arr[PUSH5 as usize] = Some(InstructionInfo::new("PUSH5", 0, 1, GasPriceTier::VeryLow));
588 arr[PUSH6 as usize] = Some(InstructionInfo::new("PUSH6", 0, 1, GasPriceTier::VeryLow));
589 arr[PUSH7 as usize] = Some(InstructionInfo::new("PUSH7", 0, 1, GasPriceTier::VeryLow));
590 arr[PUSH8 as usize] = Some(InstructionInfo::new("PUSH8", 0, 1, GasPriceTier::VeryLow));
591 arr[PUSH9 as usize] = Some(InstructionInfo::new("PUSH9", 0, 1, GasPriceTier::VeryLow));
592 arr[PUSH10 as usize] = Some(InstructionInfo::new("PUSH10", 0, 1, GasPriceTier::VeryLow));
593 arr[PUSH11 as usize] = Some(InstructionInfo::new("PUSH11", 0, 1, GasPriceTier::VeryLow));
594 arr[PUSH12 as usize] = Some(InstructionInfo::new("PUSH12", 0, 1, GasPriceTier::VeryLow));
595 arr[PUSH13 as usize] = Some(InstructionInfo::new("PUSH13", 0, 1, GasPriceTier::VeryLow));
596 arr[PUSH14 as usize] = Some(InstructionInfo::new("PUSH14", 0, 1, GasPriceTier::VeryLow));
597 arr[PUSH15 as usize] = Some(InstructionInfo::new("PUSH15", 0, 1, GasPriceTier::VeryLow));
598 arr[PUSH16 as usize] = Some(InstructionInfo::new("PUSH16", 0, 1, GasPriceTier::VeryLow));
599 arr[PUSH17 as usize] = Some(InstructionInfo::new("PUSH17", 0, 1, GasPriceTier::VeryLow));
600 arr[PUSH18 as usize] = Some(InstructionInfo::new("PUSH18", 0, 1, GasPriceTier::VeryLow));
601 arr[PUSH19 as usize] = Some(InstructionInfo::new("PUSH19", 0, 1, GasPriceTier::VeryLow));
602 arr[PUSH20 as usize] = Some(InstructionInfo::new("PUSH20", 0, 1, GasPriceTier::VeryLow));
603 arr[PUSH21 as usize] = Some(InstructionInfo::new("PUSH21", 0, 1, GasPriceTier::VeryLow));
604 arr[PUSH22 as usize] = Some(InstructionInfo::new("PUSH22", 0, 1, GasPriceTier::VeryLow));
605 arr[PUSH23 as usize] = Some(InstructionInfo::new("PUSH23", 0, 1, GasPriceTier::VeryLow));
606 arr[PUSH24 as usize] = Some(InstructionInfo::new("PUSH24", 0, 1, GasPriceTier::VeryLow));
607 arr[PUSH25 as usize] = Some(InstructionInfo::new("PUSH25", 0, 1, GasPriceTier::VeryLow));
608 arr[PUSH26 as usize] = Some(InstructionInfo::new("PUSH26", 0, 1, GasPriceTier::VeryLow));
609 arr[PUSH27 as usize] = Some(InstructionInfo::new("PUSH27", 0, 1, GasPriceTier::VeryLow));
610 arr[PUSH28 as usize] = Some(InstructionInfo::new("PUSH28", 0, 1, GasPriceTier::VeryLow));
611 arr[PUSH29 as usize] = Some(InstructionInfo::new("PUSH29", 0, 1, GasPriceTier::VeryLow));
612 arr[PUSH30 as usize] = Some(InstructionInfo::new("PUSH30", 0, 1, GasPriceTier::VeryLow));
613 arr[PUSH31 as usize] = Some(InstructionInfo::new("PUSH31", 0, 1, GasPriceTier::VeryLow));
614 arr[PUSH32 as usize] = Some(InstructionInfo::new("PUSH32", 0, 1, GasPriceTier::VeryLow));
615 arr[DUP1 as usize] = Some(InstructionInfo::new("DUP1", 1, 2, GasPriceTier::VeryLow));
616 arr[DUP2 as usize] = Some(InstructionInfo::new("DUP2", 2, 3, GasPriceTier::VeryLow));
617 arr[DUP3 as usize] = Some(InstructionInfo::new("DUP3", 3, 4, GasPriceTier::VeryLow));
618 arr[DUP4 as usize] = Some(InstructionInfo::new("DUP4", 4, 5, GasPriceTier::VeryLow));
619 arr[DUP5 as usize] = Some(InstructionInfo::new("DUP5", 5, 6, GasPriceTier::VeryLow));
620 arr[DUP6 as usize] = Some(InstructionInfo::new("DUP6", 6, 7, GasPriceTier::VeryLow));
621 arr[DUP7 as usize] = Some(InstructionInfo::new("DUP7", 7, 8, GasPriceTier::VeryLow));
622 arr[DUP8 as usize] = Some(InstructionInfo::new("DUP8", 8, 9, GasPriceTier::VeryLow));
623 arr[DUP9 as usize] = Some(InstructionInfo::new("DUP9", 9, 10, GasPriceTier::VeryLow));
624 arr[DUP10 as usize] = Some(InstructionInfo::new("DUP10", 10, 11, GasPriceTier::VeryLow));
625 arr[DUP11 as usize] = Some(InstructionInfo::new("DUP11", 11, 12, GasPriceTier::VeryLow));
626 arr[DUP12 as usize] = Some(InstructionInfo::new("DUP12", 12, 13, GasPriceTier::VeryLow));
627 arr[DUP13 as usize] = Some(InstructionInfo::new("DUP13", 13, 14, GasPriceTier::VeryLow));
628 arr[DUP14 as usize] = Some(InstructionInfo::new("DUP14", 14, 15, GasPriceTier::VeryLow));
629 arr[DUP15 as usize] = Some(InstructionInfo::new("DUP15", 15, 16, GasPriceTier::VeryLow));
630 arr[DUP16 as usize] = Some(InstructionInfo::new("DUP16", 16, 17, GasPriceTier::VeryLow));
631 arr[SWAP1 as usize] = Some(InstructionInfo::new("SWAP1", 2, 2, GasPriceTier::VeryLow));
632 arr[SWAP2 as usize] = Some(InstructionInfo::new("SWAP2", 3, 3, GasPriceTier::VeryLow));
633 arr[SWAP3 as usize] = Some(InstructionInfo::new("SWAP3", 4, 4, GasPriceTier::VeryLow));
634 arr[SWAP4 as usize] = Some(InstructionInfo::new("SWAP4", 5, 5, GasPriceTier::VeryLow));
635 arr[SWAP5 as usize] = Some(InstructionInfo::new("SWAP5", 6, 6, GasPriceTier::VeryLow));
636 arr[SWAP6 as usize] = Some(InstructionInfo::new("SWAP6", 7, 7, GasPriceTier::VeryLow));
637 arr[SWAP7 as usize] = Some(InstructionInfo::new("SWAP7", 8, 8, GasPriceTier::VeryLow));
638 arr[SWAP8 as usize] = Some(InstructionInfo::new("SWAP8", 9, 9, GasPriceTier::VeryLow));
639 arr[SWAP9 as usize] = Some(InstructionInfo::new("SWAP9", 10, 10, GasPriceTier::VeryLow));
640 arr[SWAP10 as usize] = Some(InstructionInfo::new("SWAP10", 11, 11, GasPriceTier::VeryLow));
641 arr[SWAP11 as usize] = Some(InstructionInfo::new("SWAP11", 12, 12, GasPriceTier::VeryLow));
642 arr[SWAP12 as usize] = Some(InstructionInfo::new("SWAP12", 13, 13, GasPriceTier::VeryLow));
643 arr[SWAP13 as usize] = Some(InstructionInfo::new("SWAP13", 14, 14, GasPriceTier::VeryLow));
644 arr[SWAP14 as usize] = Some(InstructionInfo::new("SWAP14", 15, 15, GasPriceTier::VeryLow));
645 arr[SWAP15 as usize] = Some(InstructionInfo::new("SWAP15", 16, 16, GasPriceTier::VeryLow));
646 arr[SWAP16 as usize] = Some(InstructionInfo::new("SWAP16", 17, 17, GasPriceTier::VeryLow));
647 arr[LOG0 as usize] = Some(InstructionInfo::new("LOG0", 2, 0, GasPriceTier::Special));
648 arr[LOG1 as usize] = Some(InstructionInfo::new("LOG1", 3, 0, GasPriceTier::Special));
649 arr[LOG2 as usize] = Some(InstructionInfo::new("LOG2", 4, 0, GasPriceTier::Special));
650 arr[LOG3 as usize] = Some(InstructionInfo::new("LOG3", 5, 0, GasPriceTier::Special));
651 arr[LOG4 as usize] = Some(InstructionInfo::new("LOG4", 6, 0, GasPriceTier::Special));
652 arr[BEGINSUB_TLOAD as usize] = Some(InstructionInfo::new("BEGINSUB", 0, 0, GasPriceTier::Base));
653 arr[JUMPSUB_MCOPY as usize] = Some(InstructionInfo::new("JUMPSUB", 1, 0, GasPriceTier::High));
654 arr[RETURNSUB_TSTORE as usize] = Some(InstructionInfo::new("RETURNSUB", 0, 0, GasPriceTier::Low));
655 arr[CREATE as usize] = Some(InstructionInfo::new("CREATE", 3, 1, GasPriceTier::Special));
656 arr[CALL as usize] = Some(InstructionInfo::new("CALL", 7, 1, GasPriceTier::Special));
657 arr[CALLCODE as usize] = Some(InstructionInfo::new("CALLCODE", 7, 1, GasPriceTier::Special));
658 arr[RETURN as usize] = Some(InstructionInfo::new("RETURN", 2, 0, GasPriceTier::Zero));
659 arr[DELEGATECALL as usize] = Some(InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special));
660 arr[STATICCALL as usize] = Some(InstructionInfo::new("STATICCALL", 6, 1, GasPriceTier::Special));
661 arr[SUICIDE as usize] = Some(InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special));
662 arr[CREATE2 as usize] = Some(InstructionInfo::new("CREATE2", 4, 1, GasPriceTier::Special));
663 arr[REVERT as usize] = Some(InstructionInfo::new("REVERT", 2, 0, GasPriceTier::Zero));
664 arr
665 };
666
667 pub static ref INSTRUCTIONS_CANCUN: [Option<InstructionInfo>; 0x100] = {
668 let mut arr = *INSTRUCTIONS;
669 arr[BEGINSUB_TLOAD as usize] = Some(InstructionInfo::new("TLOAD", 1, 1, GasPriceTier::Special));
670 arr[JUMPSUB_MCOPY as usize] = Some(InstructionInfo::new("MCOPY", 3, 0, GasPriceTier::Special));
671 arr[RETURNSUB_TSTORE as usize] = Some(InstructionInfo::new("TSTORE", 2, 0, GasPriceTier::Special));
672 arr
673 };
674
675 pub static ref INSTRUCTIONS_CIP645: [Option<InstructionInfo>; 0x100] = {
676 let mut arr = *INSTRUCTIONS_CANCUN;
677 arr[BASEFEE as usize] = Some(InstructionInfo::new("BASEFEE", 0, 1, GasPriceTier::Base));
678 arr[BLOBHASH as usize] = Some(InstructionInfo::new("BLOBHASH", 1, 1, GasPriceTier::VeryLow));
679 arr[BLOBBASEFEE as usize] = Some(InstructionInfo::new("BLOBBASEFEE", 0, 1, GasPriceTier::Base));
680 arr[JUMPSUB_MCOPY as usize] = Some(InstructionInfo::new("MCOPY", 3, 0, GasPriceTier::VeryLow));
681
682 arr
683 };
684
685 pub static ref INSTRUCTIONS_EIP7939: [Option<InstructionInfo>; 0x100] = {
686 let mut arr = *INSTRUCTIONS_CIP645;
687 arr[CLZ as usize] = Some(InstructionInfo::new("CLZ", 1, 1, GasPriceTier::Low));
688
689 arr
690 };
691}
692
693pub const MAX_NO_OF_TOPICS: usize = 4;
695
696#[cfg(test)]
697mod tests {
698 use super::*;
699
700 #[test]
701 fn test_is_push() {
702 assert!(PUSH1.is_push());
703 assert!(PUSH32.is_push());
704 assert!(!DUP1.is_push());
705 }
706
707 #[test]
708 fn test_get_push_bytes() {
709 assert_eq!(PUSH1.push_bytes(), Some(1));
710 assert_eq!(PUSH3.push_bytes(), Some(3));
711 assert_eq!(PUSH32.push_bytes(), Some(32));
712 }
713
714 #[test]
715 fn test_get_dup_position() {
716 assert_eq!(DUP1.dup_position(), Some(0));
717 assert_eq!(DUP5.dup_position(), Some(4));
718 assert_eq!(DUP10.dup_position(), Some(9));
719 }
720
721 #[test]
722 fn test_get_swap_position() {
723 assert_eq!(SWAP1.swap_position(), Some(1));
724 assert_eq!(SWAP5.swap_position(), Some(5));
725 assert_eq!(SWAP10.swap_position(), Some(10));
726 }
727
728 #[test]
729 fn test_get_log_topics() {
730 assert_eq!(LOG0.log_topics(), Some(0));
731 assert_eq!(LOG2.log_topics(), Some(2));
732 assert_eq!(LOG4.log_topics(), Some(4));
733 }
734}