revm_interpreter/instructions/
bitwise.rs

1use super::i256::i256_cmp;
2use crate::{
3    gas,
4    interpreter::Interpreter,
5    interpreter_types::{InterpreterTypes, LoopControl, RuntimeFlag, StackTr},
6    Host,
7};
8use core::cmp::Ordering;
9use primitives::U256;
10
11pub fn lt<WIRE: InterpreterTypes, H: Host + ?Sized>(
12    interpreter: &mut Interpreter<WIRE>,
13    _host: &mut H,
14) {
15    gas!(interpreter, gas::VERYLOW);
16    popn_top!([op1], op2, interpreter);
17    *op2 = U256::from(op1 < *op2);
18}
19
20pub fn gt<WIRE: InterpreterTypes, H: Host + ?Sized>(
21    interpreter: &mut Interpreter<WIRE>,
22    _host: &mut H,
23) {
24    gas!(interpreter, gas::VERYLOW);
25    popn_top!([op1], op2, interpreter);
26
27    *op2 = U256::from(op1 > *op2);
28}
29
30pub fn slt<WIRE: InterpreterTypes, H: Host + ?Sized>(
31    interpreter: &mut Interpreter<WIRE>,
32    _host: &mut H,
33) {
34    gas!(interpreter, gas::VERYLOW);
35    popn_top!([op1], op2, interpreter);
36
37    *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less);
38}
39
40pub fn sgt<WIRE: InterpreterTypes, H: Host + ?Sized>(
41    interpreter: &mut Interpreter<WIRE>,
42    _host: &mut H,
43) {
44    gas!(interpreter, gas::VERYLOW);
45    popn_top!([op1], op2, interpreter);
46
47    *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater);
48}
49
50pub fn eq<WIRE: InterpreterTypes, H: Host + ?Sized>(
51    interpreter: &mut Interpreter<WIRE>,
52    _host: &mut H,
53) {
54    gas!(interpreter, gas::VERYLOW);
55    popn_top!([op1], op2, interpreter);
56
57    *op2 = U256::from(op1 == *op2);
58}
59
60pub fn iszero<WIRE: InterpreterTypes, H: Host + ?Sized>(
61    interpreter: &mut Interpreter<WIRE>,
62    _host: &mut H,
63) {
64    gas!(interpreter, gas::VERYLOW);
65    popn_top!([], op1, interpreter);
66    *op1 = U256::from(op1.is_zero());
67}
68
69pub fn bitand<WIRE: InterpreterTypes, H: Host + ?Sized>(
70    interpreter: &mut Interpreter<WIRE>,
71    _host: &mut H,
72) {
73    gas!(interpreter, gas::VERYLOW);
74    popn_top!([op1], op2, interpreter);
75    *op2 = op1 & *op2;
76}
77
78pub fn bitor<WIRE: InterpreterTypes, H: Host + ?Sized>(
79    interpreter: &mut Interpreter<WIRE>,
80    _host: &mut H,
81) {
82    gas!(interpreter, gas::VERYLOW);
83    popn_top!([op1], op2, interpreter);
84
85    *op2 = op1 | *op2;
86}
87
88pub fn bitxor<WIRE: InterpreterTypes, H: Host + ?Sized>(
89    interpreter: &mut Interpreter<WIRE>,
90    _host: &mut H,
91) {
92    gas!(interpreter, gas::VERYLOW);
93    popn_top!([op1], op2, interpreter);
94
95    *op2 = op1 ^ *op2;
96}
97
98pub fn not<WIRE: InterpreterTypes, H: Host + ?Sized>(
99    interpreter: &mut Interpreter<WIRE>,
100    _host: &mut H,
101) {
102    gas!(interpreter, gas::VERYLOW);
103    popn_top!([], op1, interpreter);
104
105    *op1 = !*op1;
106}
107
108pub fn byte<WIRE: InterpreterTypes, H: Host + ?Sized>(
109    interpreter: &mut Interpreter<WIRE>,
110    _host: &mut H,
111) {
112    gas!(interpreter, gas::VERYLOW);
113    popn_top!([op1], op2, interpreter);
114
115    let o1 = as_usize_saturated!(op1);
116    *op2 = if o1 < 32 {
117        // `31 - o1` because `byte` returns LE, while we want BE
118        U256::from(op2.byte(31 - o1))
119    } else {
120        U256::ZERO
121    };
122}
123
124/// EIP-145: Bitwise shifting instructions in EVM
125pub fn shl<WIRE: InterpreterTypes, H: Host + ?Sized>(
126    interpreter: &mut Interpreter<WIRE>,
127    _host: &mut H,
128) {
129    check!(interpreter, CONSTANTINOPLE);
130    gas!(interpreter, gas::VERYLOW);
131    popn_top!([op1], op2, interpreter);
132
133    let shift = as_usize_saturated!(op1);
134    *op2 = if shift < 256 {
135        *op2 << shift
136    } else {
137        U256::ZERO
138    }
139}
140
141/// EIP-145: Bitwise shifting instructions in EVM
142pub fn shr<WIRE: InterpreterTypes, H: Host + ?Sized>(
143    interpreter: &mut Interpreter<WIRE>,
144    _host: &mut H,
145) {
146    check!(interpreter, CONSTANTINOPLE);
147    gas!(interpreter, gas::VERYLOW);
148    popn_top!([op1], op2, interpreter);
149
150    let shift = as_usize_saturated!(op1);
151    *op2 = if shift < 256 {
152        *op2 >> shift
153    } else {
154        U256::ZERO
155    }
156}
157
158/// EIP-145: Bitwise shifting instructions in EVM
159pub fn sar<WIRE: InterpreterTypes, H: Host + ?Sized>(
160    interpreter: &mut Interpreter<WIRE>,
161    _host: &mut H,
162) {
163    check!(interpreter, CONSTANTINOPLE);
164    gas!(interpreter, gas::VERYLOW);
165    popn_top!([op1], op2, interpreter);
166
167    let shift = as_usize_saturated!(op1);
168    *op2 = if shift < 256 {
169        op2.arithmetic_shr(shift)
170    } else if op2.bit(255) {
171        U256::MAX
172    } else {
173        U256::ZERO
174    };
175}
176
177#[cfg(test)]
178mod tests {
179    use crate::{
180        host::DummyHost,
181        instructions::bitwise::{byte, sar, shl, shr},
182        interpreter_types::LoopControl,
183        Interpreter,
184    };
185    use primitives::{uint, U256};
186
187    #[test]
188    fn test_shift_left() {
189        let mut host = DummyHost;
190        let mut interpreter = Interpreter::default();
191
192        struct TestCase {
193            value: U256,
194            shift: U256,
195            expected: U256,
196        }
197
198        uint! {
199            let test_cases = [
200                TestCase {
201                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
202                    shift: 0x00_U256,
203                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
204                },
205                TestCase {
206                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
207                    shift: 0x01_U256,
208                    expected: 0x0000000000000000000000000000000000000000000000000000000000000002_U256,
209                },
210                TestCase {
211                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
212                    shift: 0xff_U256,
213                    expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
214                },
215                TestCase {
216                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
217                    shift: 0x0100_U256,
218                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
219                },
220                TestCase {
221                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
222                    shift: 0x0101_U256,
223                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
224                },
225                TestCase {
226                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
227                    shift: 0x00_U256,
228                    expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
229                },
230                TestCase {
231                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
232                    shift: 0x01_U256,
233                    expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
234                },
235                TestCase {
236                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
237                    shift: 0xff_U256,
238                    expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
239                },
240                TestCase {
241                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
242                    shift: 0x0100_U256,
243                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
244                },
245                TestCase {
246                    value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
247                    shift: 0x01_U256,
248                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
249                },
250                TestCase {
251                    value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
252                    shift: 0x01_U256,
253                    expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
254                },
255            ];
256        }
257
258        for test in test_cases {
259            push!(interpreter, test.value);
260            push!(interpreter, test.shift);
261            shl(&mut interpreter, &mut host);
262            let res = interpreter.stack.pop().unwrap();
263            assert_eq!(res, test.expected);
264        }
265    }
266
267    #[test]
268    fn test_logical_shift_right() {
269        let mut host = DummyHost;
270        let mut interpreter = Interpreter::default();
271
272        struct TestCase {
273            value: U256,
274            shift: U256,
275            expected: U256,
276        }
277
278        uint! {
279            let test_cases = [
280                TestCase {
281                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
282                    shift: 0x00_U256,
283                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
284                },
285                TestCase {
286                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
287                    shift: 0x01_U256,
288                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
289                },
290                TestCase {
291                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
292                    shift: 0x01_U256,
293                    expected: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
294                },
295                TestCase {
296                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
297                    shift: 0xff_U256,
298                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
299                },
300                TestCase {
301                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
302                    shift: 0x0100_U256,
303                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
304                },
305                TestCase {
306                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
307                    shift: 0x0101_U256,
308                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
309                },
310                TestCase {
311                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
312                    shift: 0x00_U256,
313                    expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
314                },
315                TestCase {
316                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
317                    shift: 0x01_U256,
318                    expected: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
319                },
320                TestCase {
321                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
322                    shift: 0xff_U256,
323                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
324                },
325                TestCase {
326                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
327                    shift: 0x0100_U256,
328                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
329                },
330                TestCase {
331                    value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
332                    shift: 0x01_U256,
333                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
334                },
335            ];
336        }
337
338        for test in test_cases {
339            push!(interpreter, test.value);
340            push!(interpreter, test.shift);
341            shr(&mut interpreter, &mut host);
342            let res = interpreter.stack.pop().unwrap();
343            assert_eq!(res, test.expected);
344        }
345    }
346
347    #[test]
348    fn test_arithmetic_shift_right() {
349        let mut host = DummyHost;
350        let mut interpreter = Interpreter::default();
351
352        struct TestCase {
353            value: U256,
354            shift: U256,
355            expected: U256,
356        }
357
358        uint! {
359        let test_cases = [
360            TestCase {
361                value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
362                shift: 0x00_U256,
363                expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
364            },
365            TestCase {
366                value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
367                shift: 0x01_U256,
368                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
369            },
370            TestCase {
371                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
372                shift: 0x01_U256,
373                expected: 0xc000000000000000000000000000000000000000000000000000000000000000_U256,
374            },
375            TestCase {
376                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
377                shift: 0xff_U256,
378                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
379            },
380            TestCase {
381                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
382                shift: 0x0100_U256,
383                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
384            },
385            TestCase {
386                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
387                shift: 0x0101_U256,
388                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
389            },
390            TestCase {
391                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
392                shift: 0x00_U256,
393                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
394            },
395            TestCase {
396                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
397                shift: 0x01_U256,
398                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
399            },
400            TestCase {
401                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
402                shift: 0xff_U256,
403                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
404            },
405            TestCase {
406                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
407                shift: 0x0100_U256,
408                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
409            },
410            TestCase {
411                value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
412                shift: 0x01_U256,
413                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
414            },
415            TestCase {
416                value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
417                shift: 0xfe_U256,
418                expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
419            },
420            TestCase {
421                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
422                shift: 0xf8_U256,
423                expected: 0x000000000000000000000000000000000000000000000000000000000000007f_U256,
424            },
425            TestCase {
426                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
427                shift: 0xfe_U256,
428                expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
429            },
430            TestCase {
431                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
432                shift: 0xff_U256,
433                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
434            },
435            TestCase {
436                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
437                shift: 0x0100_U256,
438                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
439            },
440        ];
441            }
442
443        for test in test_cases {
444            push!(interpreter, test.value);
445            push!(interpreter, test.shift);
446            sar(&mut interpreter, &mut host);
447            let res = interpreter.stack.pop().unwrap();
448            assert_eq!(res, test.expected);
449        }
450    }
451
452    #[test]
453    fn test_byte() {
454        struct TestCase {
455            input: U256,
456            index: usize,
457            expected: U256,
458        }
459
460        let mut host = DummyHost;
461        let mut interpreter = Interpreter::default();
462
463        let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128);
464        let test_cases = (0..32)
465            .map(|i| {
466                let byte_pos = 31 - i;
467
468                let shift_amount = U256::from(byte_pos * 8);
469                let byte_value = (input_value >> shift_amount) & U256::from(0xFF);
470                TestCase {
471                    input: input_value,
472                    index: i,
473                    expected: byte_value,
474                }
475            })
476            .collect::<Vec<_>>();
477
478        for test in test_cases.iter() {
479            push!(interpreter, test.input);
480            push!(interpreter, U256::from(test.index));
481            byte(&mut interpreter, &mut host);
482            let res = interpreter.stack.pop().unwrap();
483            assert_eq!(res, test.expected, "Failed at index: {}", test.index);
484        }
485    }
486}