bobcat_maths/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3use core::{
4    cmp::{Eq, Ordering},
5    fmt::{Debug, Display, Error as FmtError, Formatter},
6    ops::{
7        Add, AddAssign, BitAnd, BitOr, BitOrAssign, BitXor, Deref, DerefMut, Div, Index, IndexMut,
8        Mul, MulAssign, Neg, Not, Rem, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
9    },
10    str::FromStr,
11};
12
13use num_traits::{One, Zero};
14
15#[cfg(feature = "borsh")]
16use borsh::{BorshDeserialize, BorshSerialize};
17
18#[cfg(feature = "serde")]
19use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
20
21#[cfg(feature = "proptest-enabled")]
22pub mod strategies;
23
24#[cfg(feature = "alloc")]
25extern crate alloc;
26
27pub type Address = [u8; 20];
28
29#[link(wasm_import_module = "vm_hooks")]
30#[cfg(not(feature = "alloy-enabled"))]
31unsafe extern "C" {
32    fn math_div(x: *mut u8, y: *const u8);
33    fn math_mod(x: *mut u8, y: *const u8);
34    fn math_add_mod(a: *mut u8, b: *const u8, c: *const u8);
35    fn math_mul_mod(a: *mut u8, b: *const u8, c: *const u8);
36}
37
38#[cfg(feature = "ruint-enabled")]
39use alloy_primitives::{ruint, U256};
40
41#[cfg(feature = "alloy-enabled")]
42mod alloy {
43    use core::ptr::copy_nonoverlapping;
44
45    pub(crate) use alloy_primitives::U256;
46
47    #[cfg(test)]
48    pub(crate) use alloy_primitives::I256;
49
50    pub(crate) unsafe fn math_div(out: *mut u8, y: *const u8) {
51        unsafe {
52            let x = U256::from_be_slice(&*(out as *const [u8; 32]));
53            let y = U256::from_be_slice(&*(y as *const [u8; 32]));
54            let z = if y.is_zero() {
55                // TODO: I think the node returns 0 when this is the case.
56                U256::ZERO
57            } else {
58                x / y
59            };
60            copy_nonoverlapping(z.to_be_bytes::<32>().as_ptr(), out, 32);
61        }
62    }
63
64    pub(crate) unsafe fn math_mod(out: *mut u8, y: *const u8) {
65        unsafe {
66            let x = U256::from_be_slice(&*(out as *const [u8; 32]));
67            let y = U256::from_be_slice(&*(y as *const [u8; 32]));
68            let z = x % y;
69            copy_nonoverlapping(z.to_be_bytes::<32>().as_ptr(), out, 32);
70        }
71    }
72
73    pub(crate) unsafe fn math_add_mod(a: *mut u8, b: *const u8, c: *const u8) {
74        unsafe {
75            let x = U256::from_be_slice(&*(a as *const [u8; 32]));
76            let y = U256::from_be_slice(&*(b as *const [u8; 32]));
77            let z = U256::from_be_slice(&*(c as *const [u8; 32]));
78            let x = x.add_mod(y, z);
79            copy_nonoverlapping(x.to_be_bytes::<32>().as_ptr(), a, 32);
80        }
81    }
82
83    pub(crate) unsafe fn math_mul_mod(a: *mut u8, b: *const u8, c: *const u8) {
84        unsafe {
85            let x = U256::from_be_slice(&*(a as *const [u8; 32]));
86            let y = U256::from_be_slice(&*(b as *const [u8; 32]));
87            let z = U256::from_be_slice(&*(c as *const [u8; 32]));
88            let x = x.mul_mod(y, z);
89            copy_nonoverlapping(x.to_be_bytes::<32>().as_ptr(), a, 32);
90        }
91    }
92}
93
94#[cfg(feature = "alloy-enabled")]
95use alloy::*;
96
97#[derive(Copy, Clone, PartialEq, Hash)]
98#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
99#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
100#[cfg_attr(feature = "borsh", derive(BorshDeserialize, BorshSerialize))]
101#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
102#[repr(transparent)]
103pub struct U(pub [u8; 32]);
104
105#[derive(Copy, Clone, PartialEq, Hash, Debug)]
106#[cfg_attr(feature = "proptest", derive(proptest_derive::Arbitrary))]
107#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
108#[cfg_attr(feature = "borsh", derive(BorshDeserialize, BorshSerialize))]
109#[cfg_attr(feature = "serde", derive(SerdeSerialize, SerdeDeserialize))]
110#[repr(transparent)]
111pub struct I(pub [u8; 32]);
112
113pub fn wrapping_div(x: &U, y: &U) -> U {
114    assert!(y.is_some(), "divide by zero");
115    let mut b = *x;
116    unsafe { math_div(b.as_mut_ptr(), y.as_ptr()) }
117    b
118}
119
120fn wrapping_div_quo_rem_b<const C: usize>(x: &[u8; C], denom: &[u8; C]) -> ([u8; C], [u8; C]) {
121    if denom == &[0u8; C] {
122        return ([0u8; C], [0u8; C]);
123    }
124    let mut q = [0u8; C];
125    let mut r = [0u8; C];
126    let mut one = [0u8; C];
127    one[C - 1] = 1;
128    let mut two = [0u8; C];
129    two[C - 1] = 2;
130    let mut i = 0;
131    while i < C * 8 {
132        let bit = (x[i / 8] >> (7 - (i % 8))) & 1;
133        r = wrapping_mul_b::<C>(&r, &two);
134        if bit == 1 {
135            r = wrapping_add_b::<C>(&r, &one);
136        }
137        if r >= *denom {
138            r = wrapping_sub_b::<C>(&r, denom);
139            q[i / 8] |= 1 << (7 - (i % 8));
140        }
141        i += 1;
142    }
143    (q, r)
144}
145
146pub fn const_wrapping_div(x: &U, y: &U) -> U {
147    U(wrapping_div_quo_rem_b::<32>(&x.0, &y.0).0)
148}
149
150#[cfg_attr(test, mutants::skip)]
151pub fn checked_div(x: &U, y: &U) -> Option<U> {
152    if y.is_zero() {
153        None
154    } else {
155        Some(wrapping_div(x, y))
156    }
157}
158
159pub fn modd(x: &U, y: &U) -> U {
160    let mut b = *x;
161    unsafe { math_mod(b.as_mut_ptr(), y.as_ptr()) }
162    b
163}
164
165pub fn mul_mod(mut x: U, y: &U, z: &U) -> U {
166    unsafe { math_mul_mod(x.as_mut_ptr(), y.as_ptr(), z.as_ptr()) }
167    x
168}
169
170const fn wrapping_add_b<const C: usize>(x: &[u8; C], y: &[u8; C]) -> [u8; C] {
171    let mut r = [0u8; C];
172    let mut c = 0;
173    let mut i = C - 1;
174    loop {
175        let s = x[i] as u16 + y[i] as u16 + c;
176        r[i] = s as u8;
177        c = s >> 8;
178        if i == 0 {
179            break;
180        }
181        i -= 1;
182    }
183    r
184}
185
186pub const fn wrapping_add(x: &U, y: &U) -> U {
187    U(wrapping_add_b(&x.0, &y.0))
188}
189
190#[cfg_attr(test, mutants::skip)]
191pub fn checked_add(x: &U, y: &U) -> Option<U> {
192    if x > &(U::MAX - *y) {
193        None
194    } else {
195        let z = x.add_mod(y, &U::MAX);
196        if z.is_zero() && (x.is_some() || y.is_some()) {
197            Some(U::MAX)
198        } else {
199            Some(z)
200        }
201    }
202}
203
204#[cfg_attr(test, mutants::skip)]
205pub fn saturating_add(x: &U, y: &U) -> U {
206    checked_add(x, y).unwrap_or(U::MAX)
207}
208
209const fn wrapping_sub_b<const C: usize>(x: &[u8; C], y: &[u8; C]) -> [u8; C] {
210    let mut neg_y = *y;
211    let mut i = 0;
212    while i < C {
213        neg_y[i] = !neg_y[i];
214        i += 1;
215    }
216    let mut c = 1u16;
217    let mut i = C - 1;
218    loop {
219        let sum = neg_y[i] as u16 + c;
220        neg_y[i] = sum as u8;
221        c = sum >> 8;
222        if i == 0 {
223            break;
224        }
225        i -= 1;
226    }
227    wrapping_add_b(x, &neg_y)
228}
229
230pub const fn wrapping_sub(x: &U, y: &U) -> U {
231    U(wrapping_sub_b::<32>(&x.0, &y.0))
232}
233
234pub fn saturating_sub(x: &U, y: &U) -> U {
235    checked_sub(x, y).unwrap_or(U::ZERO)
236}
237
238#[cfg_attr(test, mutants::skip)]
239pub fn checked_sub(x: &U, y: &U) -> Option<U> {
240    if x < y {
241        None
242    } else {
243        Some(wrapping_sub(x, y))
244    }
245}
246
247pub const fn wrapping_mul_b<const C: usize>(x: &[u8; C], y: &[u8; C]) -> [u8; C] {
248    let mut r = [0u8; C];
249    let mut i = 0;
250    while i < C {
251        let mut c = 0u16;
252        let mut j = 0;
253        while j < C {
254            let i_r = i + j;
255            if i_r >= C {
256                break;
257            }
258            let r_idx = C - 1 - i_r;
259            let xi = x[C - 1 - i] as u16;
260            let yj = y[C - 1 - j] as u16;
261            let prod = xi * yj + r[r_idx] as u16 + c;
262            r[r_idx] = prod as u8;
263            c = prod >> 8;
264            j += 1;
265        }
266        if i + j < C {
267            let idx = 31 - (i + j);
268            r[idx] = r[idx] + c as u8;
269        }
270        i += 1;
271    }
272    r
273}
274
275pub const fn wrapping_mul(x: &U, y: &U) -> U {
276    U(wrapping_mul_b(&x.0, &y.0))
277}
278
279#[cfg_attr(test, mutants::skip)]
280pub fn checked_mul(x: &U, y: &U) -> Option<U> {
281    if x.is_zero() || y.is_zero() {
282        return Some(U::ZERO);
283    }
284    if x > &(U::MAX / *y) {
285        None
286    } else {
287        let z = x.mul_mod(y, &U::MAX);
288        if z.is_zero() {
289            Some(U::MAX)
290        } else {
291            Some(z)
292        }
293    }
294}
295
296pub fn saturating_mul(x: &U, y: &U) -> U {
297    checked_mul(x, y).unwrap_or(U::MAX)
298}
299
300pub fn saturating_div(x: &U, y: &U) -> U {
301    checked_div(x, y).unwrap_or(U::MAX)
302}
303
304fn gcd(mut x: U, mut y: U) -> U {
305    while y.is_some() {
306        (x, y) = (y, x % y);
307    }
308    x
309}
310
311pub fn gcd_mul_div(x: &U, y: &U, denom: U) -> Option<(U, bool)> {
312    if denom.is_zero() {
313        return None;
314    }
315    let g1 = gcd(*x, denom);
316    let x_reduced = x / &g1;
317    let denom_reduced = denom / g1;
318    let g2 = gcd(*y, denom_reduced);
319    let y_reduced = y / &g2;
320    let denom_final = denom_reduced / g2;
321    let product = x_reduced.checked_mul(&y_reduced)?;
322    let result = (x_reduced * y_reduced) / denom_final;
323    let remainder = product % denom_final;
324    Some((result, remainder.is_some()))
325}
326
327pub fn gcd_mul_div_round_up(x: &U, y: &U, denom: U) -> Option<U> {
328    let (x, y) = gcd_mul_div(x, y, denom)?;
329    if x.is_max() && y {
330        return None;
331    }
332    Some(if y { x + U::ONE } else { x })
333}
334
335pub fn widening_mul(x: &U, y: &U) -> [u8; 64] {
336    let shift_128 = &U([
337        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
338        0, 0,
339    ]);
340    let x_hi = x / shift_128;
341    let x_lo = x % shift_128;
342    let y_hi = y / shift_128;
343    let y_lo = y % shift_128;
344    let t0 = x_lo.mul_mod(&y_lo, &U::MAX);
345    let t1 = x_hi.mul_mod(&y_lo, &U::MAX);
346    let t2 = x_lo.mul_mod(&y_hi, &U::MAX);
347    let t3 = x_hi.mul_mod(&y_hi, &U::MAX);
348    let t0_hi = &t0 / shift_128;
349    let t0_lo = &t0 % shift_128;
350    let t1_hi = &t1 / shift_128;
351    let t1_lo = &t1 % shift_128;
352    let t2_hi = &t2 / shift_128;
353    let t2_lo = &t2 % shift_128;
354    let mid = (t0_hi + t1_lo) + t2_lo;
355    let mid_hi = &mid / shift_128;
356    let mid_lo = &mid % shift_128;
357    let mid_lo_shifted = mid_lo.mul_mod(shift_128, &U::MAX);
358    let out_low = t0_lo + mid_lo_shifted;
359    let out_high = t3 + t1_hi + t2_hi + mid_hi;
360    let mut o = [0u8; 64];
361    o[..32].copy_from_slice(&out_high.0);
362    o[32..].copy_from_slice(&out_low.0);
363    o
364}
365
366/// Widening then truncate mul div that's cheaper in codesize that's safe for cold
367/// operations. The most expensive in gas costs.
368pub fn widening_mul_div(x: &U, y: &U, denom: U) -> Option<(U, bool)> {
369    if denom.is_zero() {
370        return None;
371    }
372    if x.is_zero() {
373        return Some((U::ZERO, false));
374    }
375    // We use a boring method if the overflow wouldn't happen:
376    if wrapping_div(&U::MAX, x) >= *y {
377        let l = wrapping_mul(x, y);
378        let carry = x.mul_mod(y, &denom).is_some();
379        return Some((wrapping_div(&l, &denom), carry));
380    }
381    let x = widening_mul(x, y);
382    let mut d = [0u8; 64];
383    d[32..].copy_from_slice(&denom.0);
384    let (q, rem) = wrapping_div_quo_rem_b::<64>(&x, &d);
385    if q[..32] != [0u8; 32] {
386        return None;
387    }
388    let l: [u8; 32] = q[32..].try_into().unwrap();
389    let l = U::from(l);
390    let has_carry = rem[32..] != [0u8; 32];
391    Some((l, has_carry))
392}
393
394pub fn widening_mul_div_round_up(x: &U, y: &U, denom: U) -> Option<U> {
395    let (x, y) = widening_mul_div(x, y, denom)?;
396    if x.is_max() && y {
397        return None;
398    }
399    Some(if y { x + U::ONE } else { x })
400}
401
402/// Muldiv that's used in practice by Uniswap and other on-chain dapps.
403/// Middling in gas costs.
404pub fn mul_div(x: &U, y: &U, mut denom: U) -> Option<(U, bool)> {
405    // Implemented from https://xn--2-umb.com/21/muldiv/
406    if denom.is_zero() {
407        return None;
408    }
409    if x.is_zero() {
410        return Some((U::ZERO, false));
411    }
412    let mut prod0 = wrapping_mul(x, y);
413    let mm = mul_mod(*x, y, &U::MAX);
414    let mut prod1 = wrapping_sub(
415        &wrapping_sub(&mm, &prod0),
416        &if prod0 > mm { U::ONE } else { U::ZERO },
417    );
418    if prod1.is_zero() {
419        let carry = mul_mod(*x, y, &denom).is_some();
420        return Some((wrapping_div(&prod0, &denom), carry));
421    }
422    if prod1 >= denom {
423        return None;
424    }
425    let remainder = mul_mod(*x, y, &denom);
426    let carry = remainder.is_some();
427    if remainder > prod0 {
428        prod1 -= U::ONE;
429    }
430    prod0 = wrapping_sub(&prod0, &remainder);
431    let mut twos = wrapping_sub(&U::ZERO, &denom) & denom;
432    denom = wrapping_div(&denom, &twos);
433    prod0 = wrapping_div(&prod0, &twos);
434    twos = wrapping_add(
435        &wrapping_div(&wrapping_sub(&U::ZERO, &twos), &twos),
436        &U::ONE,
437    );
438    prod0 = prod0 | wrapping_mul(&prod1, &twos);
439    let mut inv = wrapping_mul(&U::from(3u32), &denom) ^ U::from(2u32);
440    for _ in 0..6 {
441        inv = wrapping_mul(
442            &inv,
443            &wrapping_sub(&U::from(2u32), &wrapping_mul(&denom, &inv)),
444        );
445    }
446    Some((wrapping_mul(&prod0, &inv), carry))
447}
448
449pub fn mul_div_round_up(x: &U, y: &U, denom_and_rem: U) -> Option<U> {
450    let (x, y) = mul_div(x, y, denom_and_rem)?;
451    if x.is_max() && y {
452        return None;
453    }
454    Some(if y { x + U::ONE } else { x })
455}
456
457/// The cheapest muldiv operation, but the most expensive in codesize muldiv.
458#[cfg(feature = "ruint-enabled")]
459pub fn ruint_mul_div(x: &U, y: &U, denom: U) -> Option<(U, bool)> {
460    if denom.is_zero() {
461        return None;
462    }
463    let x = U256::from_be_slice(x.as_slice());
464    let y = U256::from_be_slice(y.as_slice());
465    let mut denom = U256::from_be_slice(denom.as_slice());
466    let mut mul_and_quo = x.widening_mul::<256, 4, 512, 8>(y);
467    unsafe {
468        ruint::algorithms::div(mul_and_quo.as_limbs_mut(), denom.as_limbs_mut());
469    }
470    let limbs = mul_and_quo.into_limbs();
471    if limbs[4..] != [0_u64; 4] {
472        return None;
473    }
474    let has_carry = !denom.is_zero();
475    let r = U(U256::from_limbs_slice(&limbs[0..4]).to_be_bytes::<32>());
476    Some((r, has_carry))
477}
478
479#[cfg(feature = "ruint-enabled")]
480pub fn ruint_mul_div_round_up(x: &U, y: &U, denom: U) -> Option<U> {
481    let (x, y) = ruint_mul_div(x, y, denom)?;
482    if x.is_max() && y {
483        return None;
484    }
485    Some(if y { x + U::ONE } else { x })
486}
487
488/// Rooti iterative method based on the 9lives implementation. Using this
489/// operation is the equivalent of pow(x, 1/n).
490pub fn checked_rooti(x: U, n: u32) -> Option<U> {
491    if n == 0 {
492        return None;
493    }
494    if x.is_zero() {
495        return Some(U::ZERO);
496    }
497    if n == 1 {
498        return Some(x);
499    }
500    // Due to the nature of this iterative method, we hardcode some
501    // values to have consistency with the 9lives reference.
502    if x == U::from(4u32) && n == 2 {
503        return Some(U::from(2u32));
504    }
505    let n_u256 = U::from(n);
506    let n_1 = n_u256 - U::ONE;
507    // Initial guess: 2^ceil(bits(x)/n)
508    let mut b = 0;
509    let mut t = x;
510    while t.is_some() {
511        b += 1;
512        t >>= 1;
513    }
514    let shift = (b + n as usize - 1) / n as usize;
515    let mut z = U::ONE << shift;
516    let mut y = x;
517    // Newton's method:
518    while z < y {
519        y = z;
520        let p = z.checked_pow(&n_1)?;
521        z = ((x / p) + (z * n_1)) / n_u256;
522    }
523    // Correct overshoot:
524    if y.checked_pow(&n_u256)? > x {
525        y -= U::ONE;
526    }
527    Some(y)
528}
529
530pub fn wrapping_pow(x: &U, exp: &U) -> U {
531    let mut r = U::ONE;
532    let mut i = U::ZERO;
533    while &i < exp {
534        r = wrapping_mul(&r, x);
535        i += U::ONE;
536    }
537    r
538}
539
540pub fn checked_pow(x: &U, exp: &U) -> Option<U> {
541    let mut r = U::ONE;
542    let mut i = U::ZERO;
543    while &i < exp {
544        r = checked_mul(&r, x)?;
545        i += U::ONE;
546    }
547    Some(r)
548}
549
550impl Add for U {
551    type Output = U;
552
553    fn add(self, rhs: U) -> U {
554        cfg_if::cfg_if! {
555            if #[cfg(debug_assertions)] {
556                checked_add(&self, &rhs).expect("overflow when add")
557            } else {
558                wrapping_add(&self, &rhs)
559            }
560        }
561    }
562}
563
564impl Add for &U {
565    type Output = U;
566
567    fn add(self, rhs: &U) -> U {
568        cfg_if::cfg_if! {
569            if #[cfg(debug_assertions)] {
570                checked_add(self, rhs).expect("overflow when add")
571            } else {
572                wrapping_add(self, rhs)
573            }
574        }
575    }
576}
577
578impl AddAssign for U {
579    fn add_assign(&mut self, o: Self) {
580        *self = *self + o;
581    }
582}
583
584impl Sub for U {
585    type Output = U;
586
587    fn sub(self, rhs: U) -> U {
588        cfg_if::cfg_if! {
589            if #[cfg(debug_assertions)] {
590                checked_sub(&self, &rhs).expect("overflow when sub")
591            } else {
592                wrapping_sub(&self, &rhs)
593            }
594        }
595    }
596}
597
598impl Sub for &U {
599    type Output = U;
600
601    fn sub(self, rhs: &U) -> U {
602        cfg_if::cfg_if! {
603            if #[cfg(debug_assertions)] {
604                checked_sub(self, rhs).expect("overflow when sub")
605            } else {
606                wrapping_sub(self, rhs)
607            }
608        }
609    }
610}
611
612impl SubAssign for U {
613    fn sub_assign(&mut self, o: Self) {
614        *self = *self - o;
615    }
616}
617
618impl Mul for U {
619    type Output = U;
620
621    fn mul(self, rhs: U) -> U {
622        cfg_if::cfg_if! {
623            if #[cfg(debug_assertions)] {
624                checked_mul(&self, &rhs).expect("overflow when mul")
625            } else {
626                wrapping_mul(&self, &rhs)
627            }
628        }
629    }
630}
631
632impl Mul for &U {
633    type Output = U;
634
635    fn mul(self, rhs: &U) -> U {
636        cfg_if::cfg_if! {
637            if #[cfg(debug_assertions)] {
638                checked_mul(self, rhs).expect("overflow when mul")
639            } else {
640                wrapping_mul(self, rhs)
641            }
642        }
643    }
644}
645
646impl MulAssign for U {
647    fn mul_assign(&mut self, rhs: Self) {
648        *self = *self * rhs
649    }
650}
651
652impl Div for U {
653    type Output = U;
654
655    fn div(self, rhs: U) -> U {
656        cfg_if::cfg_if! {
657            if #[cfg(debug_assertions)] {
658                checked_div(&self, &rhs).expect("overflow when div")
659            } else {
660                wrapping_div(&self, &rhs)
661            }
662        }
663    }
664}
665
666impl Div for &U {
667    type Output = U;
668
669    fn div(self, rhs: &U) -> U {
670        cfg_if::cfg_if! {
671            if #[cfg(debug_assertions)] {
672                checked_div(self, rhs).expect("overflow when div")
673            } else {
674                wrapping_div(self, rhs)
675            }
676        }
677    }
678}
679
680impl Rem for U {
681    type Output = U;
682
683    fn rem(self, rhs: U) -> U {
684        modd(&self, &rhs)
685    }
686}
687
688impl Rem for &U {
689    type Output = U;
690
691    fn rem(self, rhs: &U) -> U {
692        modd(self, rhs)
693    }
694}
695
696impl Shl<usize> for U {
697    type Output = Self;
698
699    fn shl(self, shift: usize) -> Self::Output {
700        if shift >= 256 {
701            return U::ZERO;
702        }
703        let mut result = [0u8; 32];
704        let byte_shift = shift / 8;
705        let bit_shift = shift % 8;
706        if bit_shift == 0 {
707            for i in 0..(32 - byte_shift) {
708                result[i] = self.0[i + byte_shift];
709            }
710        } else {
711            let mut carry = 0u8;
712            for i in (byte_shift..32).rev() {
713                let src_idx = i;
714                let dst_idx = i - byte_shift;
715                let byte = self.0[src_idx];
716                result[dst_idx] = (byte << bit_shift) | carry;
717                carry = byte >> (8 - bit_shift);
718            }
719        }
720        U(result)
721    }
722}
723
724impl ShlAssign<usize> for U {
725    fn shl_assign(&mut self, rhs: usize) {
726        *self = *self << rhs
727    }
728}
729
730impl BitAnd for U {
731    type Output = Self;
732
733    fn bitand(self, rhs: Self) -> Self::Output {
734        let mut r = U::ZERO;
735        for i in 0..32 {
736            r[i] = self[i] & rhs[i];
737        }
738        r
739    }
740}
741
742impl BitOr for U {
743    type Output = Self;
744
745    fn bitor(self, rhs: Self) -> Self::Output {
746        let mut r = U::ZERO;
747        for i in 0..32 {
748            r[i] = self[i] | rhs[i];
749        }
750        r
751    }
752}
753
754impl BitXor for U {
755    type Output = Self;
756    fn bitxor(self, rhs: Self) -> Self::Output {
757        let mut r = U::ZERO;
758        for i in 0..32 {
759            r[i] = self[i] ^ rhs[i];
760        }
761        r
762    }
763}
764
765impl BitOrAssign for U {
766    fn bitor_assign(&mut self, rhs: Self) {
767        *self = *self | rhs
768    }
769}
770
771impl Shr<usize> for U {
772    type Output = Self;
773
774    fn shr(self, shift: usize) -> Self::Output {
775        if shift >= 256 {
776            return U::ZERO;
777        }
778        let mut result = U::ZERO;
779        let byte_shift = shift / 8;
780        let bit_shift = shift % 8;
781        if bit_shift == 0 {
782            for i in byte_shift..32 {
783                result[i] = self.0[i - byte_shift];
784            }
785        } else {
786            let mut carry = 0u8;
787            for i in 0..(32 - byte_shift) {
788                let src_idx = i;
789                let dst_idx = i + byte_shift;
790                let byte = self.0[src_idx];
791                result[dst_idx] = (byte >> bit_shift) | carry;
792                carry = byte << (8 - bit_shift);
793            }
794        }
795        result
796    }
797}
798
799impl ShrAssign<usize> for U {
800    fn shr_assign(&mut self, rhs: usize) {
801        *self = *self >> rhs
802    }
803}
804
805impl Eq for U {}
806
807impl PartialOrd for U {
808    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
809        Some(self.cmp(other))
810    }
811}
812
813impl Ord for U {
814    fn cmp(&self, other: &Self) -> Ordering {
815        self.0.cmp(&other.0)
816    }
817}
818
819impl Debug for U {
820    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
821        let mut b = [0u8; 32 * 2];
822        let Ok(s) = const_hex::encode_to_str(self.0, &mut b) else {
823            return Err(FmtError);
824        };
825        write!(f, "{s}")
826    }
827}
828
829impl Not for U {
830    type Output = Self;
831
832    fn not(mut self) -> Self::Output {
833        for i in 0..32 {
834            self[i] = !self[i]
835        }
836        self
837    }
838}
839
840impl Neg for U {
841    type Output = Self;
842
843    fn neg(self) -> Self {
844        let mut r = U::ZERO;
845        let mut carry = 1u16;
846        for i in (0..32).rev() {
847            let inverted = !self.0[i] as u16;
848            let sum = inverted + carry;
849            r[i] = sum as u8;
850            carry = sum >> 8;
851        }
852        r
853    }
854}
855
856#[derive(Debug, Clone, PartialEq)]
857pub enum UFromStrErr {
858    InvalidChar(char),
859    Overflow,
860    Empty,
861}
862
863impl FromStr for U {
864    type Err = UFromStrErr;
865
866    fn from_str(s: &str) -> Result<Self, Self::Err> {
867        if s.is_empty() {
868            return Err(UFromStrErr::Empty);
869        }
870        let mut r = U::ZERO;
871        for c in s.chars() {
872            r *= U::from_u32(10);
873            r += match c {
874                '0'..='9' => U::from(c as u8 - b'0'),
875                _ => return Err(UFromStrErr::InvalidChar(c)),
876            };
877        }
878        Ok(r)
879    }
880}
881
882impl U {
883    pub const ZERO: Self = U([0u8; 32]);
884
885    pub const MAX: Self = U([u8::MAX; 32]);
886
887    pub const ONE: Self = U([
888        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
889        0, 1,
890    ]);
891
892    pub fn is_true(&self) -> bool {
893        self.0[31] == 1
894    }
895
896    pub const fn is_zero(&self) -> bool {
897        let mut i = 0;
898        while i < 32 {
899            if self.0[i] != 0 {
900                return false;
901            }
902            i += 1;
903        }
904        true
905    }
906
907    pub fn abs_diff(&self, y: &U) -> U {
908        if self > y {
909            self - y
910        } else {
911            y - self
912        }
913    }
914
915    pub const fn is_max(&self) -> bool {
916        let mut i = 0;
917        while i < 32 {
918            if self.0[i] != u8::MAX {
919                return false;
920            }
921            i += 1;
922        }
923        true
924    }
925
926    pub fn is_some(&self) -> bool {
927        !self.is_zero()
928    }
929
930    pub fn trailing_zeros(&self) -> usize {
931        let mut count = 0;
932        for i in (0..32).rev() {
933            if self[i] == 0 {
934                count += 8;
935            } else {
936                count += self[i].trailing_zeros() as usize;
937                break;
938            }
939        }
940        count
941    }
942
943    pub fn as_slice(&self) -> &[u8; 32] {
944        &self.0
945    }
946
947    #[cfg(feature = "alloc")]
948    pub fn as_vec(self) -> alloc::vec::Vec<u8> {
949        self.0.to_vec()
950    }
951
952    pub fn checked_add(&self, y: &Self) -> Option<Self> {
953        checked_add(self, y)
954    }
955
956    pub fn checked_mul(&self, y: &Self) -> Option<Self> {
957        checked_mul(self, y)
958    }
959
960    pub fn checked_sub(&self, y: &Self) -> Option<Self> {
961        checked_sub(self, y)
962    }
963
964    pub fn checked_div(&self, y: &Self) -> Option<Self> {
965        checked_div(self, y)
966    }
967
968    pub fn checked_pow(&self, exp: &U) -> Option<Self> {
969        checked_pow(self, exp)
970    }
971
972    pub fn wrapping_add(&self, y: &Self) -> U {
973        wrapping_add(self, y)
974    }
975
976    pub fn wrapping_sub(&self, y: &Self) -> U {
977        wrapping_sub(self, y)
978    }
979
980    pub fn wrapping_mul(&self, y: &Self) -> U {
981        wrapping_mul(self, y)
982    }
983
984    pub fn wrapping_div(&self, y: &Self) -> U {
985        wrapping_div(self, y)
986    }
987
988    pub fn saturating_add(&self, y: &Self) -> U {
989        saturating_add(self, y)
990    }
991
992    pub fn saturating_sub(&self, y: &Self) -> U {
993        saturating_sub(self, y)
994    }
995
996    pub fn saturating_mul(&self, y: &Self) -> U {
997        saturating_mul(self, y)
998    }
999
1000    pub fn saturating_div(&self, y: &Self) -> Self {
1001        saturating_div(self, y)
1002    }
1003
1004    pub fn wrapping_neg(self) -> Self {
1005        let mut x = self;
1006        let mut carry = 1u8;
1007        for b in x.iter_mut().rev() {
1008            *b = (!*b).wrapping_add(carry);
1009            carry = b.is_zero() as u8;
1010        }
1011        x
1012    }
1013
1014    pub fn mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1015        mul_div(self, y, z)
1016    }
1017
1018    pub fn mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1019        mul_div_round_up(self, y, z)
1020    }
1021
1022    pub fn widening_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1023        widening_mul_div(self, y, z)
1024    }
1025
1026    pub fn widening_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1027        widening_mul_div_round_up(self, y, z)
1028    }
1029
1030    #[cfg(feature = "ruint-enabled")]
1031    pub fn ruint_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1032        ruint_mul_div(self, y, z)
1033    }
1034
1035    #[cfg(feature = "ruint-enabled")]
1036    pub fn ruint_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1037        ruint_mul_div_round_up(self, y, z)
1038    }
1039
1040    pub fn gcd_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1041        gcd_mul_div(self, y, z)
1042    }
1043
1044    pub fn gcd_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1045        gcd_mul_div_round_up(self, y, z)
1046    }
1047
1048    pub fn mul_mod(&self, y: &Self, z: &Self) -> Self {
1049        mul_mod(*self, y, z)
1050    }
1051
1052    pub fn add_mod(&self, y: &Self, z: &Self) -> Self {
1053        let mut b = self.0;
1054        unsafe { math_add_mod(b.as_mut_ptr(), y.as_ptr(), z.as_ptr()) }
1055        Self(b)
1056    }
1057
1058    pub fn checked_rooti(self, x: u32) -> Option<Self> {
1059        checked_rooti(self, x)
1060    }
1061
1062    pub fn from_hex(x: &str) -> Option<U> {
1063        let mut out = U::ZERO;
1064        match const_hex::decode_to_slice(x, &mut out.0) {
1065            Ok(_) => (),
1066            Err(_) => return None,
1067        }
1068        Some(out)
1069    }
1070}
1071
1072impl Display for U {
1073    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1074        if self.is_zero() {
1075            return write!(f, "0");
1076        }
1077        let mut result = [0u8; 78];
1078        let mut i = 0;
1079        for byte in self.0 {
1080            let mut carry = byte as u32;
1081            for digit in result[..i].iter_mut() {
1082                let temp = (*digit as u32) * 256 + carry;
1083                *digit = (temp % 10) as u8;
1084                carry = temp / 10;
1085            }
1086            while carry > 0 {
1087                result[i] = (carry % 10) as u8;
1088                i += 1;
1089                debug_assert!(78 >= i, "{} > {i}", result.len());
1090                carry /= 10;
1091            }
1092        }
1093        for &digit in result[..i].iter().rev() {
1094            write!(f, "{}", digit)?;
1095        }
1096        Ok(())
1097    }
1098}
1099
1100impl From<U> for [u8; 32] {
1101    fn from(x: U) -> Self {
1102        x.0
1103    }
1104}
1105
1106impl From<&U> for U {
1107    fn from(x: &U) -> Self {
1108        *x
1109    }
1110}
1111
1112impl From<U> for bool {
1113    fn from(x: U) -> Self {
1114        x.0[31] == 1
1115    }
1116}
1117
1118impl From<&[u8; 32]> for &U {
1119    fn from(x: &[u8; 32]) -> Self {
1120        unsafe { &*(x as *const [u8; 32] as *const U) }
1121    }
1122}
1123
1124impl From<[u8; 32]> for U {
1125    fn from(x: [u8; 32]) -> Self {
1126        U(x)
1127    }
1128}
1129
1130impl Deref for U {
1131    type Target = [u8; 32];
1132
1133    fn deref(&self) -> &Self::Target {
1134        &self.0
1135    }
1136}
1137
1138impl DerefMut for U {
1139    fn deref_mut(&mut self) -> &mut Self::Target {
1140        &mut self.0
1141    }
1142}
1143
1144impl From<bool> for U {
1145    fn from(x: bool) -> Self {
1146        U::from(&[x as u8])
1147    }
1148}
1149
1150impl Zero for U {
1151    fn zero() -> Self {
1152        U::ZERO
1153    }
1154
1155    fn is_zero(&self) -> bool {
1156        self.0.iter().all(|&b| b == 0)
1157    }
1158}
1159
1160impl Default for U {
1161    fn default() -> Self {
1162        U::ZERO
1163    }
1164}
1165
1166impl One for U {
1167    fn one() -> Self {
1168        U::ONE
1169    }
1170}
1171
1172impl Index<usize> for U {
1173    type Output = u8;
1174
1175    fn index(&self, index: usize) -> &Self::Output {
1176        &self.0[index]
1177    }
1178}
1179
1180impl IndexMut<usize> for U {
1181    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1182        &mut self.0[index]
1183    }
1184}
1185
1186impl I {
1187    fn is_neg(&self) -> bool {
1188        self.0[0] & 0x80 != 0
1189    }
1190
1191    pub fn is_zero(&self) -> bool {
1192        *self == Self::ZERO
1193    }
1194
1195    pub fn is_some(&self) -> bool {
1196        !self.is_zero()
1197    }
1198
1199    pub fn as_slice(&self) -> &[u8; 32] {
1200        &self.0
1201    }
1202
1203    fn neg(&self) -> Self {
1204        let x = wrapping_add(&U(self.0.map(|b| !b)), &U::ONE);
1205        I(x.0)
1206    }
1207
1208    fn abs(self) -> U {
1209        if self.is_neg() {
1210            U(self.neg().0)
1211        } else {
1212            U(self.0)
1213        }
1214    }
1215}
1216
1217macro_rules! from_slices {
1218    ($($n:expr),+ $(,)?) => {
1219        $(
1220            impl From<&[u8; $n]> for U {
1221                fn from(x: &[u8; $n]) -> Self {
1222                    let mut b = [0u8; 32];
1223                    b[32 - $n..].copy_from_slice(x);
1224                    U(b)
1225                }
1226            }
1227
1228            impl From<[u8; $n]> for U {
1229                fn from(x: [u8; $n]) -> Self {
1230                    U::from(&x)
1231                }
1232            }
1233
1234            impl From<U> for [u8; $n] {
1235                fn from(x: U) -> Self {
1236                    unsafe { *(x.as_ptr().add(32 - $n) as *const [u8; $n]) }
1237                }
1238            }
1239        )+
1240    };
1241}
1242
1243from_slices!(
1244    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
1245    27, 28, 29, 30, 31
1246);
1247
1248impl From<&U> for Address {
1249    fn from(x: &U) -> Self {
1250        (*x).into()
1251    }
1252}
1253
1254macro_rules! from_ints {
1255    ($($t:ty),+ $(,)?) => {
1256        $(
1257            paste::paste! {
1258                impl U {
1259                    pub const fn [<from_ $t>](x: $t) -> U {
1260                        U(array_concat::concat_arrays!(
1261                            [0u8; 32-core::mem::size_of::<$t>()],
1262                            x.to_be_bytes())
1263                        )
1264                    }
1265                }
1266
1267                impl From<$t> for U {
1268                    fn from(x: $t) -> Self {
1269                        U::[<from_ $t>](x)
1270                    }
1271                }
1272
1273                impl From<U> for $t {
1274                    fn from(x: U) -> Self {
1275                        Self::from_be_bytes(x.into())
1276                    }
1277                }
1278            }
1279        )+
1280    };
1281}
1282
1283#[macro_export]
1284macro_rules! u {
1285    ($e:expr) => {
1286        $crate::U::from_u32($e)
1287    };
1288}
1289
1290from_ints! { u8, u16, u32, u64, u128, usize }
1291
1292impl From<I> for [u8; 32] {
1293    fn from(x: I) -> Self {
1294        x.0
1295    }
1296}
1297
1298impl From<[u8; 32]> for I {
1299    fn from(x: [u8; 32]) -> Self {
1300        I(x)
1301    }
1302}
1303
1304fn i_add(x: &I, y: &I) -> I {
1305    I(wrapping_add(&U(x.0), &U(y.0)).0)
1306}
1307
1308fn i_sub(x: &I, y: &I) -> I {
1309    I(wrapping_sub(&U(x.0), &U(y.0)).0)
1310}
1311
1312fn i_mul(x: &I, y: &I) -> I {
1313    let result = wrapping_mul(&U(x.0), &U(y.0));
1314    I(result.0)
1315}
1316
1317fn i_div(x: &I, y: &I) -> I {
1318    let r = wrapping_div(&x.abs(), &y.abs());
1319    if x.is_neg() ^ y.is_neg() {
1320        I(r.0).neg()
1321    } else {
1322        I(r.0)
1323    }
1324}
1325
1326fn i_rem(x: &I, y: &I) -> I {
1327    let r = modd(&x.abs(), &y.abs());
1328    if x.is_neg() {
1329        I(r.0).neg()
1330    } else {
1331        I(r.0)
1332    }
1333}
1334
1335impl Add for I {
1336    type Output = I;
1337    fn add(self, rhs: I) -> I {
1338        i_add(&self, &rhs)
1339    }
1340}
1341
1342impl Add for &I {
1343    type Output = I;
1344    fn add(self, rhs: &I) -> I {
1345        i_add(self, rhs)
1346    }
1347}
1348
1349impl Sub for I {
1350    type Output = I;
1351    fn sub(self, rhs: I) -> I {
1352        i_sub(&self, &rhs)
1353    }
1354}
1355
1356impl Sub for &I {
1357    type Output = I;
1358    fn sub(self, rhs: &I) -> I {
1359        i_sub(self, rhs)
1360    }
1361}
1362
1363impl Mul for I {
1364    type Output = I;
1365    fn mul(self, rhs: I) -> I {
1366        i_mul(&self, &rhs)
1367    }
1368}
1369
1370impl Mul for &I {
1371    type Output = I;
1372    fn mul(self, rhs: &I) -> I {
1373        i_mul(self, rhs)
1374    }
1375}
1376
1377impl Div for I {
1378    type Output = I;
1379    fn div(self, rhs: I) -> I {
1380        i_div(&self, &rhs)
1381    }
1382}
1383
1384impl Div for &I {
1385    type Output = I;
1386    fn div(self, rhs: &I) -> I {
1387        i_div(self, rhs)
1388    }
1389}
1390
1391impl Rem for I {
1392    type Output = I;
1393    fn rem(self, rhs: I) -> I {
1394        i_rem(&self, &rhs)
1395    }
1396}
1397
1398impl Eq for I {}
1399
1400impl PartialOrd for I {
1401    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1402        Some(self.cmp(other))
1403    }
1404}
1405
1406impl Ord for I {
1407    fn cmp(&self, other: &Self) -> Ordering {
1408        let self_sign = self.0[0] & 0x80;
1409        let other_sign = other.0[0] & 0x80;
1410        match (self_sign, other_sign) {
1411            (0, 0x80) => Ordering::Greater,
1412            (0x80, 0) => Ordering::Less,
1413            _ => self.0.cmp(&other.0),
1414        }
1415    }
1416}
1417
1418impl Rem for &I {
1419    type Output = I;
1420    fn rem(self, rhs: &I) -> I {
1421        i_rem(self, rhs)
1422    }
1423}
1424
1425impl I {
1426    pub const ZERO: Self = I([0u8; 32]);
1427
1428    pub const ONE: Self = I([
1429        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1430        0, 1,
1431    ]);
1432}
1433
1434impl Zero for I {
1435    fn zero() -> Self {
1436        I::ZERO
1437    }
1438    fn is_zero(&self) -> bool {
1439        self.0.iter().all(|&b| b == 0)
1440    }
1441}
1442
1443impl Default for I {
1444    fn default() -> Self {
1445        I::ZERO
1446    }
1447}
1448
1449impl One for I {
1450    fn one() -> Self {
1451        I::ONE
1452    }
1453}
1454
1455#[test]
1456fn test_is_zeroes() {
1457    assert!(U::ZERO.is_zero());
1458    assert!(U::ONE.is_some());
1459    assert!(I::ZERO.is_zero());
1460    assert!(I::ONE.is_some());
1461}
1462
1463#[cfg(all(
1464    test,
1465    feature = "alloy-enabled",
1466    feature = "proptest-enabled",
1467    feature = "std",
1468    not(target_arch = "wasm32")
1469))]
1470mod test {
1471    use proptest::prelude::*;
1472
1473    use super::*;
1474
1475    fn strat_any_u256() -> impl Strategy<Value = U256> {
1476        // Arbitrary seems to be having some issues with U256:
1477        any::<[u8; 32]>().prop_map(U256::from_be_bytes)
1478    }
1479
1480    proptest! {
1481        #[test]
1482        fn wrapping_div_b_zero_denominator_yields_zero(numerator in any::<[u8; 4]>()) {
1483            let zero = [0u8; 4];
1484            prop_assert_eq!(wrapping_div_quo_rem_b::<4>(&numerator, &zero).0, zero);
1485        }
1486
1487        #[test]
1488        fn wrapping_div_b_matches_integer_division(
1489            numerator in any::<[u8; 4]>(),
1490            denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1491        ) {
1492            let numerator_u32 = u32::from_be_bytes(numerator);
1493            let denominator_u32 = u32::from_be_bytes(denominator);
1494            let expected = numerator_u32 / denominator_u32;
1495            prop_assert_eq!(
1496                wrapping_div_quo_rem_b::<4>(&numerator, &denominator).0,
1497                expected.to_be_bytes()
1498            );
1499        }
1500
1501        #[test]
1502        fn wrapping_mod_b_matches_integer_modulo(
1503            numerator in any::<[u8; 4]>(),
1504            denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1505        ) {
1506            let numerator_u32 = u32::from_be_bytes(numerator);
1507            let denominator_u32 = u32::from_be_bytes(denominator);
1508            let expected = numerator_u32 % denominator_u32;
1509            prop_assert_eq!(
1510                wrapping_div_quo_rem_b::<4>(&numerator, &denominator).1,
1511                expected.to_be_bytes()
1512            );
1513        }
1514
1515        #[test]
1516        fn wrapping_add_b_handles_carry(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1517            let lhs_u32 = u32::from_be_bytes(lhs);
1518            let rhs_u32 = u32::from_be_bytes(rhs);
1519            let expected = lhs_u32.wrapping_add(rhs_u32);
1520            prop_assert_eq!(wrapping_add_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1521        }
1522
1523        #[test]
1524        fn wrapping_sub_b_handles_borrow(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1525            let lhs_u32 = u32::from_be_bytes(lhs);
1526            let rhs_u32 = u32::from_be_bytes(rhs);
1527            let expected = lhs_u32.wrapping_sub(rhs_u32);
1528            prop_assert_eq!(wrapping_sub_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1529        }
1530
1531        #[test]
1532        fn wrapping_mul_b_matches_wrapping_arithmetic(lhs in any::<[u8; 32]>(), rhs in any::<[u8; 32]>()) {
1533            let lhs_u = U::from(lhs);
1534            let rhs_u = U::from(rhs);
1535            let expected = lhs_u.wrapping_mul(&rhs_u);
1536            prop_assert_eq!(wrapping_mul_b::<32>(&lhs, &rhs), expected.0);
1537        }
1538
1539        #[test]
1540        fn const_wrapping_div_agrees_with_wrapping_div_b(
1541            numerator in any::<[u8; 32]>(),
1542            denominator in any::<[u8; 32]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 32])
1543        ) {
1544            let numerator_u = U::from(numerator);
1545            let denominator_u = U::from(denominator);
1546            prop_assert_eq!(
1547                const_wrapping_div(&numerator_u, &denominator_u).0,
1548                wrapping_div_quo_rem_b::<32>(&numerator, &denominator).0
1549            );
1550        }
1551
1552        #[test]
1553        fn u_predicates_track_zero_and_true(bytes in any::<[u8; 32]>()) {
1554            let value = U::from(bytes);
1555            let is_zero = bytes.iter().all(|&b| b == 0);
1556            prop_assert_eq!(value.is_zero(), is_zero);
1557            prop_assert_eq!(value.is_some(), !is_zero);
1558            prop_assert_eq!(value.is_true(), bytes[31] == 1);
1559        }
1560
1561        #[test]
1562        fn test_u_is_zero(x in any::<[u8; 32]>()) {
1563            let x = U::from(x);
1564            let ex = U256::from_be_bytes(x.0);
1565            assert_eq!(ex.is_zero(), x.is_zero());
1566        }
1567
1568        #[test]
1569        fn test_u_div(x in any::<U>(), y in any::<U>()) {
1570            let ex = U256::from_be_bytes(x.0);
1571            let ey = U256::from_be_bytes(y.0);
1572            assert_eq!((ex.wrapping_div(ey)).to_be_bytes(), x.wrapping_div(&y).0);
1573        }
1574
1575        #[test]
1576        fn test_u_mul(x in any::<U>(), y in any::<U>()) {
1577            let ex = U256::from_be_bytes(x.0);
1578            let ey = U256::from_be_bytes(y.0);
1579            assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), wrapping_mul(&x,  &y).0);
1580        }
1581
1582        #[test]
1583        fn test_u_mod(x in any::<U>(), y in any::<U>()) {
1584            let ex = U256::from_be_bytes(x.0);
1585            let ey = U256::from_be_bytes(y.0);
1586            assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1587        }
1588
1589        #[test]
1590        fn test_u_add(x in any::<U>(), y in any::<U>()) {
1591            let ex = U256::from_be_bytes(x.0);
1592            let ey = U256::from_be_bytes(y.0);
1593            let e = U::from(ex.wrapping_add(ey).to_be_bytes::<32>());
1594            assert_eq!(e, x.wrapping_add(&y), "{e} != {}", x + y);
1595        }
1596
1597        #[test]
1598        fn test_u_sub(x in any::<U>(), y in any::<U>()) {
1599            let ex = U256::from_be_bytes(x.0);
1600            let ey = U256::from_be_bytes(y.0);
1601            assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), x.wrapping_sub(&y).0);
1602        }
1603
1604        #[test]
1605        fn test_u_cmp(x in any::<U>(), y in any::<U>()) {
1606            let ex = U256::from_be_bytes(x.0);
1607            let ey = U256::from_be_bytes(y.0);
1608            assert_eq!(ex.cmp(&ey), x.cmp(&y));
1609        }
1610
1611        #[test]
1612        fn test_u_to_str(x in any::<U>()) {
1613            assert_eq!(U256::from_be_bytes(x.0).to_string(), x.to_string());
1614        }
1615
1616        #[test]
1617        fn test_u_shl(x in any::<U>(), i in any::<usize>()) {
1618            let l = U((U256::from_be_bytes(x.0) << i).to_be_bytes::<32>());
1619            assert_eq!(l, x << i);
1620        }
1621
1622        #[test]
1623        fn test_u_shr(x in any::<U>(), i in any::<usize>()) {
1624            let l = U((U256::from_be_bytes(x.0) >> i).to_be_bytes::<32>());
1625            assert_eq!(l, x >> i);
1626        }
1627
1628        #[test]
1629        fn test_trailing_zeros(x in any::<U>()) {
1630            assert_eq!(U256::from_be_bytes(x.0).trailing_zeros(), x.trailing_zeros());
1631        }
1632
1633        #[test]
1634        fn test_i_is_zero(x in any::<U>()) {
1635            let ex = I256::from_be_bytes(x.0);
1636            assert_eq!(ex.is_zero(), x.is_zero());
1637        }
1638
1639        #[test]
1640        fn test_i_div(x in any::<I>(), y in any::<I>()) {
1641            let ex = I256::from_be_bytes(x.0);
1642            let ey = I256::from_be_bytes(y.0);
1643            assert_eq!((ex / ey).to_be_bytes(), (x / y).0);
1644        }
1645
1646        #[test]
1647        fn test_i_mul(x in any::<I>(), y in any::<I>()) {
1648            let ex = I256::from_be_bytes(x.0);
1649            let ey = I256::from_be_bytes(y.0);
1650            assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), (x * y).0);
1651        }
1652
1653        #[test]
1654        fn test_i_mod(x in any::<I>(), y in any::<I>()) {
1655            let ex = I256::from_be_bytes(x.0);
1656            let ey = I256::from_be_bytes(y.0);
1657            assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1658        }
1659
1660        #[test]
1661        fn test_i_add(x in any::<I>(), y in any::<I>()) {
1662            let ex = I256::from_be_bytes(x.0);
1663            let ey = I256::from_be_bytes(y.0);
1664            assert_eq!((ex.wrapping_add(ey)).to_be_bytes(), (x + y).0);
1665        }
1666
1667        #[test]
1668        fn test_i_sub(x in any::<I>(), y in any::<I>()) {
1669            let ex = I256::from_be_bytes(x.0);
1670            let ey = I256::from_be_bytes(y.0);
1671            assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), (x - y).0);
1672        }
1673
1674        #[test]
1675        fn test_i_cmp(x in any::<I>(), y in any::<I>()) {
1676            let ex = I256::from_be_bytes(x.0);
1677            let ey = I256::from_be_bytes(y.0);
1678            assert_eq!(ex.cmp(&ey), x.cmp(&y));
1679        }
1680
1681        #[test]
1682        fn test_u_u8(x in any::<u8>()) {
1683            let mut b = [0u8; 32];
1684            b[32-size_of::<u8>()..].copy_from_slice(&x.to_be_bytes());
1685            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1686        }
1687
1688        #[test]
1689        fn test_u_u16(x in any::<u16>()) {
1690            let mut b = [0u8; 32];
1691            b[32-size_of::<u16>()..].copy_from_slice(&x.to_be_bytes());
1692            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1693        }
1694
1695        #[test]
1696        fn test_u_u32(x in any::<u32>()) {
1697            let mut b = [0u8; 32];
1698            b[32-size_of::<u32>()..].copy_from_slice(&x.to_be_bytes());
1699            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1700        }
1701
1702        #[test]
1703        fn test_u_u64(x in any::<u64>()) {
1704            let mut b = [0u8; 32];
1705            b[32-size_of::<u64>()..].copy_from_slice(&x.to_be_bytes());
1706            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1707        }
1708
1709        #[test]
1710        fn test_u_u128(x in any::<u128>()) {
1711            let mut b = [0u8; 32];
1712            b[32-size_of::<u128>()..].copy_from_slice(&x.to_be_bytes());
1713            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1714        }
1715
1716        #[test]
1717        fn test_to_and_from_addrs(x in any::<Address>()) {
1718            let y: Address = U::from(x).into();
1719            assert_eq!(x, y)
1720        }
1721
1722        #[test]
1723        fn test_u_conv_to_and_from_u8(x in any::<u8>()) {
1724            assert_eq!(x.wrapping_add(1), U::from(x).wrapping_add(&U::ONE).into());
1725        }
1726
1727        #[test]
1728        fn test_print_to_and_from(x in any::<[u8; 32]>()) {
1729            let e = format!("{}", U256::from_be_bytes(x));
1730            let v = format!("{}", U(x));
1731            assert_eq!(e, v);
1732        }
1733
1734        #[test]
1735        fn test_u_from_str(x in strat_any_u256()) {
1736            let v = U::from_str(x.to_string().as_str()).unwrap();
1737            assert_eq!(
1738                U::from(x.to_be_bytes::<32>()),
1739                v,
1740                "{x} != {v}",
1741            )
1742        }
1743    }
1744}