revm_interpreter/instructions/
bitwise.rs

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