revm_interpreter/instructions/
stack.rs1use crate::{
2 interpreter_types::{Immediates, InterpreterTypes as ITy, Jumps, RuntimeFlag, StackTr},
3 InstructionContext as Ictx, InstructionExecResult as Result, InstructionResult,
4};
5use primitives::U256;
6
7pub fn pop<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
11 popn!([_i], context.interpreter);
13 Ok(())
14}
15
16pub fn push0<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
20 check!(context.interpreter, SHANGHAI);
21 push!(context.interpreter, U256::ZERO);
22 Ok(())
23}
24
25pub fn push<const N: usize, IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
29 let slice = context.interpreter.bytecode.read_slice(N);
30 if !context.interpreter.stack.push_slice(slice) {
31 return Err(InstructionResult::StackOverflow);
32 }
33
34 context.interpreter.bytecode.relative_jump(N as isize);
35 Ok(())
36}
37
38pub fn dup<const N: usize, IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
42 if !context.interpreter.stack.dup(N) {
43 return Err(InstructionResult::StackOverflow);
44 }
45 Ok(())
46}
47
48pub fn swap<const N: usize, IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
52 assert!(N != 0);
53 if !context.interpreter.stack.exchange(0, N) {
54 return Err(InstructionResult::StackUnderflow);
55 }
56 Ok(())
57}
58
59pub fn dupn<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
63 check!(context.interpreter, AMSTERDAM);
64 let x: usize = context.interpreter.bytecode.read_u8().into();
65 if let Some(n) = decode_single(x) {
66 if !context.interpreter.stack.dup(n) {
67 return Err(InstructionResult::StackOverflow);
68 }
69 context.interpreter.bytecode.relative_jump(1);
70 } else {
71 return Err(InstructionResult::InvalidImmediateEncoding);
72 }
73 Ok(())
74}
75
76pub fn swapn<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
80 check!(context.interpreter, AMSTERDAM);
81 let x: usize = context.interpreter.bytecode.read_u8().into();
82 if let Some(n) = decode_single(x) {
83 if !context.interpreter.stack.exchange(0, n) {
84 return Err(InstructionResult::StackUnderflow);
85 }
86 context.interpreter.bytecode.relative_jump(1);
87 } else {
88 return Err(InstructionResult::InvalidImmediateEncoding);
89 }
90 Ok(())
91}
92
93pub fn exchange<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
97 check!(context.interpreter, AMSTERDAM);
98 let x: usize = context.interpreter.bytecode.read_u8().into();
99 if let Some((n, m)) = decode_pair(x) {
100 if !context.interpreter.stack.exchange(n, m - n) {
101 return Err(InstructionResult::StackUnderflow);
102 }
103 context.interpreter.bytecode.relative_jump(1);
104 } else {
105 return Err(InstructionResult::InvalidImmediateEncoding);
106 }
107 Ok(())
108}
109
110const fn decode_single(x: usize) -> Option<usize> {
111 if x <= 90 || x >= 128 {
112 Some((x + 145) % 256)
113 } else {
114 None
115 }
116}
117
118const fn decode_pair(x: usize) -> Option<(usize, usize)> {
119 if x > 81 && x < 128 {
120 return None;
121 }
122 let k = x ^ 143;
123 let q = k / 16;
124 let r = k % 16;
125 if q < r {
126 Some((q + 1, r + 1))
127 } else {
128 Some((r + 1, 29 - q))
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use crate::{
135 host::DummyHost,
136 instructions::{gas_table, instruction_table},
137 interpreter::{EthInterpreter, ExtBytecode, InputsImpl, SharedMemory},
138 interpreter_types::LoopControl,
139 Interpreter,
140 };
141 use bytecode::opcode::*;
142 use bytecode::Bytecode;
143 use primitives::{hardfork::SpecId, Bytes, U256};
144
145 fn run_bytecode(code: &[u8]) -> Interpreter {
146 let bytecode = Bytecode::new_raw(Bytes::copy_from_slice(code));
147 let mut interpreter = Interpreter::<EthInterpreter>::new(
148 SharedMemory::new(),
149 ExtBytecode::new(bytecode),
150 InputsImpl::default(),
151 false,
152 SpecId::AMSTERDAM,
153 u64::MAX,
154 );
155 let table = instruction_table::<EthInterpreter, DummyHost>();
156 let gas = gas_table();
157 let mut host = DummyHost::new(SpecId::AMSTERDAM);
158 interpreter.run_plain(&table, &gas, &mut host);
159 interpreter
160 }
161
162 #[test]
163 fn test_dupn() {
164 let interpreter = run_bytecode(&[
165 PUSH1, 0x01, PUSH1, 0x00, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1,
166 DUP1, DUP1, DUP1, DUP1, DUP1, DUPN, 0x80,
167 ]);
168 assert_eq!(interpreter.stack.len(), 18);
169 assert_eq!(interpreter.stack.data()[17], U256::from(1));
170 assert_eq!(interpreter.stack.data()[0], U256::from(1));
171 for i in 1..17 {
172 assert_eq!(interpreter.stack.data()[i], U256::ZERO);
173 }
174 }
175
176 #[test]
177 fn test_swapn() {
178 let interpreter = run_bytecode(&[
179 PUSH1, 0x01, PUSH1, 0x00, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1, DUP1,
180 DUP1, DUP1, DUP1, DUP1, DUP1, PUSH1, 0x02, SWAPN, 0x80,
181 ]);
182 assert_eq!(interpreter.stack.len(), 18);
183 assert_eq!(interpreter.stack.data()[17], U256::from(1));
184 assert_eq!(interpreter.stack.data()[0], U256::from(2));
185 for i in 1..17 {
186 assert_eq!(interpreter.stack.data()[i], U256::ZERO);
187 }
188 }
189
190 #[test]
191 fn test_exchange() {
192 let interpreter = run_bytecode(&[PUSH1, 0x00, PUSH1, 0x01, PUSH1, 0x02, EXCHANGE, 0x8E]);
193 assert_eq!(interpreter.stack.len(), 3);
194 assert_eq!(interpreter.stack.data()[2], U256::from(2));
195 assert_eq!(interpreter.stack.data()[1], U256::from(0));
196 assert_eq!(interpreter.stack.data()[0], U256::from(1));
197 }
198
199 #[test]
200 fn test_swapn_invalid_immediate() {
201 let mut interpreter = run_bytecode(&[SWAPN, JUMPDEST]);
202 assert!(interpreter.bytecode.instruction_result().is_none());
203 }
204
205 #[test]
206 fn test_jump_over_invalid_dupn() {
207 let interpreter = run_bytecode(&[PUSH1, 0x04, JUMP, DUPN, JUMPDEST]);
208 assert!(interpreter.bytecode.is_not_end());
209 }
210
211 #[test]
212 fn test_exchange_with_iszero() {
213 let interpreter = run_bytecode(&[
214 PUSH1, 0x00, PUSH1, 0x00, PUSH1, 0x00, EXCHANGE, 0x8E, ISZERO,
215 ]);
216 assert_eq!(interpreter.stack.len(), 3);
217 assert_eq!(interpreter.stack.data()[2], U256::from(1));
218 assert_eq!(interpreter.stack.data()[1], U256::ZERO);
219 assert_eq!(interpreter.stack.data()[0], U256::ZERO);
220 }
221}