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