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