1#![allow(
2 clippy::needless_update,
3 unreachable_pub,
4 dead_code,
5 missing_docs,
6 missing_debug_implementations
7)]
8
9use crate::*;
10use revm_bytecode::opcode as op;
11use revm_context_interface as context_interface;
12use revm_interpreter as interpreter;
13use revm_interpreter::{
14 CreateInputs, FrameInput, Gas, InstructionResult, InterpreterAction, InterpreterResult,
15};
16use revm_primitives::{
17 Address, B256, Bytes, KECCAK_EMPTY, Log, LogData, hardfork::SpecId, hex, keccak256,
18};
19use revmc_builtins::gas;
20
21const fn keccak256_cost(len: u64) -> Option<u64> {
23 let words = len.div_ceil(32);
24 match words.checked_mul(gas::KECCAK256WORD) {
25 Some(dyn_cost) => Some(gas::KECCAK256.saturating_add(dyn_cost)),
26 None => None,
27 }
28}
29
30const fn log_cost(n_topics: u8, len: u64) -> Option<u64> {
32 match gas::LOGDATA.checked_mul(len) {
33 Some(dyn_cost) => {
34 Some((gas::LOG + gas::LOGTOPIC * n_topics as u64).saturating_add(dyn_cost))
35 }
36 None => None,
37 }
38}
39
40const fn verylowcopy_cost(len: u64) -> Option<u64> {
42 let words = len.div_ceil(32);
43 match words.checked_mul(gas::COPY) {
44 Some(dyn_cost) => Some(gas::VERYLOW.saturating_add(dyn_cost)),
45 None => None,
46 }
47}
48
49#[macro_use]
50mod macros;
51
52mod meta;
53
54mod fibonacci;
55mod resume;
56mod resume_at_call;
57
58mod runner;
59pub use runner::*;
60
61#[cfg(feature = "llvm")]
62pub fn with_jit_compiler<R>(
63 opt_level: revmc_backend::OptimizationLevel,
64 f: fn(&mut EvmCompiler<revmc_llvm::EvmLlvmBackend>) -> R,
65) -> R {
66 init_tracing();
67 let mut compiler = EvmCompiler::new_llvm(false).unwrap();
68 compiler.set_opt_level(opt_level);
69 compiler.set_profiling_support(false);
70 compiler.set_simple_perf(false);
71 compiler.single_error(false);
72 f(&mut compiler)
73}
74
75const I256_MIN: U256 = U256::from_limbs([
76 0x0000000000000000,
77 0x0000000000000000,
78 0x0000000000000000,
79 0x8000000000000000,
80]);
81
82const I256_MAX: U256 = U256::from_limbs([
83 0xFFFFFFFFFFFFFFFF,
84 0xFFFFFFFFFFFFFFFF,
85 0xFFFFFFFFFFFFFFFF,
86 0x7FFFFFFFFFFFFFFF,
87]);
88
89tests! {
90 ret {
91 empty(@raw {}),
92 no_stop(@raw {
93 bytecode: &[op::PUSH0],
94 expected_stack: &[U256::ZERO],
95 expected_gas: 2,
96 }),
97 stop(@raw {
98 bytecode: &[op::STOP],
99 expected_gas: 0,
100 }),
101 invalid(@raw {
102 bytecode: &[op::INVALID],
103 expected_return: InstructionResult::InvalidFEOpcode,
104 expected_gas: 0,
105 }),
106 unknown(@raw {
107 bytecode: &[0x21],
108 expected_return: InstructionResult::OpcodeNotFound,
109 expected_gas: 0,
110 }),
111 underflow1(@raw {
112 bytecode: &[op::ADD],
113 expected_return: InstructionResult::StackUnderflow,
114 expected_gas: 3,
115 }),
116 underflow2(@raw {
117 bytecode: &[op::PUSH0, op::ADD],
118 expected_return: InstructionResult::StackUnderflow,
119 expected_stack: &[U256::ZERO],
120 expected_gas: 5,
121 }),
122 underflow3(@raw {
123 bytecode: &[op::PUSH0, op::POP, op::ADD],
124 expected_return: InstructionResult::StackUnderflow,
125 expected_gas: 7,
126 }),
127 underflow4(@raw {
128 bytecode: &[op::PUSH0, op::ADD, op::POP],
129 expected_return: InstructionResult::StackUnderflow,
130 expected_stack: &[U256::ZERO],
131 expected_gas: 5,
132 }),
133 overflow_not0(@raw {
134 bytecode: &[op::PUSH0; 1023],
135 expected_return: InstructionResult::Stop,
136 expected_stack: &[0_U256; 1023],
137 expected_gas: 2 * 1023,
138 }),
139 overflow_not1(@raw {
140 bytecode: &[op::PUSH0; 1024],
141 expected_return: InstructionResult::Stop,
142 expected_stack: &[0_U256; 1024],
143 expected_gas: 2 * 1024,
144 }),
145 overflow0(@raw {
146 bytecode: &[op::PUSH0; 1025],
147 expected_return: InstructionResult::StackOverflow,
148 expected_stack: &[0_U256; 1024],
149 expected_gas: 2 * 1025,
150 }),
151 overflow1(@raw {
152 bytecode: &[op::PUSH0; 1026],
153 expected_return: InstructionResult::StackOverflow,
154 expected_stack: &[0_U256; 1024],
155 expected_gas: 2 * 1025,
156 }),
157 }
158
159 spec_id {
160 push0_merge(@raw {
161 bytecode: &[op::PUSH0],
162 spec_id: SpecId::MERGE,
163 expected_return: InstructionResult::NotActivated,
164 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
165 }),
166 push0_shanghai(@raw {
167 bytecode: &[op::PUSH0],
168 spec_id: SpecId::SHANGHAI,
169 expected_stack: &[U256::ZERO],
170 expected_gas: 2,
171 }),
172 push0_cancun(@raw {
173 bytecode: &[op::PUSH0],
174 spec_id: SpecId::CANCUN,
175 expected_stack: &[U256::ZERO],
176 expected_gas: 2,
177 }),
178 clz_cancun(@raw {
179 bytecode: &[op::MSIZE, op::CLZ],
180 spec_id: SpecId::CANCUN,
181 expected_return: InstructionResult::NotActivated,
182 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
183 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
184 }),
185 clz_arrow_glacier(@raw {
186 bytecode: &[op::MSIZE, op::CLZ],
187 spec_id: SpecId::LONDON,
188 expected_return: InstructionResult::NotActivated,
189 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
190 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
191 }),
192
193 dupn_cancun(@raw {
194 bytecode: &[op::PUSH0, op::DUPN, 0x00],
195 spec_id: SpecId::CANCUN,
196 expected_return: InstructionResult::NotActivated,
197 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
198 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
199 }),
200 swapn_cancun(@raw {
201 bytecode: &[op::PUSH0, op::SWAPN, 0x00],
202 spec_id: SpecId::CANCUN,
203 expected_return: InstructionResult::NotActivated,
204 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
205 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
206 }),
207 exchange_cancun(@raw {
208 bytecode: &[op::PUSH0, op::EXCHANGE, 0x01],
209 spec_id: SpecId::CANCUN,
210 expected_return: InstructionResult::NotActivated,
211 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
212 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
213 }),
214 slotnum_cancun(@raw {
215 bytecode: &[op::SLOTNUM],
216 spec_id: SpecId::CANCUN,
217 expected_return: InstructionResult::NotActivated,
218 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
219 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
220 }),
221
222 exp_zero_frontier(@raw {
225 bytecode: &bytecode_binop(op::EXP, 2_U256, 0_U256),
226 spec_id: SpecId::FRONTIER,
227 expected_stack: &[1_U256],
228 expected_gas: 6 + 10,
229 }),
230 exp_one_frontier(@raw {
232 bytecode: &bytecode_binop(op::EXP, 2_U256, 1_U256),
233 spec_id: SpecId::FRONTIER,
234 expected_stack: &[2_U256],
235 expected_gas: 6 + 10 + 10,
236 }),
237 exp_multi_byte_frontier(@raw {
239 bytecode: &bytecode_binop(op::EXP, 2_U256, 256_U256),
240 spec_id: SpecId::FRONTIER,
241 expected_stack: &[0_U256],
242 expected_gas: 6 + 10 + 20,
243 }),
244 exp_zero_istanbul(@raw {
246 bytecode: &bytecode_binop(op::EXP, 2_U256, 0_U256),
247 spec_id: SpecId::ISTANBUL,
248 expected_stack: &[1_U256],
249 expected_gas: 6 + 10,
250 }),
251 exp_one_istanbul(@raw {
252 bytecode: &bytecode_binop(op::EXP, 2_U256, 1_U256),
253 spec_id: SpecId::ISTANBUL,
254 expected_stack: &[2_U256],
255 expected_gas: 6 + 10 + 50,
256 }),
257 exp_multi_byte_istanbul(@raw {
258 bytecode: &bytecode_binop(op::EXP, 2_U256, 256_U256),
259 spec_id: SpecId::ISTANBUL,
260 expected_stack: &[0_U256],
261 expected_gas: 6 + 10 + 100,
262 }),
263 }
264
265 stack {
266 pop(@raw {
267 bytecode: &[op::PUSH1, 1, op::POP],
268 expected_gas: 3 + 2,
269 }),
270 dup(@raw {
271 bytecode: &[op::PUSH1, 1, op::DUP1],
272 expected_stack: &[1_U256, 1_U256],
273 expected_gas: 3 + 3,
274 }),
275
276 swap(@raw {
277 bytecode: &[op::PUSH1, 1, op::PUSH1, 2, op::SWAP1],
278 expected_stack: &[2_U256, 1_U256],
279 expected_gas: 3 + 3 + 3,
280 }),
281 swap2(@raw {
282 bytecode: &[op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::SWAP2],
283 expected_stack: &[3_U256, 2_U256, 1_U256],
284 expected_gas: 3 + 3 + 3 + 3,
285 }),
286 swap3(@raw {
287 bytecode: &[op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::SWAP3],
288 expected_stack: &[4_U256, 2_U256, 3_U256, 1_U256],
289 expected_gas: 3 + 3 + 3 + 3 + 3,
290 }),
291
292 dupn(@raw {
294 bytecode: &{
295 let mut code = [0u8; 21];
296 code[0] = op::PUSH1; code[1] = 1; let mut i = 2;
299 while i < 18 {
300 code[i] = op::PUSH0;
301 i += 1;
302 }
303 code[18] = op::DUPN;
304 code[19] = 0x80; code
306 },
307 spec_id: SpecId::AMSTERDAM,
308 expected_stack: &{
309 let mut s = [U256::ZERO; 18];
310 s[0] = 1_U256; s[17] = 1_U256; s
314 },
315 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
316 }),
317
318 swapn(@raw {
320 bytecode: &{
321 let mut code = [0u8; 23];
322 code[0] = op::PUSH1; code[1] = 1; let mut i = 2;
325 while i < 18 {
326 code[i] = op::PUSH0;
327 i += 1;
328 }
329 code[18] = op::PUSH1; code[19] = 2; code[20] = op::SWAPN;
331 code[21] = 0x80; code
333 },
334 spec_id: SpecId::AMSTERDAM,
335 expected_stack: &{
336 let mut s = [U256::ZERO; 18];
337 s[0] = 2_U256; s[17] = 1_U256; s
341 },
342 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
343 }),
344
345 exchange_basic(@raw {
347 bytecode: &[op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::EXCHANGE, 0x8E],
348 spec_id: SpecId::AMSTERDAM,
349 expected_stack: &[2_U256, 1_U256, 3_U256],
353 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
354 }),
355
356 slotnum(@raw {
358 bytecode: &[op::SLOTNUM],
359 spec_id: SpecId::AMSTERDAM,
360 expected_stack: &[U256::ZERO],
361 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
362 }),
363
364 dupn_underflow(@raw {
366 bytecode: &[op::PUSH0, op::DUPN, 0x80],
367 spec_id: SpecId::AMSTERDAM,
368 expected_return: InstructionResult::StackOverflow,
369 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
370 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
371 }),
372 swapn_underflow(@raw {
374 bytecode: &[op::PUSH0, op::SWAPN, 0x80],
375 spec_id: SpecId::AMSTERDAM,
376 expected_return: InstructionResult::StackUnderflow,
377 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
378 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
379 }),
380 exchange_underflow(@raw {
382 bytecode: &[op::PUSH0, op::PUSH0, op::EXCHANGE, 0x8E],
383 spec_id: SpecId::AMSTERDAM,
384 expected_return: InstructionResult::StackUnderflow,
385 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
386 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
387 }),
388 swap16_dup10_selfdestruct_underflow(@raw {
389 bytecode: &[op::SWAP16, op::DUP10, op::SELFDESTRUCT],
390 spec_id: SpecId::OSAKA,
391 expected_return: InstructionResult::StackUnderflow,
392 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
393 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
394 }),
395
396 dupn_invalid_imm(@raw {
398 bytecode: &[op::PUSH0, op::DUPN, 0x5B],
399 spec_id: SpecId::AMSTERDAM,
400 expected_return: InstructionResult::InvalidImmediateEncoding,
401 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
402 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
403 }),
404 swapn_invalid_imm(@raw {
405 bytecode: &[op::PUSH0, op::SWAPN, 0x5B],
406 spec_id: SpecId::AMSTERDAM,
407 expected_return: InstructionResult::InvalidImmediateEncoding,
408 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
409 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
410 }),
411 exchange_invalid_imm(@raw {
413 bytecode: &[op::PUSH0, op::PUSH0, op::PUSH0, op::EXCHANGE, 82],
414 spec_id: SpecId::AMSTERDAM,
415 expected_return: InstructionResult::InvalidImmediateEncoding,
416 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
417 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
418 }),
419
420 dupn_truncated_eof(@raw {
423 bytecode: &{
424 let mut code = [0u8; 18];
425 let mut i = 0;
426 while i < 17 {
427 code[i] = op::PUSH0;
428 i += 1;
429 }
430 code[17] = op::DUPN; code
432 },
433 spec_id: SpecId::AMSTERDAM,
434 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
435 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
436 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
437 }),
438 swapn_truncated_eof(@raw {
441 bytecode: &{
442 let mut code = [0u8; 19];
443 let mut i = 0;
444 while i < 18 {
445 code[i] = op::PUSH0;
446 i += 1;
447 }
448 code[18] = op::SWAPN; code
450 },
451 spec_id: SpecId::AMSTERDAM,
452 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
453 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
454 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
455 }),
456
457 jump_into_dupn_immediate(@raw {
460 bytecode: &[
461 op::PUSH1, 4, op::JUMP,
462 op::DUPN, op::JUMPDEST, op::PUSH1, 0x42, op::PUSH0, op::MSTORE,
464 op::PUSH1, 0x20, op::PUSH0, op::RETURN,
465 ],
466 spec_id: SpecId::AMSTERDAM,
467 expected_return: InstructionResult::Return,
468 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
469 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
470 }),
471 jump_into_swapn_immediate(@raw {
473 bytecode: &[
474 op::PUSH1, 4, op::JUMP,
475 op::SWAPN, op::JUMPDEST,
476 op::PUSH1, 0x42, op::PUSH0, op::MSTORE,
477 op::PUSH1, 0x20, op::PUSH0, op::RETURN,
478 ],
479 spec_id: SpecId::AMSTERDAM,
480 expected_return: InstructionResult::Return,
481 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
482 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
483 }),
484 jump_into_exchange_immediate(@raw {
486 bytecode: &[
487 op::PUSH1, 4, op::JUMP,
488 op::EXCHANGE, op::JUMPDEST,
489 op::PUSH1, 0x42, op::PUSH0, op::MSTORE,
490 op::PUSH1, 0x20, op::PUSH0, op::RETURN,
491 ],
492 spec_id: SpecId::AMSTERDAM,
493 expected_return: InstructionResult::Return,
494 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
495 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
496 }),
497
498 push2_truncated_eof(@raw {
501 bytecode: &[op::PUSH2, 0x42],
502 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
503 expected_stack: &[U256::from(0x4200u64)],
504 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
505 }),
506 push3_truncated_eof(@raw {
508 bytecode: &[op::PUSH3, 0xAB, 0xCD],
509 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
510 expected_stack: &[U256::from(0xABCD00u64)],
511 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
512 }),
513 push1_no_imm_eof(@raw {
515 bytecode: &[op::PUSH1],
516 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
517 expected_stack: &[U256::ZERO],
518 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
519 }),
520
521 overflow_analysis_edge_case(@raw {
522 bytecode: &[&[op::JUMPDEST][..], &[op::PUSH0; 1025][..], &[op::JUMPI][..]].concat(),
523 expected_return: InstructionResult::StackOverflow,
524 }),
525 }
526
527 control_flow {
528 basic_jump(@raw {
529 bytecode: &[op::PUSH1, 3, op::JUMP, op::JUMPDEST, op::PUSH1, 69],
530 expected_stack: &[69_U256],
531 expected_gas: 3 + 8 + 1 + 3,
532 }),
533 unmodified_stack_after_push_jump(@raw {
534 bytecode: &[op::PUSH1, 3, op::JUMP, op::JUMPDEST, op::PUSH0, op::ADD],
535 expected_return: InstructionResult::StackUnderflow,
536 expected_stack: &[U256::ZERO],
537 expected_gas: 3 + 8 + 1 + 2 + 3,
538 }),
539 bad_jump(@raw {
540 bytecode: &[op::JUMP],
541 expected_return: InstructionResult::StackUnderflow,
542 expected_gas: 8,
543 }),
544 bad_jumpi1(@raw {
545 bytecode: &[op::JUMPI],
546 expected_return: InstructionResult::StackUnderflow,
547 expected_gas: 10,
548 }),
549 bad_jumpi2(@raw {
550 bytecode: &[op::PUSH0, op::JUMPI],
551 expected_return: InstructionResult::StackUnderflow,
552 expected_stack: &[0_U256],
553 expected_gas: 2 + 10,
554 }),
555 bad_jumpi3(@raw {
556 bytecode: &[op::JUMPDEST, op::PUSH0, op::JUMPI],
557 expected_return: InstructionResult::StackUnderflow,
558 expected_stack: &[0_U256],
559 expected_gas: 1 + 2 + 10,
560 }),
561
562 basic_jumpi1(@raw {
563 bytecode: &[op::JUMPDEST, op::PUSH0, op::PUSH0, op::JUMPI, op::PUSH1, 69],
564 expected_stack: &[69_U256],
565 expected_gas: 1 + 2 + 2 + 10 + 3,
566 }),
567 basic_jumpi1_lazy_invalid_target(@raw {
568 bytecode: &[op::PUSH0, op::PUSH0, op::JUMPI, op::PUSH1, 69],
569 expected_stack: &[69_U256],
570 expected_gas: 2 + 2 + 10 + 3,
571 }),
572 basic_jumpi2(@raw {
573 bytecode: &[op::PUSH1, 1, op::PUSH1, 5, op::JUMPI, op::JUMPDEST, op::PUSH1, 69],
574 expected_stack: &[69_U256],
575 expected_gas: 3 + 3 + 10 + 1 + 3,
576 }),
577 basic_jumpi2_lazy_invalid_target(@raw {
578 bytecode: &[op::PUSH1, 1, op::PUSH0, op::JUMPI, op::PUSH1, 69],
579 expected_return: InstructionResult::InvalidJump,
580 expected_gas: 3 + 2 + 10,
581 }),
582 unmodified_stack_after_push_jumpi(@raw {
583 bytecode: &[op::PUSH1, 1, op::PUSH1, 5, op::JUMPI, op::JUMPDEST, op::PUSH0, op::ADD],
584 expected_return: InstructionResult::StackUnderflow,
585 expected_stack: &[U256::ZERO],
586 expected_gas: 3 + 3 + 10 + 1 + 2 + 3,
587 }),
588
589 basic_loop(@raw {
590 bytecode: &[
591 op::PUSH1, 3, op::JUMPDEST, op::PUSH1, 1, op::SWAP1, op::SUB, op::DUP1, op::PUSH1, 2, op::JUMPI, op::POP, op::PUSH1, 69, ],
602 expected_stack: &[69_U256],
603 expected_gas: 3 + (1 + 3 + 3 + 3 + 3 + 3 + 10) * 3 + 2 + 3,
604 }),
605
606 pc(@raw {
607 bytecode: &[op::PC, op::PC, op::PUSH1, 69, op::PC, op::PUSH0, op::PC],
608 expected_stack: &[0_U256, 1_U256, 69_U256, 4_U256, 0_U256, 6_U256],
609 expected_gas: 2 + 2 + 3 + 2 + 2 + 2,
610 }),
611
612 }
613
614 arith {
615 add1(op::ADD, 0_U256, 0_U256 => 0_U256),
616 add2(op::ADD, 1_U256, 2_U256 => 3_U256),
617 add3(op::ADD, 255_U256, 255_U256 => 510_U256),
618 add4(op::ADD, U256::MAX, 1_U256 => 0_U256),
619 add5(op::ADD, U256::MAX, 2_U256 => 1_U256),
620
621 sub1(op::SUB, 3_U256, 2_U256 => 1_U256),
622 sub2(op::SUB, 1_U256, 2_U256 => -1_U256),
623 sub3(op::SUB, 1_U256, 3_U256 => (-1_U256).wrapping_sub(1_U256)),
624 sub4(op::SUB, 255_U256, 255_U256 => 0_U256),
625
626 mul1(op::MUL, 1_U256, 2_U256 => 2_U256),
627 mul2(op::MUL, 32_U256, 32_U256 => 1024_U256),
628 mul3(op::MUL, U256::MAX, 2_U256 => U256::MAX.wrapping_sub(1_U256)),
629
630 div1(op::DIV, 32_U256, 32_U256 => 1_U256),
631 div2(op::DIV, 1_U256, 2_U256 => 0_U256),
632 div3(op::DIV, 2_U256, 2_U256 => 1_U256),
633 div4(op::DIV, 3_U256, 2_U256 => 1_U256),
634 div5(op::DIV, 4_U256, 2_U256 => 2_U256),
635 div_by_one(op::DIV, 42_U256, 1_U256 => 42_U256),
636 div_pow2_4(op::DIV, 100_U256, 4_U256 => 25_U256),
637 div_pow2_256(op::DIV, 512_U256, 256_U256 => 2_U256),
638 div_zero_dividend(op::DIV, 0_U256, 42_U256 => 0_U256),
639 div_by_zero1(op::DIV, 0_U256, 0_U256 => 0_U256),
640 div_by_zero2(op::DIV, 32_U256, 0_U256 => 0_U256),
641
642 rem1(op::MOD, 32_U256, 32_U256 => 0_U256),
643 rem2(op::MOD, 1_U256, 2_U256 => 1_U256),
644 rem3(op::MOD, 2_U256, 2_U256 => 0_U256),
645 rem4(op::MOD, 3_U256, 2_U256 => 1_U256),
646 rem5(op::MOD, 4_U256, 2_U256 => 0_U256),
647 rem_by_one(op::MOD, 42_U256, 1_U256 => 0_U256),
648 rem_pow2_4(op::MOD, 100_U256, 4_U256 => 0_U256),
649 rem_pow2_256(op::MOD, 513_U256, 256_U256 => 1_U256),
650 rem_zero_dividend(op::MOD, 0_U256, 42_U256 => 0_U256),
651 rem_by_zero1(op::MOD, 0_U256, 0_U256 => 0_U256),
652 rem_by_zero2(op::MOD, 32_U256, 0_U256 => 0_U256),
653
654 sdiv1(op::SDIV, 32_U256, 32_U256 => 1_U256),
655 sdiv2(op::SDIV, 1_U256, 2_U256 => 0_U256),
656 sdiv3(op::SDIV, 2_U256, 2_U256 => 1_U256),
657 sdiv4(op::SDIV, 3_U256, 2_U256 => 1_U256),
658 sdiv5(op::SDIV, 4_U256, 2_U256 => 2_U256),
659 sdiv_by_zero1(op::SDIV, 0_U256, 0_U256 => 0_U256),
660 sdiv_by_zero2(op::SDIV, 32_U256, 0_U256 => 0_U256),
661 sdiv_min_by_1(op::SDIV, I256_MIN, 1_U256 => -I256_MIN),
662 sdiv_min_by_minus_1(op::SDIV, I256_MIN, -1_U256 => I256_MIN),
663 sdiv_max1(op::SDIV, I256_MAX, 1_U256 => I256_MAX),
664 sdiv_max2(op::SDIV, I256_MAX, -1_U256 => -I256_MAX),
665 sdiv_by_int_min(op::SDIV, I256_MIN, I256_MIN => 1_U256),
666 sdiv_nonmin_by_int_min(op::SDIV, 42_U256, I256_MIN => 0_U256),
667 sdiv_zero_dividend(op::SDIV, 0_U256, 42_U256 => 0_U256),
668
669 srem1(op::SMOD, 32_U256, 32_U256 => 0_U256),
670 srem2(op::SMOD, 1_U256, 2_U256 => 1_U256),
671 srem3(op::SMOD, 2_U256, 2_U256 => 0_U256),
672 srem4(op::SMOD, 3_U256, 2_U256 => 1_U256),
673 srem5(op::SMOD, 4_U256, 2_U256 => 0_U256),
674 srem_by_one(op::SMOD, 42_U256, 1_U256 => 0_U256),
675 srem_by_minus_one(op::SMOD, 42_U256, -1_U256 => 0_U256),
676 srem_zero_dividend(op::SMOD, 0_U256, 42_U256 => 0_U256),
677 srem_by_zero1(op::SMOD, 0_U256, 0_U256 => 0_U256),
678 srem_by_zero2(op::SMOD, 32_U256, 0_U256 => 0_U256),
679
680 addmod_mod_zero(op::ADDMOD, 1_U256, 2_U256, 0_U256 => 0_U256),
681 addmod_mod_one(op::ADDMOD, 5_U256, 3_U256, 1_U256 => 0_U256),
682 addmod_both_zero(op::ADDMOD, 0_U256, 0_U256, 42_U256 => 0_U256),
683 addmod1(op::ADDMOD, 1_U256, 2_U256, 3_U256 => 0_U256),
684 addmod2(op::ADDMOD, 1_U256, 2_U256, 4_U256 => 3_U256),
685 addmod3(op::ADDMOD, 1_U256, 2_U256, 2_U256 => 1_U256),
686 addmod4(op::ADDMOD, 32_U256, 32_U256, 69_U256 => 64_U256),
687
688 mulmod_mod_zero(op::MULMOD, 3_U256, 4_U256, 0_U256 => 0_U256),
689 mulmod1(op::MULMOD, 0_U256, 0_U256, 1_U256 => 0_U256),
690 mulmod2(op::MULMOD, 69_U256, 0_U256, 1_U256 => 0_U256),
691 mulmod3(op::MULMOD, 0_U256, 1_U256, 2_U256 => 0_U256),
692 mulmod_a_zero(op::MULMOD, 0_U256, 5_U256, 7_U256 => 0_U256),
693 mulmod_b_zero(op::MULMOD, 5_U256, 0_U256, 7_U256 => 0_U256),
694 mulmod4(op::MULMOD, 69_U256, 1_U256, 2_U256 => 1_U256),
695 mulmod5(op::MULMOD, 69_U256, 1_U256, 30_U256 => 9_U256),
696 mulmod6(op::MULMOD, 69_U256, 2_U256, 100_U256 => 38_U256),
697
698 exp1(op::EXP, 0_U256, 0_U256 => 1_U256; op_gas(10)),
699 exp2(op::EXP, 2_U256, 0_U256 => 1_U256; op_gas(10)),
700 exp3(op::EXP, 2_U256, 1_U256 => 2_U256; op_gas(60)),
701 exp4(op::EXP, 2_U256, 2_U256 => 4_U256; op_gas(60)),
702 exp5(op::EXP, 2_U256, 3_U256 => 8_U256; op_gas(60)),
703 exp6(op::EXP, 2_U256, 4_U256 => 16_U256; op_gas(60)),
704 exp_zero_base_zero_exp(op::EXP, 0_U256, 0_U256 => 1_U256; op_gas(10)),
705 exp_zero_base_nonzero_exp(op::EXP, 0_U256, 5_U256 => 0_U256; op_gas(60)),
706 exp_one_base_large_exp(op::EXP, 1_U256, U256::MAX => 1_U256; op_gas(1610)),
707 exp_minus_one_base_even_exp(op::EXP, -1_U256, 4_U256 => 1_U256; op_gas(60)),
708 exp_minus_one_base_odd_exp(op::EXP, -1_U256, 5_U256 => -1_U256; op_gas(60)),
709 exp_pow4_base_in_range(op::EXP, 4_U256, 63_U256 => 1_U256 << 126; op_gas(60)),
710 exp_pow4_base_overflow(op::EXP, 4_U256, 128_U256 => 0_U256; op_gas(60)),
711 exp_non_pow2_base(op::EXP, 3_U256, 5_U256 => 243_U256; op_gas(60)),
712 exp_overflow(op::EXP, 2_U256, 256_U256 => 0_U256; op_gas(110)),
713 exp_large(op::EXP, 2_U256, 0xFFFF_U256 => 2_U256.pow(0xFFFF_U256); op_gas(110)),
715 exp_max_exponent(op::EXP, 2_U256, U256::MAX => 0_U256; op_gas(1610)),
717
718 signextend1(op::SIGNEXTEND, 0_U256, 0_U256 => 0_U256),
719 signextend2(op::SIGNEXTEND, 1_U256, 0_U256 => 0_U256),
720 signextend3(op::SIGNEXTEND, 0_U256, -1_U256 => -1_U256),
721 signextend4(op::SIGNEXTEND, 1_U256, -1_U256 => -1_U256),
722 signextend5(op::SIGNEXTEND, 0_U256, 0x7f_U256 => 0x7f_U256),
723 signextend6(op::SIGNEXTEND, 0_U256, 0x80_U256 => -0x80_U256),
724 signextend7(op::SIGNEXTEND, 0_U256, 0xff_U256 => U256::MAX),
725 signextend8(op::SIGNEXTEND, 1_U256, 0x7fff_U256 => 0x7fff_U256),
726 signextend8_extra(op::SIGNEXTEND, 1_U256, 0xff7fff_U256 => 0x7fff_U256),
727 signextend9(op::SIGNEXTEND, 1_U256, 0x8000_U256 => -0x8000_U256),
728 signextend9_extra(op::SIGNEXTEND, 1_U256, 0x118000_U256 => -0x8000_U256),
729 signextend10(op::SIGNEXTEND, 1_U256, 0xffff_U256 => U256::MAX),
730 signextend_noop_31(op::SIGNEXTEND, 31_U256, 0x42_U256 => 0x42_U256),
731 signextend_noop_32(op::SIGNEXTEND, 32_U256, 0x42_U256 => 0x42_U256),
732 signextend_noop_max(op::SIGNEXTEND, U256::MAX, 0x42_U256 => 0x42_U256),
733 }
734
735 cmp {
736 lt1(op::LT, 1_U256, 2_U256 => 1_U256),
737 lt2(op::LT, 2_U256, 1_U256 => 0_U256),
738 lt3(op::LT, 1_U256, 1_U256 => 0_U256),
739 lt4(op::LT, -1_U256, 1_U256 => 0_U256),
740
741 gt1(op::GT, 1_U256, 2_U256 => 0_U256),
742 gt2(op::GT, 2_U256, 1_U256 => 1_U256),
743 gt3(op::GT, 1_U256, 1_U256 => 0_U256),
744 gt4(op::GT, -1_U256, 1_U256 => 1_U256),
745
746 slt1(op::SLT, 1_U256, 2_U256 => 1_U256),
747 slt2(op::SLT, 2_U256, 1_U256 => 0_U256),
748 slt3(op::SLT, 1_U256, 1_U256 => 0_U256),
749 slt4(op::SLT, -1_U256, 1_U256 => 1_U256),
750
751 sgt1(op::SGT, 1_U256, 2_U256 => 0_U256),
752 sgt2(op::SGT, 2_U256, 1_U256 => 1_U256),
753 sgt3(op::SGT, 1_U256, 1_U256 => 0_U256),
754 sgt4(op::SGT, -1_U256, 1_U256 => 0_U256),
755
756 eq1(op::EQ, 1_U256, 2_U256 => 0_U256),
757 eq2(op::EQ, 2_U256, 1_U256 => 0_U256),
758 eq3(op::EQ, 1_U256, 1_U256 => 1_U256),
759
760 iszero1(op::ISZERO, 0_U256 => 1_U256),
761 iszero2(op::ISZERO, 1_U256 => 0_U256),
762 iszero3(op::ISZERO, 2_U256 => 0_U256),
763 }
764
765 bitwise {
766 and1(op::AND, 0_U256, 0_U256 => 0_U256),
767 and2(op::AND, 1_U256, 1_U256 => 1_U256),
768 and3(op::AND, 1_U256, 2_U256 => 0_U256),
769 and4(op::AND, 255_U256, 255_U256 => 255_U256),
770
771 or1(op::OR, 0_U256, 0_U256 => 0_U256),
772 or2(op::OR, 1_U256, 2_U256 => 3_U256),
773 or3(op::OR, 1_U256, 3_U256 => 3_U256),
774 or4(op::OR, 2_U256, 2_U256 => 2_U256),
775
776 xor1(op::XOR, 0_U256, 0_U256 => 0_U256),
777 xor2(op::XOR, 1_U256, 2_U256 => 3_U256),
778 xor3(op::XOR, 1_U256, 3_U256 => 2_U256),
779 xor4(op::XOR, 2_U256, 2_U256 => 0_U256),
780
781 not1(op::NOT, 0_U256 => U256::MAX),
782 not2(op::NOT, U256::MAX => 0_U256),
783 not3(op::NOT, 1_U256 => U256::MAX.wrapping_sub(1_U256)),
784
785 byte1(op::BYTE, 0_U256, 0x1122334400000000000000000000000000000000000000000000000000000000_U256 => 0x11_U256),
786 byte2(op::BYTE, 1_U256, 0x1122334400000000000000000000000000000000000000000000000000000000_U256 => 0x22_U256),
787 byte3(op::BYTE, 2_U256, 0x1122334400000000000000000000000000000000000000000000000000000000_U256 => 0x33_U256),
788 byte4(op::BYTE, 3_U256, 0x1122334400000000000000000000000000000000000000000000000000000000_U256 => 0x44_U256),
789 byte5(op::BYTE, 4_U256, 0x1122334400000000000000000000000000000000000000000000000000000000_U256 => 0x00_U256),
790 byte_oob0(op::BYTE, 31_U256, U256::MAX => 0xFF_U256),
791 byte_oob1(op::BYTE, 32_U256, U256::MAX => 0_U256),
792 byte_oob2(op::BYTE, 33_U256, U256::MAX => 0_U256),
793
794 shl1(op::SHL, 0_U256, 1_U256 => 1_U256),
797 shl2(op::SHL, 1_U256, 1_U256 => 2_U256),
798 shl3(op::SHL, 2_U256, 1_U256 => 4_U256),
799 shl4(op::SHL, 255_U256, -1_U256 => -1_U256 << 255),
800 shl5(op::SHL, 256_U256, -1_U256 => 0_U256),
801
802 shr1(op::SHR, 0_U256, 1_U256 => 1_U256),
803 shr2(op::SHR, 1_U256, 2_U256 => 1_U256),
804 shr3(op::SHR, 2_U256, 4_U256 => 1_U256),
805 shr4(op::SHR, 255_U256, -1_U256 => 1_U256),
806 shr5(op::SHR, 256_U256, -1_U256 => 0_U256),
807
808 sar1(op::SAR, 0_U256, 1_U256 => 1_U256),
809 sar2(op::SAR, 1_U256, 2_U256 => 1_U256),
810 sar3(op::SAR, 2_U256, 4_U256 => 1_U256),
811 sar4(op::SAR, 1_U256, -1_U256 => -1_U256),
812 sar5(op::SAR, 2_U256, -1_U256 => -1_U256),
813 sar6(op::SAR, 255_U256, -1_U256 => -1_U256),
814 sar7(op::SAR, 256_U256, -1_U256 => -1_U256),
815 }
816
817 system {
818 gas0(@raw {
819 bytecode: &[op::GAS, op::GAS, op::JUMPDEST, op::GAS],
820 expected_stack: &[DEF_GAS_LIMIT_U256 - 2_U256, DEF_GAS_LIMIT_U256 - 4_U256, DEF_GAS_LIMIT_U256 - 7_U256],
821 expected_gas: 2 + 2 + 1 + 2,
822 }),
823 keccak256_empty1(@raw {
824 bytecode: &[op::PUSH0, op::PUSH0, op::KECCAK256],
825 expected_stack: &[KECCAK_EMPTY.into()],
826 expected_gas: 2 + 2 + gas::KECCAK256,
827 }),
828 keccak256_empty2(@raw {
829 bytecode: &[op::PUSH0, op::PUSH1, 32, op::KECCAK256],
830 expected_stack: &[KECCAK_EMPTY.into()],
831 expected_gas: 2 + 3 + gas::KECCAK256,
832 }),
833 keccak256_empty_dynamic_offset(@raw {
834 bytecode: &[op::PUSH0, op::ADDRESS, op::KECCAK256],
835 expected_stack: &[KECCAK_EMPTY.into()],
836 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
837 }),
838 keccak256_1(@raw {
839 bytecode: &[op::PUSH1, 32, op::PUSH0, op::KECCAK256],
840 expected_stack: &[keccak256([0; 32]).into()],
841 expected_memory: &[0; 32],
842 expected_gas: 3 + 2 + (keccak256_cost(32).unwrap() + 3),
843 }),
844 keccak256_2(@raw {
845 bytecode: &[op::PUSH2, 0x69, 0x42, op::PUSH0, op::MSTORE, op::PUSH1, 0x20, op::PUSH0, op::KECCAK256],
846 expected_stack: &[keccak256(0x6942_U256.to_be_bytes::<32>()).into()],
847 expected_memory: &0x6942_U256.to_be_bytes::<32>(),
848 expected_gas: 3 + 2 + (3 + 3) + 3 + 2 + keccak256_cost(32).unwrap(),
849 }),
850
851 address(@raw {
852 bytecode: &[op::ADDRESS, op::ADDRESS],
853 expected_stack: &[DEF_ADDR.into_word().into(), DEF_ADDR.into_word().into()],
854 expected_gas: 4,
855 }),
856 origin(@raw {
857 bytecode: &[op::ORIGIN, op::ORIGIN],
858 expected_stack: &[def_env().tx.caller.into_word().into(), def_env().tx.caller.into_word().into()],
859 expected_gas: 4,
860 }),
861 caller(@raw {
862 bytecode: &[op::CALLER, op::CALLER],
863 expected_stack: &[DEF_CALLER.into_word().into(), DEF_CALLER.into_word().into()],
864 expected_gas: 4,
865 }),
866 callvalue(@raw {
867 bytecode: &[op::CALLVALUE, op::CALLVALUE],
868 expected_stack: &[DEF_VALUE, DEF_VALUE],
869 expected_gas: 4,
870 }),
871 }
872
873 calldata {
874 calldataload1(@raw {
875 bytecode: &[op::PUSH0, op::CALLDATALOAD],
876 expected_stack: &[U256::from_be_slice(&DEF_CD[..32])],
877 expected_gas: 2 + 3,
878 }),
879 calldataload2(@raw {
880 bytecode: &[op::PUSH1, 63, op::CALLDATALOAD],
881 expected_stack: &[0xaa00000000000000000000000000000000000000000000000000000000000000_U256],
882 expected_gas: 3 + 3,
883 }),
884 calldatasize(@raw {
885 bytecode: &[op::CALLDATASIZE, op::CALLDATASIZE],
886 expected_stack: &[U256::from(DEF_CD.len()), U256::from(DEF_CD.len())],
887 expected_gas: 2 + 2,
888 }),
889 calldatacopy(@raw {
890 bytecode: &[op::PUSH1, 32, op::PUSH0, op::PUSH0, op::CALLDATACOPY],
891 expected_memory: &DEF_CD[..32],
892 expected_gas: 3 + 2 + 2 + (verylowcopy_cost(32).unwrap() + 3),
893 }),
894 }
895
896 code {
897 codesize(@raw {
898 bytecode: &[op::CODESIZE, op::CODESIZE],
899 expected_stack: &[2_U256, 2_U256],
900 expected_gas: 2 + 2,
901 }),
902 codecopy(@raw {
903 bytecode: &[op::PUSH1, 5, op::PUSH0, op::PUSH0, op::CODECOPY],
904 expected_memory: &hex!("60055f5f39000000000000000000000000000000000000000000000000000000"),
905 expected_gas: 3 + 2 + 2 + (verylowcopy_cost(32).unwrap() + memory_gas_cost(1)),
906 }),
907 }
908
909 returndata {
910 returndatasize(@raw {
911 bytecode: &[op::RETURNDATASIZE, op::RETURNDATASIZE],
913 expected_stack: &[0_U256, 0_U256],
914 expected_gas: 2 + 2,
915 }),
916 returndatacopy(@raw {
917 bytecode: &[op::PUSH1, 32, op::PUSH0, op::PUSH0, op::RETURNDATACOPY],
919 expected_return: InstructionResult::OutOfOffset,
920 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
921 }),
922 }
923
924 extcode {
925 extcodesize1(op::EXTCODESIZE, DEF_ADDR.into_word().into() => 0_U256;
926 op_gas(100)),
927 extcodesize2(op::EXTCODESIZE, OTHER_ADDR.into_word().into() => U256::from(def_codemap()[&OTHER_ADDR].len());
928 op_gas(100)),
929 extcodecopy1(@raw {
930 bytecode: &[op::PUSH0, op::PUSH0, op::PUSH0, op::PUSH0, op::EXTCODECOPY],
931 expected_memory: &[],
932 expected_gas: 2 + 2 + 2 + 2 + 100,
933 }),
934 extcodecopy2(@raw {
935 bytecode: &hex!("6040 5f 5f 736969696969696969696969696969696969696969 3c"),
937 expected_memory: &{
938 let mut mem = [0; 64];
939 let code = def_codemap()[&OTHER_ADDR].original_bytes();
940 mem[..code.len()].copy_from_slice(&code);
941 mem
942 },
943 expected_gas: 3 + 2 + 2 + 3 + (100 + 12),
944 }),
945 extcodehash1(op::EXTCODEHASH, DEF_ADDR.into_word().into() => KECCAK_EMPTY.into();
946 op_gas(100)),
947 extcodehash2(op::EXTCODEHASH, OTHER_ADDR.into_word().into() => def_codemap()[&OTHER_ADDR].hash_slow().into();
948 op_gas(100)),
949 }
950
951 env {
952 gas_price(@raw {
953 bytecode: &[op::GASPRICE],
954 expected_stack: &[def_env().effective_gas_price()],
955 expected_gas: 2,
956 }),
957 blockhash0(op::BLOCKHASH, DEF_BN - 0_U256 => 0_U256), blockhash1(op::BLOCKHASH, DEF_BN - 1_U256 => DEF_BN - 1_U256), blockhash2(op::BLOCKHASH, DEF_BN - 255_U256 => DEF_BN - 255_U256), blockhash3(op::BLOCKHASH, DEF_BN - 256_U256 => DEF_BN - 256_U256), blockhash4(op::BLOCKHASH, DEF_BN - 257_U256 => 0_U256), coinbase(@raw {
967 bytecode: &[op::COINBASE, op::COINBASE],
968 expected_stack: &[def_env().block.coinbase.into_word().into(), def_env().block.coinbase.into_word().into()],
969 expected_gas: 4,
970 }),
971 timestamp(@raw {
972 bytecode: &[op::TIMESTAMP, op::TIMESTAMP],
973 expected_stack: &[def_env().block.timestamp, def_env().block.timestamp],
974 expected_gas: 4,
975 }),
976 number(@raw {
977 bytecode: &[op::NUMBER, op::NUMBER],
978 expected_stack: &[def_env().block.number, def_env().block.number],
979 expected_gas: 4,
980 }),
981 difficulty(@raw {
982 bytecode: &[op::DIFFICULTY, op::DIFFICULTY],
983 spec_id: SpecId::LONDON,
984 expected_stack: &[def_env().block.difficulty, def_env().block.difficulty],
985 expected_gas: 4,
986 }),
987 difficulty_prevrandao(@raw {
988 bytecode: &[op::DIFFICULTY, op::DIFFICULTY],
989 spec_id: SpecId::MERGE,
990 expected_stack: &[def_env().block.prevrandao.unwrap().into(), def_env().block.prevrandao.unwrap().into()],
991 expected_gas: 4,
992 }),
993 gaslimit(@raw {
994 bytecode: &[op::GASLIMIT, op::GASLIMIT],
995 expected_stack: &[def_env().block.gas_limit, def_env().block.gas_limit],
996 expected_gas: 4,
997 }),
998 chainid(@raw {
999 bytecode: &[op::CHAINID, op::CHAINID],
1000 expected_stack: &[U256::from(def_env().cfg.chain_id), U256::from(def_env().cfg.chain_id)],
1001 expected_gas: 4,
1002 }),
1003 selfbalance(@raw {
1004 bytecode: &[op::SELFBALANCE, op::SELFBALANCE],
1005 expected_stack: &[0xba_U256, 0xba_U256],
1006 expected_gas: 10,
1007 }),
1008 basefee(@raw {
1009 bytecode: &[op::BASEFEE, op::BASEFEE],
1010 expected_stack: &[def_env().block.basefee, def_env().block.basefee],
1011 expected_gas: 4,
1012 }),
1013 blobhash0(@raw {
1014 bytecode: &[op::PUSH0, op::BLOBHASH],
1015 expected_stack: &[def_env().tx.blob_hashes[0].into()],
1016 expected_gas: 2 + 3,
1017 }),
1018 blobhash1(@raw {
1019 bytecode: &[op::PUSH1, 1, op::BLOBHASH],
1020 expected_stack: &[def_env().tx.blob_hashes[1].into()],
1021 expected_gas: 3 + 3,
1022 }),
1023 blobhash2(@raw {
1024 bytecode: &[op::PUSH1, 2, op::BLOBHASH],
1025 expected_stack: &[0_U256],
1026 expected_gas: 3 + 3,
1027 }),
1028 blobbasefee(@raw {
1029 bytecode: &[op::BLOBBASEFEE, op::BLOBBASEFEE],
1030 expected_stack: &[U256::from(def_env().block.get_blob_gasprice().unwrap()), U256::from(def_env().block.get_blob_gasprice().unwrap())],
1031 expected_gas: 4,
1032 }),
1033 }
1034
1035 memory {
1036 mload1(@raw {
1037 bytecode: &[op::PUSH0, op::MLOAD],
1038 expected_stack: &[0_U256],
1039 expected_memory: &[0; 32],
1040 expected_gas: 2 + (3 + memory_gas_cost(1)),
1041 }),
1042 mload2(@raw {
1043 bytecode: &[op::PUSH1, 1, op::MLOAD],
1044 expected_stack: &[0_U256],
1045 expected_memory: &[0; 64],
1046 expected_gas: 3 + (3 + memory_gas_cost(2)),
1047 }),
1048 mload3(@raw {
1049 bytecode: &[op::PUSH1, 32, op::MLOAD],
1050 expected_stack: &[0_U256],
1051 expected_memory: &[0; 64],
1052 expected_gas: 3 + (3 + memory_gas_cost(2)),
1053 }),
1054 mload4(@raw {
1055 bytecode: &[op::PUSH1, 33, op::MLOAD],
1056 expected_stack: &[0_U256],
1057 expected_memory: &[0; 96],
1058 expected_gas: 3 + (3 + memory_gas_cost(3)),
1059 }),
1060 mload_overflow1(@raw {
1061 bytecode: &[op::PUSH8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, op::MLOAD],
1062 expected_return: InstructionResult::MemoryOOG,
1063 expected_stack: &[U256::from(u64::MAX)],
1064 expected_gas: 3 + 3,
1065 }),
1066 mload_overflow2(@raw {
1067 bytecode: &[op::PUSH8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - 1, op::MLOAD],
1068 expected_return: InstructionResult::MemoryOOG,
1069 expected_stack: &[U256::from(u64::MAX - 1)],
1070 expected_gas: 3 + 3,
1071 }),
1072 mload_overflow3(@raw {
1073 bytecode: &[op::PUSH8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - 31, op::MLOAD],
1074 expected_return: InstructionResult::MemoryOOG,
1075 expected_stack: &[U256::from(u64::MAX - 31)],
1076 expected_gas: 3 + 3,
1077 }),
1078 mload_overflow4(@raw {
1079 bytecode: &[op::PUSH8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - 32, op::MLOAD],
1080 expected_return: InstructionResult::MemoryOOG,
1081 expected_stack: &[U256::from(u64::MAX - 32)],
1082 expected_gas: 3 + 3,
1083 }),
1084 mload_overflow5(@raw {
1085 bytecode: &[op::PUSH8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - 33, op::MLOAD],
1086 expected_return: InstructionResult::MemoryOOG,
1087 expected_stack: &[U256::from(u64::MAX - 33)],
1088 expected_gas: 3 + 3,
1089 }),
1090 mload_overflow6(@raw {
1091 bytecode: &[op::ADDRESS, op::MLOAD],
1092 expected_return: InstructionResult::InvalidOperandOOG,
1093 expected_stack: &[DEF_ADDR.into_word().into()],
1094 expected_gas: 5,
1095 }),
1096 mload_const_offset_too_large(@raw {
1097 bytecode: &{
1098 let mut code = Vec::new();
1099 code.push(op::PUSH9);
1100 code.extend_from_slice(&0x1_0000_0000_0000_0000_U256.to_be_bytes::<32>()[23..]);
1101 code.push(op::MLOAD);
1102 code
1103 },
1104 expected_return: InstructionResult::InvalidOperandOOG,
1105 expected_stack: &[0x1_0000_0000_0000_0000_U256],
1106 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1107 }),
1108 mstore1(@raw {
1109 bytecode: &[op::PUSH0, op::PUSH0, op::MSTORE],
1110 expected_memory: &[0; 32],
1111 expected_gas: 2 + 2 + (3 + memory_gas_cost(1)),
1112 }),
1113 mstore_const_offset_dyn_value(@raw {
1114 bytecode: &bytecode_binop_mixed(op::MSTORE, 0_U256, 0x69_U256, true, false),
1115 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1116 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1117 }),
1118 mstore_dyn_offset_const_value(@raw {
1119 bytecode: &bytecode_binop_mixed(op::MSTORE, 0_U256, 0x69_U256, false, true),
1120 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1121 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1122 }),
1123 mstore_dyn_offset_dyn_value(@raw {
1124 bytecode: &bytecode_binop_mixed(op::MSTORE, 0_U256, 0x69_U256, false, false),
1125 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1126 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1127 }),
1128 mstore8_1(@raw {
1129 bytecode: &[op::PUSH0, op::PUSH0, op::MSTORE8],
1130 expected_memory: &[0; 32],
1131 expected_gas: 2 + 2 + (3 + memory_gas_cost(1)),
1132 }),
1133 mstore8_2(@raw {
1134 bytecode: &[op::PUSH2, 0x69, 0x69, op::PUSH0, op::MSTORE8],
1135 expected_memory: &{
1136 let mut mem = [0; 32];
1137 mem[0] = 0x69;
1138 mem
1139 },
1140 expected_gas: 3 + 2 + (3 + memory_gas_cost(1)),
1141 }),
1142 msize1(@raw {
1143 bytecode: &[op::MSIZE, op::MSIZE],
1144 expected_stack: &[0_U256, 0_U256],
1145 expected_gas: 2 + 2,
1146 }),
1147 msize2(@raw {
1148 bytecode: &[op::MSIZE, op::PUSH0, op::MLOAD, op::POP, op::MSIZE, op::PUSH1, 1, op::MLOAD, op::POP, op::MSIZE],
1149 expected_stack: &[0_U256, 32_U256, 64_U256],
1150 expected_memory: &[0; 64],
1151 expected_gas: 2 + 2 + (3 + memory_gas_cost(1)) + 2 + 2 + 3 + (3 + (memory_gas_cost(2) - memory_gas_cost(1))) + 2 + 2,
1152 }),
1153 mcopy1(@raw {
1154 bytecode: &[op::PUSH1, 32, op::PUSH0, op::PUSH1, 32, op::MCOPY],
1155 expected_memory: &[0; 64],
1156 expected_gas: 3 + 2 + 3 + (verylowcopy_cost(32).unwrap() + memory_gas_cost(2)),
1157 }),
1158 mcopy2(@raw {
1159 bytecode: &[op::PUSH2, 0x42, 0x69, op::PUSH0, op::MSTORE,
1160 op::PUSH1, 2, op::PUSH1, 30, op::PUSH1, 1, op::MCOPY],
1161 expected_memory: &{
1162 let mut mem = [0; 32];
1163 mem[30] = 0x42;
1164 mem[31] = 0x69;
1165 mem[1] = 0x42;
1166 mem[2] = 0x69;
1167 mem
1168 },
1169 expected_gas: 3 + 2 + (3 + memory_gas_cost(1)) +
1170 3 + 3 + 3 + verylowcopy_cost(2).unwrap(),
1171 }),
1172 }
1173
1174 host {
1175 balance(op::BALANCE, 0_U256 => 0_U256; op_gas(100)),
1176 sload1(@raw {
1177 bytecode: &[op::PUSH1, 69, op::SLOAD],
1178 expected_stack: &[42_U256],
1179 expected_gas: 3 + 100,
1180 }),
1181 sload2(@raw {
1182 bytecode: &[op::PUSH1, 70, op::SLOAD],
1183 expected_stack: &[0_U256],
1184 expected_gas: 3 + 100, }),
1186 sload3(@raw {
1187 bytecode: &[op::PUSH1, 0xff, op::SLOAD],
1188 expected_stack: &[0_U256],
1189 expected_gas: 3 + 100, }),
1191 sstore1(@raw {
1192 bytecode: &[op::PUSH1, 200, op::SLOAD, op::PUSH1, 100, op::PUSH1, 200, op::SSTORE, op::PUSH1, 200, op::SLOAD],
1193 expected_stack: &[0_U256, 100_U256],
1194 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1195 assert_host: Some(|host| {
1196 assert_eq!(host.storage.get(&200_U256), Some(&100_U256));
1197 }),
1198 }),
1199 sstore_const_inputs(@raw {
1200 bytecode: &[op::PUSH1, 42, op::PUSH0, op::SSTORE],
1201 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1202 assert_host: Some(|host| {
1203 assert_eq!(host.storage.get(&U256::ZERO), Some(&42_U256));
1204 }),
1205 }),
1206 tstore_const_inputs(@raw {
1207 bytecode: &[op::PUSH1, 42, op::PUSH1, 69, op::TSTORE],
1208 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1209 assert_host: Some(|host| {
1210 assert_eq!(host.transient_storage.get(&69_U256), Some(&42_U256));
1211 }),
1212 }),
1213 sstore_constantinople(@raw {
1214 bytecode: &[op::PC, op::PC, op::SSTORE, op::PC, op::COINBASE],
1215 spec_id: SpecId::PETERSBURG,
1216 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
1217 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1218 }),
1219 tload(@raw {
1220 bytecode: &[op::PUSH1, 69, op::TLOAD],
1221 expected_stack: &[0_U256],
1222 expected_gas: 3 + 100,
1223 assert_host: Some(|host| {
1224 assert!(host.transient_storage.is_empty());
1225 }),
1226 }),
1227 tstore(@raw {
1228 bytecode: &[op::PUSH1, 69, op::TLOAD, op::PUSH1, 42, op::PUSH1, 69, op::TSTORE, op::PUSH1, 69, op::TLOAD],
1229 expected_stack: &[0_U256, 42_U256],
1230 expected_gas: 3 + 100 + 3 + 3 + 100 + 3 + 100,
1231 assert_host: Some(|host| {
1232 assert_eq!(host.transient_storage.get(&69_U256), Some(&42_U256));
1233 }),
1234 }),
1235 log0(@raw {
1236 bytecode: &[op::PUSH0, op::PUSH0, op::LOG0],
1237 expected_gas: 2 + 2 + log_cost(0, 0).unwrap(),
1238 assert_host: Some(|host| {
1239 assert_eq!(host.logs, [Log {
1240 address: DEF_ADDR,
1241 data: LogData::new(vec![], Bytes::new()).unwrap(),
1242 }]);
1243 }),
1244 }),
1245 log0_data(@raw {
1246 bytecode: &[op::PUSH2, 0x69, 0x42, op::PUSH0, op::MSTORE, op::PUSH1, 32, op::PUSH0, op::LOG0],
1247 expected_memory: &0x6942_U256.to_be_bytes::<32>(),
1248 expected_gas: 3 + 2 + (3 + memory_gas_cost(1)) + 3 + 2 + log_cost(0, 32).unwrap(),
1249 assert_host: Some(|host| {
1250 assert_eq!(host.logs, [Log {
1251 address: DEF_ADDR,
1252 data: LogData::new(vec![], Bytes::copy_from_slice(&0x6942_U256.to_be_bytes::<32>())).unwrap(),
1253 }]);
1254 }),
1255 }),
1256 log1_1(@raw {
1257 bytecode: &[op::PUSH0, op::PUSH0, op::PUSH0, op::LOG1],
1258 expected_gas: 2 + 2 + 2 + log_cost(1, 0).unwrap(),
1259 assert_host: Some(|host| {
1260 assert_eq!(host.logs, [Log {
1261 address: DEF_ADDR,
1262 data: LogData::new(vec![B256::ZERO], Bytes::new()).unwrap(),
1263 }]);
1264 }),
1265 }),
1266 log1_2(@raw {
1267 bytecode: &hex!(
1268 "7f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff"
1269 "7f0000000000000000000000000000000000000000000000000000000000000032" "59"
1271 "a1"
1272 ),
1273 expected_memory: &[0; 64],
1274 expected_gas: 3 + 3 + 2 + (log_cost(1, 50).unwrap() + memory_gas_cost(2)),
1275 assert_host: Some(|host| {
1276 assert_eq!(host.logs, [Log {
1277 address: DEF_ADDR,
1278 data: LogData::new(
1279 vec![0xffffffffffffffffffffffffffffffffffffffff_U256.into()],
1280 Bytes::copy_from_slice(&[0; 50]),
1281 ).unwrap(),
1282 }]);
1283 }),
1284 }),
1285 log3_topic_does_not_resize_memory(@raw {
1286 bytecode: &[
1287 op::PUSH2, 0x08, 0x00, op::PUSH0, op::PUSH0, op::PUSH0, op::PUSH0, op::LOG3,
1288 op::PUSH0, op::PUSH0, op::MSTORE,
1289 ],
1290 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1291 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1292 }),
1293 create(@raw {
1294 bytecode: &[op::PUSH1, 0x69, op::PUSH0, op::MSTORE, op::PUSH1, 32, op::PUSH0, op::PUSH1, 0x42, op::CREATE],
1295 expected_return: InstructionResult::Stop,
1296 expected_stack: &[],
1298 expected_memory: &0x69_U256.to_be_bytes::<32>(),
1299 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1300 expected_next_action: InterpreterAction::NewFrame(FrameInput::Create(Box::new(CreateInputs::new(
1301 DEF_ADDR,
1302 context_interface::CreateScheme::Create,
1303 0x42_U256,
1304 Bytes::copy_from_slice(&0x69_U256.to_be_bytes::<32>()),
1305 66917,
1306 0,
1307 )))),
1308 }),
1309 create2(@raw {
1310 bytecode: &[op::PUSH1, 0x69, op::PUSH0, op::MSTORE, op::PUSH1, 100, op::PUSH1, 32, op::PUSH0, op::PUSH1, 0x42, op::CREATE2],
1311 expected_return: InstructionResult::Stop,
1312 expected_stack: &[],
1314 expected_memory: &0x69_U256.to_be_bytes::<32>(),
1315 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1316 expected_next_action: InterpreterAction::NewFrame(FrameInput::Create(Box::new(CreateInputs::new(
1317 DEF_ADDR,
1318 context_interface::CreateScheme::Create2 { salt: 100_U256 },
1319 0x42_U256,
1320 Bytes::copy_from_slice(&0x69_U256.to_be_bytes::<32>()),
1321 66908,
1322 0,
1323 )))),
1324 }),
1325 call(@raw {
1326 bytecode: &[
1327 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::PUSH1, 7, op::CALL,
1335 ],
1336 expected_return: InstructionResult::Stop,
1337 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1339 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1340 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1341 }),
1342 callcode(@raw {
1343 bytecode: &[
1344 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::PUSH1, 7, op::CALLCODE,
1352 ],
1353 expected_return: InstructionResult::Stop,
1354 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1355 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1356 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1357 }),
1358 delegatecall(@raw {
1359 bytecode: &[
1360 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::DELEGATECALL,
1367 ],
1368 expected_return: InstructionResult::Stop,
1369 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1370 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1371 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1372 }),
1373 staticcall(@raw {
1374 bytecode: &[
1375 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::STATICCALL,
1382 ],
1383 expected_return: InstructionResult::Stop,
1384 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1385 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1386 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1387 }),
1388 ret_empty_dynamic_offset(@raw {
1389 bytecode: &[op::PUSH0, op::ADDRESS, op::RETURN],
1390 expected_return: InstructionResult::Return,
1391 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1392 }),
1393 ret(@raw {
1394 bytecode: &[op::PUSH1, 0x69, op::PUSH0, op::MSTORE, op::PUSH1, 32, op::PUSH0, op::RETURN],
1395 expected_return: InstructionResult::Return,
1396 expected_memory: &0x69_U256.to_be_bytes::<32>(),
1397 expected_gas: 3 + 2 + (3 + memory_gas_cost(1)) + 3 + 2,
1398 expected_next_action: InterpreterAction::Return(
1399 InterpreterResult {
1400 result: InstructionResult::Return,
1401 output: Bytes::copy_from_slice(&0x69_U256.to_be_bytes::<32>()),
1402 gas: {
1403 let mut gas = Gas::new(DEF_GAS_LIMIT);
1404 assert!(gas.record_regular_cost(3 + 2 + (3 + memory_gas_cost(1)) + 3 + 2));
1405 gas
1406 },
1407 }
1408 ),
1409 }),
1410 revert(@raw {
1411 bytecode: &[op::PUSH1, 0x69, op::PUSH0, op::MSTORE, op::PUSH1, 32, op::PUSH0, op::REVERT],
1412 expected_return: InstructionResult::Revert,
1413 expected_memory: &0x69_U256.to_be_bytes::<32>(),
1414 expected_gas: 3 + 2 + (3 + memory_gas_cost(1)) + 3 + 2,
1415 expected_next_action: InterpreterAction::Return(
1416 InterpreterResult {
1417 result: InstructionResult::Revert,
1418 output: Bytes::copy_from_slice(&0x69_U256.to_be_bytes::<32>()),
1419 gas: {
1420 let mut gas = Gas::new(DEF_GAS_LIMIT);
1421 assert!(gas.record_regular_cost(3 + 2 + (3 + memory_gas_cost(1)) + 3 + 2));
1422 gas
1423 },
1424 }
1425 ),
1426 }),
1427 selfdestruct(@raw {
1428 bytecode: &[op::PUSH1, 0x69, op::SELFDESTRUCT, op::INVALID],
1429 expected_return: InstructionResult::SelfDestruct,
1430 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1431 assert_host: Some(|host| {
1432 assert_eq!(host.selfdestructs, [(DEF_ADDR, Address::with_last_byte(0x69))]);
1433 }),
1434 }),
1435 selfdestruct_preserves_remaining_stack(@raw {
1436 bytecode: &[op::NUMBER, op::NUMBER, op::SELFDESTRUCT],
1437 spec_id: SpecId::BERLIN,
1438 expected_return: InstructionResult::SelfDestruct,
1439 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
1440 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1441 }),
1442 selfdestruct_static_oog(@raw {
1444 bytecode: &[op::PUSH1, 0x01, op::SELFDESTRUCT],
1445 is_static: true,
1446 gas_limit: 4000,
1447 expected_return: InstructionResult::OutOfGas,
1448 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1449 }),
1450 selfdestruct_static_enough_gas(@raw {
1452 bytecode: &[op::PUSH1, 0x01, op::SELFDESTRUCT],
1453 is_static: true,
1454 expected_return: InstructionResult::StateChangeDuringStaticCall,
1455 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1456 }),
1457 }
1458
1459 call_gas {
1462 call_value_cancun(@raw {
1463 bytecode: &[
1464 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::PUSH1, 7, op::CALL,
1472 ],
1473 spec_id: SpecId::CANCUN,
1474 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1475 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1476 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1477 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1478 }),
1479 call_no_value_cancun(@raw {
1480 bytecode: &[
1481 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH0, op::PUSH1, 6, op::PUSH1, 7, op::CALL,
1489 ],
1490 spec_id: SpecId::CANCUN,
1491 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1492 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1493 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1494 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1495 }),
1496 staticcall_cancun(@raw {
1497 bytecode: &[
1498 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::STATICCALL,
1505 ],
1506 spec_id: SpecId::CANCUN,
1507 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1508 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1509 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1510 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1511 }),
1512 delegatecall_cancun(@raw {
1513 bytecode: &[
1514 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::DELEGATECALL,
1521 ],
1522 spec_id: SpecId::CANCUN,
1523 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1524 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1525 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1526 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1527 }),
1528
1529 call_value_petersburg(@raw {
1531 bytecode: &[
1532 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::PUSH1, 7, op::CALL,
1540 ],
1541 spec_id: SpecId::PETERSBURG,
1542 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1543 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1544 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1545 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1546 }),
1547 call_no_value_petersburg(@raw {
1548 bytecode: &[
1549 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 0, op::PUSH1, 6, op::PUSH1, 7, op::CALL,
1557 ],
1558 spec_id: SpecId::PETERSBURG,
1559 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1560 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1561 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1562 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1563 }),
1564 staticcall_petersburg(@raw {
1565 bytecode: &[
1566 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::STATICCALL,
1573 ],
1574 spec_id: SpecId::PETERSBURG,
1575 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1576 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1577 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1578 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1579 }),
1580 call_value_istanbul(@raw {
1581 bytecode: &[
1582 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::PUSH1, 7, op::CALL,
1590 ],
1591 spec_id: SpecId::ISTANBUL,
1592 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1593 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1594 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1595 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1596 }),
1597 call_no_value_istanbul(@raw {
1598 bytecode: &[
1599 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 0, op::PUSH1, 6, op::PUSH1, 7, op::CALL,
1607 ],
1608 spec_id: SpecId::ISTANBUL,
1609 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1610 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1611 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1612 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1613 }),
1614 staticcall_istanbul(@raw {
1615 bytecode: &[
1616 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::STATICCALL,
1623 ],
1624 spec_id: SpecId::ISTANBUL,
1625 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1626 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1627 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1628 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1629 }),
1630 call_value_byzantium(@raw {
1631 bytecode: &[
1632 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::PUSH1, 7, op::CALL,
1640 ],
1641 spec_id: SpecId::BYZANTIUM,
1642 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1643 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1644 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1645 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1646 }),
1647 call_high_gas_value_istanbul(@raw {
1648 bytecode: &[
1649 op::PUSH1, 32, op::PUSH1, 0, op::PUSH1, 64, op::PUSH1, 0, op::PUSH1, 100, op::PUSH1, 0x69, op::PUSH2, 0xFF, 0xFF, op::CALL,
1657 ],
1658 spec_id: SpecId::ISTANBUL,
1659 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1660 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1661 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1662 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1663 }),
1664 call_value_muir_glacier(@raw {
1666 bytecode: &[
1667 op::PUSH1, 1, op::PUSH1, 2, op::PUSH1, 3, op::PUSH1, 4, op::PUSH1, 5, op::PUSH1, 6, op::PUSH1, 7, op::CALL,
1675 ],
1676 spec_id: SpecId::ISTANBUL,
1677 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1678 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1679 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1680 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1681 }),
1682 call_high_gas_value(@raw {
1683 bytecode: &[
1684 op::PUSH1, 32, op::PUSH0, op::PUSH1, 64, op::PUSH0, op::PUSH1, 100, op::PUSH1, 0x69, op::PUSH2, 0xFF, 0xFF, op::CALL,
1692 ],
1693 spec_id: SpecId::CANCUN,
1694 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1695 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1696 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1697 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1698 }),
1699 call_known_bytecode(@raw {
1700 bytecode: &[
1701 op::PUSH1, 0, op::PUSH1, 0, op::PUSH1, 0, op::PUSH1, 0, op::PUSH1, 0, op::PUSH1, 0x69, op::PUSH1, 7, op::CALL,
1709 ],
1710 spec_id: SpecId::CANCUN,
1711 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1712 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1713 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1714 expected_next_action: ACTION_WHAT_INTERPRETER_SAYS,
1715 assert_ecx: Some(|ecx| {
1716 if let Some(InterpreterAction::NewFrame(FrameInput::Call(call_inputs))) =
1717 ecx.next_action.as_ref()
1718 {
1719 let (code_hash, _) = &call_inputs.known_bytecode;
1720 assert!(
1721 !code_hash.is_zero(),
1722 "CALL must populate known_bytecode via load_account_delegated; \
1723 got zero code hash (old code path that skips delegation resolution)"
1724 );
1725 }
1726 }),
1727 }),
1728 }
1729
1730 i256_lanes {
1734 add_full_width(op::ADD,
1736 0xDEADBEEF_12345678_ABCDEF01_23456789_FEDCBA98_76543210_01234567_89ABCDEF_U256,
1737 0x11111111_22222222_33333333_44444444_55555555_66666666_77777777_88888888_U256
1738 => 0xDEADBEEF_12345678_ABCDEF01_23456789_FEDCBA98_76543210_01234567_89ABCDEF_U256
1739 + 0x11111111_22222222_33333333_44444444_55555555_66666666_77777777_88888888_U256
1740 ),
1741 mul_full_width(op::MUL,
1743 0x00000000_00000000_00000000_00000000_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_U256,
1744 0x00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000002_U256
1745 => 0x00000000_00000000_00000000_00000001_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_U256
1746 ),
1747 sub_cross_lane(op::SUB,
1749 0x00000000_00000000_00000000_00000001_00000000_00000000_00000000_00000000_U256,
1750 0x00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001_U256
1751 => 0x00000000_00000000_00000000_00000000_FFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFF_U256
1752 ),
1753 or_all_lanes(op::OR,
1755 0xFF000000_00000000_00FF0000_00000000_0000FF00_00000000_000000FF_00000000_U256,
1756 0x00000000_FF000000_00000000_00FF0000_00000000_0000FF00_00000000_000000FF_U256
1757 => 0xFF000000_FF000000_00FF0000_00FF0000_0000FF00_0000FF00_000000FF_000000FF_U256
1758 ),
1759 shl_cross_lane(op::SHL,
1761 64_U256,
1762 0x00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001_U256
1763 => 0x00000000_00000000_00000000_00000000_00000000_00000001_00000000_00000000_U256
1764 ),
1765 shr_cross_lane(op::SHR,
1767 64_U256,
1768 0x00000000_00000001_00000000_00000000_00000000_00000000_00000000_00000000_U256
1769 => 0x00000000_00000000_00000000_00000001_00000000_00000000_00000000_00000000_U256
1770 ),
1771 }
1772
1773 codecopy_fix {
1777 codecopy_exact(@raw {
1778 bytecode: &[op::PUSH1, 5, op::PUSH0, op::PUSH0, op::CODECOPY],
1779 expected_memory: &hex!("60055f5f39000000000000000000000000000000000000000000000000000000"),
1780 expected_gas: 3 + 2 + 2 + (verylowcopy_cost(32).unwrap() + memory_gas_cost(1)),
1781 }),
1782 codecopy_offset(@raw {
1783 bytecode: &[op::PUSH1, 3, op::PUSH1, 2, op::PUSH0, op::CODECOPY],
1784 expected_memory: &hex!("60025f0000000000000000000000000000000000000000000000000000000000"),
1785 expected_gas: 3 + 3 + 2 + (verylowcopy_cost(32).unwrap() + memory_gas_cost(1)),
1786 }),
1787 codecopy_beyond(@raw {
1788 bytecode: &[op::PUSH1, 10, op::PUSH0, op::PUSH0, op::CODECOPY],
1789 expected_memory: &hex!("600a5f5f39000000000000000000000000000000000000000000000000000000"),
1790 expected_gas: 3 + 2 + 2 + (verylowcopy_cost(32).unwrap() + memory_gas_cost(1)),
1791 }),
1792 codecopy_longer(@raw {
1793 bytecode: &[
1794 op::PUSH1, 42, op::POP, op::PUSH1, 99, op::POP, op::PUSH1, 12, op::PUSH0, op::PUSH0, op::CODECOPY, ],
1803 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
1804 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1805 }),
1806 codecopy_runtime_ptr(@raw {
1810 bytecode: &[op::PUSH1, 5, op::PUSH0, op::PUSH0, op::CODECOPY],
1811 modify_ecx: Some(|ecx| {
1812 static FAKE_CODE: [u8; 5] = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE];
1813 ecx.bytecode = &FAKE_CODE as *const [u8];
1814 }),
1815 expected_return: InstructionResult::Stop,
1816 expected_memory: &hex!("AABBCCDDEE000000000000000000000000000000000000000000000000000000"),
1817 expected_gas: 3 + 2 + 2 + (verylowcopy_cost(32).unwrap() + memory_gas_cost(1)),
1818 }),
1819 }
1820
1821 dedup {
1822 transitive_redirect_multi_jump(@raw {
1831 bytecode: &asm("
1832 ; entry: dispatch on CALLDATASIZE (nonzero -> path1)
1833 CALLDATASIZE
1834 PUSH %path1
1835 JUMPI
1836 ; not taken: u0 via t0
1837 PUSH %u0
1838 PUSH %t0
1839 JUMP
1840
1841 path1:
1842 JUMPDEST
1843 CALLVALUE
1844 PUSH %path2
1845 JUMPI
1846 ; not taken: u1 via t1 via fn
1847 PUSH %u1
1848 PUSH %t1
1849 PUSH %fn
1850 JUMP
1851
1852 path2:
1853 JUMPDEST
1854 ; u1 via t2 via fn
1855 PUSH %u1
1856 PUSH %t2
1857 PUSH %fn
1858 JUMP
1859
1860 dead0: INVALID
1861 dead1: INVALID
1862 dead2: INVALID
1863
1864 ; three byte-identical trampolines that get deduped (t2->t1->t0)
1865 t0: JUMPDEST JUMP
1866 t1: JUMPDEST JUMP
1867 t2: JUMPDEST JUMP
1868
1869 u0: JUMPDEST STOP
1870 u1: JUMPDEST STOP
1871
1872 fn: JUMPDEST JUMP
1873 "),
1874 spec_id: SpecId::CANCUN,
1875 expected_return: RETURN_WHAT_INTERPRETER_SAYS,
1876 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
1877 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1878 }),
1879
1880 dedup_multi_jump_dispatcher(@raw {
1888 bytecode: &asm("
1889 ; dispatch on first calldata word
1890 PUSH0
1891 CALLDATALOAD
1892 PUSH %d1
1893 JUMPI
1894
1895 ; dispatch on second calldata word
1896 PUSH 0x20
1897 CALLDATALOAD
1898 PUSH %d0
1899 JUMPI
1900
1901 ; neither taken: stop0 via fn1
1902 PUSH %stop0
1903 PUSH %fn1
1904 JUMP
1905
1906 d0:
1907 JUMPDEST
1908 PUSH %stop1
1909 PUSH %fn1
1910 JUMP
1911
1912 d1:
1913 JUMPDEST
1914 PUSH 0x20
1915 CALLDATALOAD
1916 PUSH %d1_taken
1917 JUMPI
1918 ; not taken: stop2 via fn2
1919 PUSH %stop2
1920 PUSH %fn2
1921 JUMP
1922
1923 d1_taken:
1924 JUMPDEST
1925 PUSH %stop3
1926 PUSH %fn2
1927 JUMP
1928
1929 stop0: JUMPDEST STOP
1930 stop1: JUMPDEST STOP
1931 stop2: JUMPDEST STOP
1932 stop3: JUMPDEST STOP
1933
1934 ; two byte-identical dispatchers that get deduped
1935 fn1: JUMPDEST JUMP
1936 fn2: JUMPDEST JUMP
1937 "),
1938 expected_return: InstructionResult::Stop,
1939 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1940 }),
1941 }
1942
1943 regressions {
1944 dedup_leader_propagation(@raw {
1953 bytecode: &asm("
1954 entry:
1955 JUMPDEST
1956 PUSH 0x00 ; cond = 0
1957 PUSH %jumpi2
1958 JUMPI ; not taken
1959 ; canonical fall-through
1960 PUSH %jumpi2
1961 JUMP
1962
1963 jumpi2:
1964 JUMPDEST
1965 PUSH 0x2a ; live-out value DSE must preserve
1966 CALLDATASIZE ; condition (nonzero)
1967 PUSH %dest
1968 JUMPI ; taken
1969 ; duplicate fall-through (same bytes as canonical -> deduped)
1970 PUSH %jumpi2
1971 JUMP
1972
1973 INVALID ; alive after dead deduped block
1974
1975 dest:
1976 JUMPDEST
1977 PUSH 0x00
1978 MSTORE ; mem[0] = 0x2a
1979 PUSH 0x20
1980 PUSH 0x00
1981 RETURN
1982 "),
1983 inspect_stack: Some(false),
1984 expected_return: InstructionResult::Return,
1985 expected_memory: &U256::from(0x2a).to_be_bytes::<32>(),
1986 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
1987 expected_next_action: InterpreterAction::Return(
1988 InterpreterResult {
1989 result: InstructionResult::Return,
1990 output: Bytes::copy_from_slice(&U256::from(0x2a).to_be_bytes::<32>()),
1991 gas: Gas::new(GAS_WHAT_INTERPRETER_SAYS),
1992 }
1993 ),
1994 }),
1995
1996 dedup_jumpdest_leader(@raw {
2001 bytecode: &asm("
2002 entry:
2003 JUMPDEST
2004 PUSH 0x00
2005 CALLDATASIZE
2006 PUSH %alt_entry
2007 JUMPI
2008 ; not-taken -> dup_ret (makes it reachable for analysis)
2009 PUSH %dup_ret
2010 JUMP
2011
2012 canonical_ret:
2013 JUMPDEST
2014 PUSH %dest
2015 JUMP
2016
2017 alt_entry:
2018 JUMPDEST
2019 DUP1
2020 POP
2021 POP
2022 PUSH 0x2a ; <- DSE must NOT kill
2023
2024 dup_ret:
2025 ; byte-identical to canonical_ret -> deduped
2026 JUMPDEST
2027 PUSH %dest
2028 JUMP
2029
2030 INVALID ; alive after dead dup_ret
2031
2032 dest:
2033 JUMPDEST
2034 PUSH 0x00
2035 MSTORE
2036 PUSH 0x20
2037 PUSH 0x00
2038 RETURN
2039 "),
2040 inspect_stack: Some(false),
2041 expected_return: InstructionResult::Return,
2042 expected_memory: &U256::from(0x2a).to_be_bytes::<32>(),
2043 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
2044 expected_next_action: InterpreterAction::Return(
2045 InterpreterResult {
2046 result: InstructionResult::Return,
2047 output: Bytes::copy_from_slice(&U256::from(0x2a).to_be_bytes::<32>()),
2048 gas: Gas::new(GAS_WHAT_INTERPRETER_SAYS),
2049 }
2050 ),
2051 }),
2052
2053 dedup_false_jumpi_non_jumpdest_fallthrough(@raw {
2054 bytecode: &asm("
2055 CALLDATASIZE
2056 PUSH %path2
2057 JUMPI
2058
2059 PUSH0
2060 PUSH %done
2061 JUMPI
2062 PUSH0
2063 PUSH0
2064 REVERT
2065
2066 path2:
2067 JUMPDEST
2068 PUSH0
2069 PUSH %done
2070 JUMPI
2071 PUSH0
2072 PUSH0
2073 REVERT
2074
2075 done:
2076 JUMPDEST
2077 STOP
2078 "),
2079 expected_return: InstructionResult::Revert,
2080 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
2081 }),
2082
2083 dedup_fallthrough_jump_tail_charges_jump_gas(@raw {
2084 bytecode: &asm("
2085 PUSH %done
2086 CALLER
2087 PUSH %path2
2088 JUMPI
2089 JUMP
2090
2091 path2:
2092 JUMPDEST
2093 PUSH0
2094 PUSH %other
2095 JUMPI
2096 JUMP
2097
2098 other:
2099 JUMPDEST
2100 STOP
2101
2102 done:
2103 JUMPDEST
2104 STOP
2105 "),
2106 expected_return: InstructionResult::Stop,
2107 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
2108 }),
2109
2110 dedup_fallthrough_redirect_materializes_stack(@raw {
2111 bytecode: &asm("
2112 CALLVALUE
2113 PUSH 123456789
2114 SUB
2115 PUSH %join_a
2116 JUMPI
2117 CALLVALUE
2118 PUSH 123456789
2119 SUB
2120 PUSH %join_b
2121 JUMPI
2122
2123 CALLDATASIZE
2124 PUSH %case_b_entry
2125 JUMPI
2126
2127 PUSH0
2128 PUSH0
2129 PUSH %case_a
2130 JUMP
2131
2132 case_a:
2133 JUMPDEST
2134 PUSH 0xaa
2135 SWAP2
2136 POP
2137 join_a:
2138 JUMPDEST
2139 PUSH %done
2140 JUMP
2141
2142 case_b_entry:
2143 JUMPDEST
2144 PUSH0
2145 PUSH0
2146 PUSH %case_b
2147 JUMP
2148
2149 case_b:
2150 JUMPDEST
2151 PUSH 0xbb
2152 SWAP2
2153 POP
2154 join_b:
2155 JUMPDEST
2156 PUSH %done
2157 JUMP
2158
2159 done:
2160 JUMPDEST
2161 POP
2162 ISZERO
2163 PUSH %bad
2164 JUMPI
2165 STOP
2166
2167 bad:
2168 JUMPDEST
2169 PUSH0
2170 PUSH0
2171 REVERT
2172 "),
2173 inspect_stack: Some(false),
2174 expected_return: InstructionResult::Stop,
2175 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
2176 }),
2177
2178 calldatasize_tstore_shanghai(@raw {
2187 bytecode: &[op::CALLDATASIZE, op::TSTORE],
2188 spec_id: SpecId::SHANGHAI,
2189 expected_return: InstructionResult::NotActivated,
2190 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
2191 }),
2192
2193 push0_tload_shanghai(@raw {
2195 bytecode: &[op::PUSH0, op::TLOAD],
2196 spec_id: SpecId::SHANGHAI,
2197 expected_return: InstructionResult::NotActivated,
2198 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
2199 }),
2200
2201 st_solidity_keywords(@raw {
2204 bytecode: &hex!("7c01000000000000000000000000000000000000000000000000000000006000350463380e439681146037578063c040622614604757005b603d6084565b8060005260206000f35b604d6057565b8060005260206000f35b6000605f6084565b600060006101000a81548160ff0219169083021790555060ff60016000540416905090565b6000808160011560cd575b600a82121560a157600190910190608f565b81600a1460ac5760c9565b50600a5b60008160ff16111560c85760019182900391900360b0565b5b60d5565b6000925060ed565b8160001460e05760e8565b6001925060ed565b600092505b50509056"),
2205 spec_id: SpecId::ISTANBUL,
2206 modify_ecx: Some(|ecx| {
2207 ecx.input.call_value = 1_U256;
2208 ecx.input.input = interpreter::CallInput::Bytes(Bytes::from(&hex!("c0406226")));
2209 }),
2210 expected_return: InstructionResult::Return,
2214 expected_stack: STACK_WHAT_INTERPRETER_SAYS,
2215 expected_gas: GAS_WHAT_INTERPRETER_SAYS,
2216 expected_memory: MEMORY_WHAT_INTERPRETER_SAYS,
2217 expected_next_action: InterpreterAction::Return(
2218 InterpreterResult {
2219 result: InstructionResult::Return,
2220 output: Bytes::copy_from_slice(&1_U256.to_be_bytes::<32>()),
2221 gas: Gas::new(GAS_WHAT_INTERPRETER_SAYS),
2222 }
2223 ),
2224 assert_host: Some(|host| {
2225 assert_eq!(host.storage.get(&0_U256), Some(&1_U256));
2226 }),
2227 }),
2228 }
2229}
2230
2231fn bytecode_unop(op: u8, a: U256) -> [u8; 34] {
2232 let mut code = [0; 34];
2233 let mut i = 0;
2234 build_push32!(code[i], a);
2235 code[i] = op;
2236 code
2237}
2238
2239fn bytecode_binop(op: u8, a: U256, b: U256) -> [u8; 67] {
2240 let mut code = [0; 67];
2241 let mut i = 0;
2242 build_push32!(code[i], b);
2243 build_push32!(code[i], a);
2244 code[i] = op;
2245 code
2246}
2247
2248fn bytecode_ternop(op: u8, a: U256, b: U256, c: U256) -> [u8; 100] {
2249 let mut code = [0; 100];
2250 let mut i = 0;
2251 build_push32!(code[i], c);
2252 build_push32!(code[i], b);
2253 build_push32!(code[i], a);
2254 code[i] = op;
2255 code
2256}
2257
2258fn bytecode_unop_opaque(opcode: u8, a: U256) -> Vec<u8> {
2260 let mut code = Vec::with_capacity(64);
2261 code.push(op::PUSH32);
2262 code.extend_from_slice(&a.to_be_bytes::<32>());
2263 code.push(op::PUSH1);
2264 code.push(0x00);
2265 code.push(op::MSTORE);
2266 code.push(op::PUSH1);
2267 code.push(0x00);
2268 code.push(op::MLOAD);
2269 code.push(opcode);
2270 code
2271}
2272
2273fn push_const_or_load(code: &mut Vec<u8>, value: U256, is_const: bool, offset: u8) {
2274 if is_const {
2275 code.push(op::PUSH32);
2276 code.extend_from_slice(&value.to_be_bytes::<32>());
2277 } else {
2278 code.push(op::PUSH1);
2279 code.push(offset);
2280 code.push(op::MLOAD);
2281 }
2282}
2283
2284fn store_dynamic_operands(code: &mut Vec<u8>, operands: &[(U256, bool, u8)]) {
2285 for &(value, is_const, offset) in operands {
2286 if !is_const {
2287 code.push(op::PUSH32);
2288 code.extend_from_slice(&value.to_be_bytes::<32>());
2289 code.push(op::PUSH1);
2290 code.push(offset);
2291 code.push(op::MSTORE);
2292 }
2293 }
2294}
2295
2296fn bytecode_binop_mixed(opcode: u8, a: U256, b: U256, a_const: bool, b_const: bool) -> Vec<u8> {
2297 let mut code = Vec::with_capacity(128);
2298 store_dynamic_operands(&mut code, &[(a, a_const, 0x00), (b, b_const, 0x20)]);
2299 push_const_or_load(&mut code, b, b_const, 0x20);
2300 push_const_or_load(&mut code, a, a_const, 0x00);
2301 code.push(opcode);
2302 code
2303}
2304
2305fn bytecode_ternop_mixed(
2306 opcode: u8,
2307 a: U256,
2308 b: U256,
2309 c: U256,
2310 a_const: bool,
2311 b_const: bool,
2312 c_const: bool,
2313) -> Vec<u8> {
2314 let mut code = Vec::with_capacity(192);
2315 store_dynamic_operands(
2316 &mut code,
2317 &[(a, a_const, 0x00), (b, b_const, 0x20), (c, c_const, 0x40)],
2318 );
2319 push_const_or_load(&mut code, c, c_const, 0x40);
2320 push_const_or_load(&mut code, b, b_const, 0x20);
2321 push_const_or_load(&mut code, a, a_const, 0x00);
2322 code.push(opcode);
2323 code
2324}
2325
2326fn asm(s: &str) -> Vec<u8> {
2327 crate::parse_asm(s).unwrap()
2328}