revm_interpreter/instructions/
stack.rs

1use crate::{
2    gas,
3    instructions::utility::cast_slice_to_u256,
4    interpreter_types::{Immediates, InterpreterTypes, Jumps, RuntimeFlag, StackTr},
5    InstructionResult,
6};
7use primitives::U256;
8
9use crate::InstructionContext;
10
11/// Implements the POP instruction.
12///
13/// Removes the top item from the stack.
14pub fn pop<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
15    gas!(context.interpreter, gas::BASE);
16    // Can ignore return. as relative N jump is safe operation.
17    popn!([_i], context.interpreter);
18}
19
20/// EIP-3855: PUSH0 instruction
21///
22/// Introduce a new instruction which pushes the constant value 0 onto the stack.
23pub fn push0<WIRE: InterpreterTypes, H: ?Sized>(context: InstructionContext<'_, H, WIRE>) {
24    check!(context.interpreter, SHANGHAI);
25    gas!(context.interpreter, gas::BASE);
26    push!(context.interpreter, U256::ZERO);
27}
28
29/// Implements the PUSH1-PUSH32 instructions.
30///
31/// Pushes N bytes from bytecode onto the stack as a 32-byte value.
32pub fn push<const N: usize, WIRE: InterpreterTypes, H: ?Sized>(
33    context: InstructionContext<'_, H, WIRE>,
34) {
35    gas!(context.interpreter, gas::VERYLOW);
36    push!(context.interpreter, U256::ZERO);
37    popn_top!([], top, context.interpreter);
38
39    let imm = context.interpreter.bytecode.read_slice(N);
40    cast_slice_to_u256(imm, top);
41
42    // Can ignore return. as relative N jump is safe operation
43    context.interpreter.bytecode.relative_jump(N as isize);
44}
45
46/// Implements the DUP1-DUP16 instructions.
47///
48/// Duplicates the Nth stack item to the top of the stack.
49pub fn dup<const N: usize, WIRE: InterpreterTypes, H: ?Sized>(
50    context: InstructionContext<'_, H, WIRE>,
51) {
52    gas!(context.interpreter, gas::VERYLOW);
53    if !context.interpreter.stack.dup(N) {
54        context.interpreter.halt(InstructionResult::StackOverflow);
55    }
56}
57
58/// Implements the SWAP1-SWAP16 instructions.
59///
60/// Swaps the top stack item with the Nth stack item.
61pub fn swap<const N: usize, WIRE: InterpreterTypes, H: ?Sized>(
62    context: InstructionContext<'_, H, WIRE>,
63) {
64    gas!(context.interpreter, gas::VERYLOW);
65    assert!(N != 0);
66    if !context.interpreter.stack.exchange(0, N) {
67        context.interpreter.halt(InstructionResult::StackOverflow);
68    }
69}