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