revm_interpreter/instructions/
stack.rs1use crate::{
2 gas,
3 instructions::utility::cast_slice_to_u256,
4 interpreter::Interpreter,
5 interpreter_types::{Immediates, InterpreterTypes, Jumps, LoopControl, RuntimeFlag, StackTr},
6 Host,
7};
8use primitives::U256;
9
10pub fn pop<WIRE: InterpreterTypes, H: Host + ?Sized>(
11 interpreter: &mut Interpreter<WIRE>,
12 _host: &mut H,
13) {
14 gas!(interpreter, gas::BASE);
15 popn!([_i], interpreter);
17}
18
19pub fn push0<WIRE: InterpreterTypes, H: Host + ?Sized>(
23 interpreter: &mut Interpreter<WIRE>,
24 _host: &mut H,
25) {
26 check!(interpreter, SHANGHAI);
27 gas!(interpreter, gas::BASE);
28 push!(interpreter, U256::ZERO);
29}
30
31pub fn push<const N: usize, WIRE: InterpreterTypes, H: Host + ?Sized>(
32 interpreter: &mut Interpreter<WIRE>,
33 _host: &mut H,
34) {
35 gas!(interpreter, gas::VERYLOW);
36 push!(interpreter, U256::ZERO);
37 popn_top!([], top, interpreter);
38
39 let imm = interpreter.bytecode.read_slice(N);
40 cast_slice_to_u256(imm, top);
41
42 interpreter.bytecode.relative_jump(N as isize);
44}
45
46pub fn dup<const N: usize, WIRE: InterpreterTypes, H: Host + ?Sized>(
47 interpreter: &mut Interpreter<WIRE>,
48 _host: &mut H,
49) {
50 gas!(interpreter, gas::VERYLOW);
51 if !interpreter.stack.dup(N) {
52 interpreter
53 .control
54 .set_instruction_result(crate::InstructionResult::StackOverflow);
55 }
56}
57
58pub fn swap<const N: usize, WIRE: InterpreterTypes, H: Host + ?Sized>(
59 interpreter: &mut Interpreter<WIRE>,
60 _host: &mut H,
61) {
62 gas!(interpreter, gas::VERYLOW);
63 assert!(N != 0);
64 if !interpreter.stack.exchange(0, N) {
65 interpreter
66 .control
67 .set_instruction_result(crate::InstructionResult::StackOverflow);
68 }
69}
70
71pub fn dupn<WIRE: InterpreterTypes, H: Host + ?Sized>(
72 interpreter: &mut Interpreter<WIRE>,
73 _host: &mut H,
74) {
75 require_eof!(interpreter);
76 gas!(interpreter, gas::VERYLOW);
77 let imm = interpreter.bytecode.read_u8();
78 if !interpreter.stack.dup(imm as usize + 1) {
79 interpreter
80 .control
81 .set_instruction_result(crate::InstructionResult::StackOverflow);
82 }
83 interpreter.bytecode.relative_jump(1);
84}
85
86pub fn swapn<WIRE: InterpreterTypes, H: Host + ?Sized>(
87 interpreter: &mut Interpreter<WIRE>,
88 _host: &mut H,
89) {
90 require_eof!(interpreter);
91 gas!(interpreter, gas::VERYLOW);
92 let imm = interpreter.bytecode.read_u8();
93 if !interpreter.stack.exchange(0, imm as usize + 1) {
94 interpreter
95 .control
96 .set_instruction_result(crate::InstructionResult::StackOverflow);
97 }
98 interpreter.bytecode.relative_jump(1);
99}
100
101pub fn exchange<WIRE: InterpreterTypes, H: Host + ?Sized>(
102 interpreter: &mut Interpreter<WIRE>,
103 _host: &mut H,
104) {
105 require_eof!(interpreter);
106 gas!(interpreter, gas::VERYLOW);
107 let imm = interpreter.bytecode.read_u8();
108 let n = (imm >> 4) + 1;
109 let m = (imm & 0x0F) + 1;
110 if !interpreter.stack.exchange(n as usize, m as usize) {
111 interpreter
112 .control
113 .set_instruction_result(crate::InstructionResult::StackOverflow);
114 }
115 interpreter.bytecode.relative_jump(1);
116}
117
118#[cfg(test)]
119mod test {
120
121 use super::*;
122 use crate::{host::DummyHost, instruction_table, InstructionResult};
123 use bytecode::opcode::{DUPN, EXCHANGE, STOP, SWAPN};
124 use bytecode::Bytecode;
125 use primitives::{Bytes, U256};
126
127 #[test]
128 fn dupn() {
129 let bytecode = Bytecode::new_raw(Bytes::from(&[DUPN, 0x00, DUPN, 0x01, DUPN, 0x02, STOP]));
130 let mut interpreter = Interpreter::default().with_bytecode(bytecode);
131
132 let table = instruction_table();
133 let mut host = DummyHost;
134
135 interpreter.runtime_flag.is_eof = true;
136 let _ = interpreter.stack.push(U256::from(10));
137 let _ = interpreter.stack.push(U256::from(20));
138 interpreter.step(&table, &mut host);
139 assert_eq!(interpreter.stack.pop(), Ok(U256::from(20)));
140 interpreter.step(&table, &mut host);
141 assert_eq!(interpreter.stack.pop(), Ok(U256::from(10)));
142 interpreter.step(&table, &mut host);
143 assert_eq!(
144 interpreter.control.instruction_result,
145 InstructionResult::StackOverflow
146 );
147 }
148
149 #[test]
150 fn swapn() {
151 let bytecode = Bytecode::new_raw(Bytes::from(&[SWAPN, 0x00, SWAPN, 0x01, STOP]));
152 let mut interpreter = Interpreter::default().with_bytecode(bytecode);
153
154 let table = instruction_table();
155 let mut host = DummyHost;
156 interpreter.runtime_flag.is_eof = true;
157
158 let _ = interpreter.stack.push(U256::from(10));
159 let _ = interpreter.stack.push(U256::from(20));
160 let _ = interpreter.stack.push(U256::from(0));
161 interpreter.step(&table, &mut host);
162 assert_eq!(interpreter.stack.peek(0), Ok(U256::from(20)));
163 assert_eq!(interpreter.stack.peek(1), Ok(U256::from(0)));
164 interpreter.step(&table, &mut host);
165 assert_eq!(interpreter.stack.peek(0), Ok(U256::from(10)));
166 assert_eq!(interpreter.stack.peek(2), Ok(U256::from(20)));
167 }
168
169 #[test]
170 fn exchange() {
171 let bytecode = Bytecode::new_raw(Bytes::from(&[EXCHANGE, 0x00, EXCHANGE, 0x11, STOP]));
172 let mut interpreter = Interpreter::default().with_bytecode(bytecode);
173
174 let table = instruction_table();
175 let mut host = DummyHost;
176 interpreter.runtime_flag.is_eof = true;
177
178 let _ = interpreter.stack.push(U256::from(1));
179 let _ = interpreter.stack.push(U256::from(5));
180 let _ = interpreter.stack.push(U256::from(10));
181 let _ = interpreter.stack.push(U256::from(15));
182 let _ = interpreter.stack.push(U256::from(0));
183
184 interpreter.step(&table, &mut host);
185 assert_eq!(interpreter.stack.peek(1), Ok(U256::from(10)));
186 assert_eq!(interpreter.stack.peek(2), Ok(U256::from(15)));
187 interpreter.step(&table, &mut host);
188 assert_eq!(interpreter.stack.peek(2), Ok(U256::from(1)));
189 assert_eq!(interpreter.stack.peek(4), Ok(U256::from(15)));
190 }
191}