1use yevm_base::{
2 Int,
3 math::{ONE, ZERO, lift},
4};
5use yevm_misc::keccak256;
6
7use crate::evm::{self, Evm, EvmResult, EvmYield};
8use crate::state::State;
9use crate::trace::Event;
10
11pub fn stop(_: &mut Evm) -> EvmResult<()> {
12 Err(EvmYield::Return(vec![]))
13}
14
15#[inline]
16pub fn add(evm: &mut Evm) -> EvmResult<()> {
17 evm.gas_charge(3)?;
18 let [a, b] = evm.peek()?;
19 let f = lift(|[a, b]| a + b);
20 let r = f([a, b]);
21 evm.push(r)?;
22 Ok(())
23}
24
25pub fn mul(evm: &mut Evm) -> EvmResult<()> {
26 evm.gas_charge(5)?;
27 let [a, b] = evm.peek()?;
28 let f = lift(|[a, b]| a * b);
29 let r = f([a, b]);
30 evm.push(r)?;
31 Ok(())
32}
33
34pub fn sub(evm: &mut Evm) -> EvmResult<()> {
35 evm.gas_charge(3)?;
36 let [a, b] = evm.peek()?;
37 let f = lift(|[a, b]| a - b);
38 let r = f([a, b]);
39 evm.push(r)?;
40 Ok(())
41}
42
43pub fn div(evm: &mut Evm) -> EvmResult<()> {
44 evm.gas_charge(5)?;
45 let [a, b] = evm.peek()?;
46 if b.is_zero() {
47 evm.push(Int::ZERO)?;
48 return Ok(());
49 }
50 let f = lift(|[a, b]| a / b);
51 let r = f([a, b]);
52 evm.push(r)?;
53 Ok(())
54}
55
56pub fn sdiv(evm: &mut Evm) -> EvmResult<()> {
57 use yevm_base::math::U256;
58 evm.gas_charge(5)?;
59 let [a, b] = evm.peek()?;
60 if b.is_zero() {
61 evm.push(Int::ZERO)?;
62 return Ok(());
63 }
64 let f = lift(|[a, b]| {
65 let neg = |x: U256| (!x) + U256::ONE;
66 let sign_a = a.bit(255);
67 let sign_b = b.bit(255);
68 let abs_a = if sign_a { neg(a) } else { a };
69 let abs_b = if sign_b { neg(b) } else { b };
70 let result = abs_a / abs_b;
71 if sign_a != sign_b {
72 neg(result)
73 } else {
74 result
75 }
76 });
77 let r = f([a, b]);
78 evm.push(r)?;
79 Ok(())
80}
81
82pub fn r#mod(evm: &mut Evm) -> EvmResult<()> {
83 evm.gas_charge(5)?;
84 let [a, b] = evm.peek()?;
85 if b.is_zero() {
86 evm.push(Int::ZERO)?;
87 return Ok(());
88 }
89 let f = lift(|[a, b]| a % b);
90 let r = f([a, b]);
91 evm.push(r)?;
92 Ok(())
93}
94
95pub fn smod(evm: &mut Evm) -> EvmResult<()> {
96 use yevm_base::math::U256;
97 evm.gas_charge(5)?;
98 let [a, b] = evm.peek()?;
99 let f = lift(|[a, b]| {
100 if b.is_zero() {
101 return U256::ZERO;
102 }
103 let neg = |x: U256| (!x) + U256::ONE;
104 let sign_a = a.bit(255);
105 let abs_a = if sign_a { neg(a) } else { a };
106 let abs_b = if b.bit(255) { neg(b) } else { b };
107 let result = abs_a % abs_b;
108 if sign_a && !result.is_zero() {
109 neg(result)
110 } else {
111 result
112 }
113 });
114 let r = f([a, b]);
115 evm.push(r)?;
116 Ok(())
117}
118
119pub fn addmod(evm: &mut Evm) -> EvmResult<()> {
120 evm.gas_charge(8)?;
121 let [a, b, m] = evm.peek()?;
122 let f = lift(|[a, b, m]| a.add_mod(b, m));
123 let r = f([a, b, m]);
124 evm.push(r)?;
125 Ok(())
126}
127
128pub fn mulmod(evm: &mut Evm) -> EvmResult<()> {
129 evm.gas_charge(8)?;
130 let [a, b, m] = evm.peek()?;
131 let f = lift(|[a, b, m]| a.mul_mod(b, m));
132 let r = f([a, b, m]);
133 evm.push(r)?;
134 Ok(())
135}
136
137pub fn exp(evm: &mut Evm) -> EvmResult<()> {
138 let [a, b] = evm.peek()?;
139 let exp_cost = if b.is_zero() {
141 10
142 } else {
143 use yevm_base::math::U256;
144 let b_u = U256::from_be_slice(b.as_ref());
145 let bit_len = 256 - b_u.leading_zeros();
146 10 + 50 * bit_len.div_ceil(8) as i64
147 };
148 evm.gas_charge(exp_cost)?;
149 let f = lift(|[a, b]| a.pow(b));
150 let r = f([a, b]);
151 evm.push(r)?;
152 Ok(())
153}
154
155pub fn signextend(evm: &mut Evm) -> EvmResult<()> {
156 use yevm_base::math::U256;
157 evm.gas_charge(5)?;
158 let [b, x] = evm.peek()?;
159 let f = lift(|[b, x]| {
160 if b >= U256::from(32u32) {
161 return x;
162 }
163 let b = b.saturating_to::<usize>();
164 let sign_bit = b * 8 + 7;
165 let low_bits = b * 8 + 8; let mask = if low_bits == 256 {
167 U256::MAX
168 } else {
169 (U256::ONE << low_bits) - U256::ONE
170 };
171 if x.bit(sign_bit) { x | !mask } else { x & mask }
172 });
173 let r = f([b, x]);
174 evm.push(r)?;
175 Ok(())
176}
177
178pub fn lt(evm: &mut Evm) -> EvmResult<()> {
179 evm.gas_charge(3)?;
180 let [a, b] = evm.peek()?;
181 let f = lift(|[a, b]| if a < b { ONE } else { ZERO });
182 let r = f([a, b]);
183 evm.push(r)?;
184 Ok(())
185}
186
187pub fn gt(evm: &mut Evm) -> EvmResult<()> {
188 evm.gas_charge(3)?;
189 let [a, b] = evm.peek()?;
190 let f = lift(|[a, b]| if a > b { ONE } else { ZERO });
191 let r = f([a, b]);
192 evm.push(r)?;
193 Ok(())
194}
195
196pub fn slt(evm: &mut Evm) -> EvmResult<()> {
197 evm.gas_charge(3)?;
198 let [a, b] = evm.peek()?;
199 let f = lift(|[a, b]| {
200 let key = |x| x ^ (ONE << 255);
202 if key(a) < key(b) { ONE } else { ZERO }
203 });
204 let r = f([a, b]);
205 evm.push(r)?;
206 Ok(())
207}
208
209pub fn sgt(evm: &mut Evm) -> EvmResult<()> {
210 evm.gas_charge(3)?;
211 let [a, b] = evm.peek()?;
212 let f = lift(|[a, b]| {
213 let key = |x| x ^ (ONE << 255);
214 if key(a) > key(b) { ONE } else { ZERO }
215 });
216 let r = f([a, b]);
217 evm.push(r)?;
218 Ok(())
219}
220
221pub fn eq(evm: &mut Evm) -> EvmResult<()> {
222 evm.gas_charge(3)?;
223 let [a, b] = evm.peek()?;
224 let f = lift(|[a, b]| if a == b { ONE } else { ZERO });
225 let r = f([a, b]);
226 evm.push(r)?;
227 Ok(())
228}
229
230pub fn iszero(evm: &mut Evm) -> EvmResult<()> {
231 evm.gas_charge(3)?;
232 let [x] = evm.peek()?;
233 let f = lift(|[x]| if x.is_zero() { ONE } else { ZERO });
234 let r = f([x]);
235 evm.push(r)?;
236 Ok(())
237}
238
239pub fn and(evm: &mut Evm) -> EvmResult<()> {
240 evm.gas_charge(3)?;
241 let [a, b] = evm.peek()?;
242 let f = lift(|[a, b]| a & b);
243 let r = f([a, b]);
244 evm.push(r)?;
245 Ok(())
246}
247
248pub fn or(evm: &mut Evm) -> EvmResult<()> {
249 evm.gas_charge(3)?;
250 let [a, b] = evm.peek()?;
251 let f = lift(|[a, b]| a | b);
252 let r = f([a, b]);
253 evm.push(r)?;
254 Ok(())
255}
256
257pub fn xor(evm: &mut Evm) -> EvmResult<()> {
258 evm.gas_charge(3)?;
259 let [a, b] = evm.peek()?;
260 let f = lift(|[a, b]| a ^ b);
261 let r = f([a, b]);
262 evm.push(r)?;
263 Ok(())
264}
265
266pub fn not(evm: &mut Evm) -> EvmResult<()> {
267 evm.gas_charge(3)?;
268 let [x] = evm.peek()?;
269 let f = lift(|[x]| !x);
270 let r = f([x]);
271 evm.push(r)?;
272 Ok(())
273}
274
275pub fn byte(evm: &mut Evm) -> EvmResult<()> {
276 evm.gas_charge(3)?;
277 let [idx, int] = evm.peek()?;
278 let byte = int
279 .as_ref()
280 .get(idx.as_usize())
281 .copied()
282 .unwrap_or_default();
283 evm.push(Int::from(byte))?;
284 Ok(())
285}
286
287pub fn shl(evm: &mut Evm) -> EvmResult<()> {
288 evm.gas_charge(3)?;
289 let [shift, val] = evm.peek()?;
290 let f = lift(|[shift, val]| val << shift);
291 let r = f([shift, val]);
292 evm.push(r)?;
293 Ok(())
294}
295
296pub fn shr(evm: &mut Evm) -> EvmResult<()> {
297 evm.gas_charge(3)?;
298 let [shift, val] = evm.peek()?;
299 let f = lift(|[shift, val]| val >> shift);
300 let r = f([shift, val]);
301 evm.push(r)?;
302 Ok(())
303}
304
305pub fn sar(evm: &mut Evm) -> EvmResult<()> {
306 evm.gas_charge(3)?;
307 let [shift, val] = evm.peek()?;
308 let f = lift(|[shift, val]| val.arithmetic_shr(shift.saturating_to::<usize>()));
309 let r = f([shift, val]);
310 evm.push(r)?;
311 Ok(())
312}
313
314pub fn clz(evm: &mut Evm) -> EvmResult<()> {
315 use yevm_base::math::U256;
316 evm.gas_charge(5)?;
317 let [x] = evm.peek()?;
318 let f = lift(|[x]| U256::from(x.leading_zeros()));
319 let r = f([x]);
320 evm.push(r)?;
321 Ok(())
322}
323
324pub fn hash(evm: &mut Evm, state: &mut dyn State) -> EvmResult<()> {
325 evm.gas_charge(30)?;
326 let [offset, size] = evm.peek()?;
327 evm::mem_check_int(offset, size)?;
328 let (offset, size) = (offset.as_usize(), size.as_usize());
329 evm.gas_charge(6 * size.div_ceil(32) as i64)?;
330 let data = evm.mem_get(offset, size)?;
331 let hash = keccak256(&data);
332 let hash_int = Int::from(hash.as_ref());
333 state.emit(Event::Hash(data.into(), hash_int));
334 evm.push(hash_int)?;
335 Ok(())
336}