bobcat_maths/
lib.rs

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