revm_interpreter/instructions/
bitwise.rs

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