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