1use crate::{
2 Call, Int,
3 evm::{Context, Evm, EvmResult, EvmYield, HaltReason},
4 state::State,
5};
6
7#[inline]
8pub fn push(evm: &mut Evm, _: &Context, _: &Call, _: &mut dyn State) -> EvmResult<()> {
9 let op = evm.code[evm.pc];
10 let len = match op {
11 0x60..=0x7F => op as usize - 0x5F, _ => 0, };
14 if len == 0 {
15 evm.gas_charge(2)?;
16 evm.push(Int::ZERO)?;
17 } else {
18 evm.gas_charge(3)?;
19 let lo = evm.pc + 1;
20 let available = len.min(evm.code.len().saturating_sub(lo));
21 let mut buf = [0u8; 32];
22 let dst = 32 - len;
23 buf[dst..dst + available].copy_from_slice(&evm.code[lo..lo + available]);
24 evm.push(Int::from(&buf[..]))?;
25 evm.pc += len;
26 }
27 Ok(())
28}
29
30#[inline]
31pub fn dup(evm: &mut Evm, _: &Context, _: &Call, _: &mut dyn State) -> EvmResult<()> {
32 evm.gas_charge(3)?;
33 let op = evm.code[evm.pc];
34 let n = idx(op) - 1;
35 let Some(int) = evm.stack.iter().rev().nth(n).copied() else {
36 return Err(EvmYield::Halt(HaltReason::StackUnderflow));
37 };
38 evm.push(int)?;
39 Ok(())
40}
41
42pub fn swap(evm: &mut Evm, _: &Context, _: &Call, _: &mut dyn State) -> EvmResult<()> {
43 evm.gas_charge(3)?;
44 let op = evm.code[evm.pc];
45 let n = idx(op); if evm.stack.len() <= n {
47 return Err(EvmYield::Halt(HaltReason::StackUnderflow));
48 }
49 let i = evm.stack.len() - 1;
50 let j = i - n;
51 evm.stack.swap(i, j);
52 Ok(())
53}
54
55fn idx(op: u8) -> usize {
56 match op {
57 0x60..0x80 => op as usize - 0x60 + 1, 0x80..0x90 => op as usize - 0x80 + 1, 0x90..0xA0 => op as usize - 0x90 + 1, _ => 0,
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::super::tests::{call, ctx, state};
67 use super::*;
68 use crate::call::Head;
69 use crate::{
70 Int,
71 evm::{Evm, HaltReason},
72 };
73
74 fn int(val: u64) -> Int {
75 Int::from(val)
76 }
77
78 fn is_halt(result: EvmResult<()>, expected: HaltReason) -> bool {
79 match (result, expected) {
80 (Err(EvmYield::Halt(HaltReason::StackUnderflow)), HaltReason::StackUnderflow) => true,
81 (Err(EvmYield::Halt(HaltReason::BadOpcode(a))), HaltReason::BadOpcode(b)) => a == b,
82 _ => false,
83 }
84 }
85
86 #[test]
89 fn test_push0() {
90 let head = Head::default();
91 let mut evm = Evm::new(head, vec![0x5F], 1000, Int::ONE, Int::ONE, vec![]); push(&mut evm, &ctx(), &call(), &mut state()).unwrap();
93 evm.apply(&mut state());
94 assert_eq!(evm.stack, vec![Int::ZERO]);
95 assert_eq!(evm.pc, 0);
96 }
97
98 #[test]
99 fn test_push1() {
100 let head = Head::default();
101 let mut evm = Evm::new(head, vec![0x60, 0x42], 1000, Int::ONE, Int::ONE, vec![]); push(&mut evm, &ctx(), &call(), &mut state()).unwrap();
103 evm.apply(&mut state());
104 assert_eq!(evm.stack, vec![int(0x42)]);
105 assert_eq!(evm.pc, 1);
106 }
107
108 #[test]
109 fn test_push2() {
110 let head = Head::default();
111 let mut evm = Evm::new(
112 head,
113 vec![0x61, 0x01, 0x02],
114 1000,
115 Int::ONE,
116 Int::ONE,
117 vec![],
118 ); push(&mut evm, &ctx(), &call(), &mut state()).unwrap();
120 evm.apply(&mut state());
121 assert_eq!(evm.stack, vec![int(0x0102)]);
122 assert_eq!(evm.pc, 2);
123 }
124
125 #[test]
126 fn test_push32() {
127 let mut code = vec![0x7F]; code.extend(1u8..=32);
129 let head = Head::default();
130 let mut evm = Evm::new(head, code, 1000, Int::ONE, Int::ONE, vec![]);
131 push(&mut evm, &ctx(), &call(), &mut state()).unwrap();
132 evm.apply(&mut state());
133 assert_eq!(evm.stack.len(), 1);
134 assert_eq!(evm.pc, 32);
135 let expected: Vec<u8> = (1u8..=32).collect();
136 assert_eq!(evm.stack[0], Int::from(expected.as_slice()));
137 }
138
139 #[test]
140 fn test_push_truncated() {
141 let head = Head::default();
142 let mut evm = Evm::new(head, vec![0x61, 0xFF], 1000, Int::ONE, Int::ONE, vec![]);
143 push(&mut evm, &ctx(), &call(), &mut state()).unwrap();
144 evm.apply(&mut state());
145 assert_eq!(evm.stack.len(), 1);
146 assert_eq!(evm.pc, 2);
147 assert_eq!(evm.stack[0], Int::from(0xFF00));
148 }
149
150 #[test]
153 fn test_dup1() {
154 let a = int(1);
155 let head = Head::default();
156 let mut evm = Evm::new(head, vec![0x80], 1000, Int::ONE, Int::ONE, vec![]); evm.stack.push(a);
158 dup(&mut evm, &ctx(), &call(), &mut state()).unwrap();
159 evm.apply(&mut state());
160 assert_eq!(evm.stack, vec![a, a]);
161 assert_eq!(evm.pc, 0);
162 }
163
164 #[test]
165 fn test_dup2() {
166 let (a, b) = (int(1), int(2));
167 let head = Head::default();
168 let mut evm = Evm::new(head, vec![0x81], 1000, Int::ONE, Int::ONE, vec![]); evm.stack.extend([a, b]);
170 dup(&mut evm, &ctx(), &call(), &mut state()).unwrap();
171 evm.apply(&mut state());
172 assert_eq!(evm.stack, vec![a, b, a]); assert_eq!(evm.pc, 0);
174 }
175
176 #[test]
177 fn test_dup16() {
178 let vals: Vec<Int> = (1..=16).map(int).collect();
179 let head = Head::default();
180 let mut evm = Evm::new(head, vec![0x8F], 1000, Int::ONE, Int::ONE, vec![]); evm.stack.extend(vals.iter().copied());
182 dup(&mut evm, &ctx(), &call(), &mut state()).unwrap();
183 evm.apply(&mut state());
184 assert_eq!(evm.stack.len(), 17);
185 assert_eq!(*evm.stack.last().unwrap(), int(1)); }
187
188 #[test]
189 fn test_dup_underflow() {
190 let head = Head::default();
191 let mut evm = Evm::new(head, vec![0x81], 1000, Int::ONE, Int::ONE, vec![]); evm.stack.push(int(1));
193 let result = dup(&mut evm, &ctx(), &call(), &mut state());
194 assert!(is_halt(result, HaltReason::StackUnderflow));
195 }
196
197 #[test]
198 fn test_dup_empty() {
199 let head = Head::default();
200 let mut evm = Evm::new(head, vec![0x80], 1000, Int::ONE, Int::ONE, vec![]); let result = dup(&mut evm, &ctx(), &call(), &mut state());
202 assert!(is_halt(result, HaltReason::StackUnderflow));
203 }
204
205 #[test]
208 fn test_swap1() {
209 let (a, b) = (int(1), int(2));
210 let head = Head::default();
211 let mut evm = Evm::new(head, vec![0x90], 1000, Int::ONE, Int::ONE, vec![]); evm.stack.extend([a, b]);
213 swap(&mut evm, &ctx(), &call(), &mut state()).unwrap();
214 evm.apply(&mut state());
215 assert_eq!(evm.stack, vec![b, a]); assert_eq!(evm.pc, 0);
217 }
218
219 #[test]
220 fn test_swap2() {
221 let (a, b, c) = (int(1), int(2), int(3));
222 let head = Head::default();
223 let mut evm = Evm::new(head, vec![0x91], 1000, Int::ONE, Int::ONE, vec![]); evm.stack.extend([a, b, c]);
225 swap(&mut evm, &ctx(), &call(), &mut state()).unwrap();
226 evm.apply(&mut state());
227 assert_eq!(evm.stack, vec![c, b, a]); assert_eq!(evm.pc, 0);
229 }
230
231 #[test]
232 fn test_swap16() {
233 let vals: Vec<Int> = (1..=17).map(int).collect(); let head = Head::default();
235 let mut evm = Evm::new(head, vec![0x9F], 1000, Int::ONE, Int::ONE, vec![]); evm.stack.extend(vals.iter().copied());
237 swap(&mut evm, &ctx(), &call(), &mut state()).unwrap();
238 evm.apply(&mut state());
239 assert_eq!(*evm.stack.last().unwrap(), int(1)); assert_eq!(evm.stack[0], int(17)); }
242
243 #[test]
244 fn test_swap1_underflow_empty() {
245 let head = Head::default();
246 let mut evm = Evm::new(head, vec![0x90], 1000, Int::ONE, Int::ONE, vec![]); let result = swap(&mut evm, &ctx(), &call(), &mut state());
248 assert!(is_halt(result, HaltReason::StackUnderflow));
249 }
250
251 #[test]
252 fn test_swap1_underflow_one() {
253 let head = Head::default();
254 let mut evm = Evm::new(head, vec![0x90], 1000, Int::ONE, Int::ONE, vec![]); evm.stack.push(int(1));
256 let result = swap(&mut evm, &ctx(), &call(), &mut state());
257 eprintln!("RESULT: {result:?}");
258 assert!(is_halt(result, HaltReason::StackUnderflow));
259 }
260
261 #[test]
262 fn test_swap2_underflow() {
263 let head = Head::default();
264 let mut evm = Evm::new(head, vec![0x91], 1000, Int::ONE, Int::ONE, vec![]); evm.stack.extend([int(1), int(2)]);
266 let result = swap(&mut evm, &ctx(), &call(), &mut state());
267 assert!(is_halt(result, HaltReason::StackUnderflow));
268 }
269}