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, LowerHex, UpperHex},
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 LowerHex for U {
921    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
922        let mut b = [0u8; 32 * 2];
923        let s = const_hex::encode_to_str(self.0, &mut b).unwrap();
924        write!(f, "{s}")
925    }
926}
927
928impl UpperHex for U {
929    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
930        let mut b = [0u8; 32 * 2];
931        let s = const_hex::encode_to_str_upper(self.0, &mut b).unwrap();
932        write!(f, "{s}")
933    }
934}
935
936impl Debug for U {
937    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
938        write!(f, "{self:x}")
939    }
940}
941
942impl Not for U {
943    type Output = Self;
944
945    fn not(mut self) -> Self::Output {
946        for i in 0..32 {
947            self[i] = !self[i]
948        }
949        self
950    }
951}
952
953impl Neg for U {
954    type Output = Self;
955
956    fn neg(self) -> Self {
957        let mut r = U::ZERO;
958        let mut carry = 1u16;
959        for i in (0..32).rev() {
960            let inverted = !self.0[i] as u16;
961            let sum = inverted + carry;
962            r[i] = sum as u8;
963            carry = sum >> 8;
964        }
965        r
966    }
967}
968
969#[derive(Debug, Clone, PartialEq)]
970pub enum UFromStrErr {
971    InvalidChar(char),
972    Overflow,
973    Empty,
974}
975
976impl Display for UFromStrErr {
977    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
978        write!(f, "{self:?}")
979    }
980}
981
982impl core::error::Error for UFromStrErr {}
983
984impl FromStr for U {
985    type Err = UFromStrErr;
986
987    fn from_str(s: &str) -> Result<Self, Self::Err> {
988        if s.is_empty() {
989            return Err(UFromStrErr::Empty);
990        }
991        let mut r = U::ZERO;
992        for c in s.chars() {
993            r *= U::from_u32(10);
994            r += match c {
995                '0'..='9' => U::from(c as u8 - b'0'),
996                _ => return Err(UFromStrErr::InvalidChar(c)),
997            };
998        }
999        Ok(r)
1000    }
1001}
1002
1003impl U {
1004    pub const ZERO: Self = U([0u8; 32]);
1005
1006    pub const MAX: Self = U([u8::MAX; 32]);
1007
1008    pub const ONE: Self = U([
1009        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,
1010        0, 1,
1011    ]);
1012
1013    pub fn is_true(&self) -> bool {
1014        self.0[31] == 1
1015    }
1016
1017    pub const fn is_zero(&self) -> bool {
1018        let mut i = 0;
1019        while i < 32 {
1020            if self.0[i] != 0 {
1021                return false;
1022            }
1023            i += 1;
1024        }
1025        true
1026    }
1027
1028    pub fn abs_diff(&self, y: &U) -> U {
1029        if self > y {
1030            self - y
1031        } else {
1032            y - self
1033        }
1034    }
1035
1036    pub const fn const_addr(self) -> Address {
1037        self.const_20_slice()
1038    }
1039
1040    pub const fn is_max(&self) -> bool {
1041        let mut i = 0;
1042        while i < 32 {
1043            if self.0[i] != u8::MAX {
1044                return false;
1045            }
1046            i += 1;
1047        }
1048        true
1049    }
1050
1051    pub fn is_some(&self) -> bool {
1052        !self.is_zero()
1053    }
1054
1055    pub fn trailing_zeros(&self) -> usize {
1056        let mut count = 0;
1057        for i in (0..32).rev() {
1058            if self[i] == 0 {
1059                count += 8;
1060            } else {
1061                count += self[i].trailing_zeros() as usize;
1062                break;
1063            }
1064        }
1065        count
1066    }
1067
1068    pub fn as_slice(&self) -> &[u8; 32] {
1069        &self.0
1070    }
1071
1072    pub const fn from_slice_leftpad(x: &[u8]) -> Option<U> {
1073        if x.len() > 32 {
1074            return None;
1075        }
1076        let mut b = [0u8; 32];
1077        let mut i = 0;
1078        while i < x.len() {
1079            b[32 - x.len() + i] = x[i];
1080            i += 1;
1081        }
1082        Some(U(b))
1083    }
1084
1085    #[cfg(feature = "alloc")]
1086    pub fn as_vec(self) -> alloc::vec::Vec<u8> {
1087        self.0.to_vec()
1088    }
1089
1090    pub fn checked_add_opt(&self, y: &Self) -> Option<Self> {
1091        checked_add_opt(self, y)
1092    }
1093
1094    pub fn checked_add(&self, y: &Self) -> Self {
1095        checked_add(self, y)
1096    }
1097
1098    pub fn checked_mul_opt(&self, y: &Self) -> Option<Self> {
1099        checked_mul_opt(self, y)
1100    }
1101
1102    pub fn checked_mul(&self, y: &Self) -> Self {
1103        checked_mul(self, y)
1104    }
1105
1106    pub fn checked_sub_opt(&self, y: &Self) -> Option<Self> {
1107        checked_sub_opt(self, y)
1108    }
1109
1110    pub fn checked_sub(&self, y: &Self) -> Self {
1111        checked_sub(self, y)
1112    }
1113
1114    pub fn checked_div_opt(&self, y: &Self) -> Option<Self> {
1115        checked_div_opt(self, y)
1116    }
1117
1118    pub fn checked_div(&self, y: &Self) -> Self {
1119        checked_div(self, y)
1120    }
1121
1122    pub fn checked_pow(&self, exp: &U) -> Option<Self> {
1123        checked_pow(self, exp)
1124    }
1125
1126    pub fn wrapping_add(&self, y: &Self) -> U {
1127        wrapping_add(self, y)
1128    }
1129
1130    pub fn wrapping_sub(&self, y: &Self) -> U {
1131        wrapping_sub(self, y)
1132    }
1133
1134    pub fn wrapping_mul(&self, y: &Self) -> U {
1135        wrapping_mul(self, y)
1136    }
1137
1138    pub fn wrapping_div(&self, y: &Self) -> U {
1139        wrapping_div(self, y)
1140    }
1141
1142    pub fn saturating_add(&self, y: &Self) -> U {
1143        saturating_add(self, y)
1144    }
1145
1146    pub fn saturating_sub(&self, y: &Self) -> U {
1147        saturating_sub(self, y)
1148    }
1149
1150    pub fn saturating_mul(&self, y: &Self) -> U {
1151        saturating_mul(self, y)
1152    }
1153
1154    pub fn saturating_div(&self, y: &Self) -> Self {
1155        saturating_div(self, y)
1156    }
1157
1158    pub fn wrapping_neg(self) -> Self {
1159        let mut x = self;
1160        let mut carry = 1u8;
1161        for b in x.iter_mut().rev() {
1162            *b = (!*b).wrapping_add(carry);
1163            carry = b.is_zero() as u8;
1164        }
1165        x
1166    }
1167
1168    pub fn mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1169        mul_div(self, y, z)
1170    }
1171
1172    pub fn mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1173        mul_div_round_up(self, y, z)
1174    }
1175
1176    pub fn widening_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1177        widening_mul_div(self, y, z)
1178    }
1179
1180    pub fn widening_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1181        widening_mul_div_round_up(self, y, z)
1182    }
1183
1184    #[cfg(feature = "ruint-enabled")]
1185    pub fn ruint_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1186        ruint_mul_div(self, y, z)
1187    }
1188
1189    #[cfg(feature = "ruint-enabled")]
1190    pub fn ruint_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1191        ruint_mul_div_round_up(self, y, z)
1192    }
1193
1194    pub fn mul_mod(&self, y: &Self, z: &Self) -> Self {
1195        mul_mod(*self, y, z)
1196    }
1197
1198    pub fn add_mod(&self, y: &Self, z: &Self) -> Self {
1199        let mut b = self.0;
1200        unsafe { math_add_mod(b.as_mut_ptr(), y.as_ptr(), z.as_ptr()) }
1201        Self(b)
1202    }
1203
1204    pub fn checked_rooti(self, x: u32) -> Option<Self> {
1205        checked_rooti(self, x)
1206    }
1207
1208    pub fn from_hex(x: &str) -> Option<U> {
1209        match const_hex::decode_to_array::<_, 32>(x) {
1210            Ok(v) => Some(U(v)),
1211            Err(_) => None,
1212        }
1213    }
1214
1215    pub const fn const_from_hex(x: &[u8; 64]) -> Option<U> {
1216        match const_hex::const_decode_to_array::<32>(x) {
1217            Ok(v) => Some(U(v)),
1218            Err(_) => None,
1219        }
1220    }
1221}
1222
1223impl Display for U {
1224    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1225        if self.is_zero() {
1226            return write!(f, "0");
1227        }
1228        let mut result = [0u8; 78];
1229        let mut i = 0;
1230        for byte in self.0 {
1231            let mut carry = byte as u32;
1232            for digit in result[..i].iter_mut() {
1233                let temp = (*digit as u32) * 256 + carry;
1234                *digit = (temp % 10) as u8;
1235                carry = temp / 10;
1236            }
1237            while carry > 0 {
1238                result[i] = (carry % 10) as u8;
1239                i += 1;
1240                debug_assert!(78 >= i, "{} > {i}", result.len());
1241                carry /= 10;
1242            }
1243        }
1244        for &digit in result[..i].iter().rev() {
1245            write!(f, "{}", digit)?;
1246        }
1247        Ok(())
1248    }
1249}
1250
1251impl From<U> for [u8; 32] {
1252    fn from(x: U) -> Self {
1253        x.0
1254    }
1255}
1256
1257impl From<&U> for U {
1258    fn from(x: &U) -> Self {
1259        *x
1260    }
1261}
1262
1263impl From<U> for bool {
1264    fn from(x: U) -> Self {
1265        x.0[31] == 1
1266    }
1267}
1268
1269impl From<&[u8]> for U {
1270    fn from(x: &[u8]) -> Self {
1271        let x: &[u8; 32] = x.try_into().unwrap();
1272        (*x).into()
1273    }
1274}
1275
1276impl From<&[u8; 32]> for &U {
1277    fn from(x: &[u8; 32]) -> Self {
1278        unsafe { &*(x as *const [u8; 32] as *const U) }
1279    }
1280}
1281
1282impl From<[u8; 32]> for U {
1283    fn from(x: [u8; 32]) -> Self {
1284        U(x)
1285    }
1286}
1287
1288impl Deref for U {
1289    type Target = [u8; 32];
1290
1291    fn deref(&self) -> &Self::Target {
1292        &self.0
1293    }
1294}
1295
1296impl DerefMut for U {
1297    fn deref_mut(&mut self) -> &mut Self::Target {
1298        &mut self.0
1299    }
1300}
1301
1302impl From<bool> for U {
1303    fn from(x: bool) -> Self {
1304        U::from(&[x as u8])
1305    }
1306}
1307
1308impl Zero for U {
1309    fn zero() -> Self {
1310        U::ZERO
1311    }
1312
1313    fn is_zero(&self) -> bool {
1314        self.0.iter().all(|&b| b == 0)
1315    }
1316}
1317
1318impl Default for U {
1319    fn default() -> Self {
1320        U::ZERO
1321    }
1322}
1323
1324impl One for U {
1325    fn one() -> Self {
1326        U::ONE
1327    }
1328}
1329
1330impl Index<usize> for U {
1331    type Output = u8;
1332
1333    fn index(&self, index: usize) -> &Self::Output {
1334        &self.0[index]
1335    }
1336}
1337
1338impl IndexMut<usize> for U {
1339    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1340        &mut self.0[index]
1341    }
1342}
1343
1344impl I {
1345    fn is_neg(&self) -> bool {
1346        self.0[0] & 0x80 != 0
1347    }
1348
1349    pub fn is_zero(&self) -> bool {
1350        *self == Self::ZERO
1351    }
1352
1353    pub fn is_some(&self) -> bool {
1354        !self.is_zero()
1355    }
1356
1357    pub fn as_slice(&self) -> &[u8; 32] {
1358        &self.0
1359    }
1360
1361    fn neg(&self) -> Self {
1362        let x = wrapping_add(&U(self.0.map(|b| !b)), &U::ONE);
1363        I(x.0)
1364    }
1365
1366    fn abs(self) -> U {
1367        if self.is_neg() {
1368            U(self.neg().0)
1369        } else {
1370            U(self.0)
1371        }
1372    }
1373}
1374
1375macro_rules! from_slices {
1376    ($($n:expr),+ $(,)?) => {
1377        $(
1378            paste::paste! {
1379                impl From<&[u8; $n]> for U {
1380                    fn from(x: &[u8; $n]) -> Self {
1381                        let mut b = [0u8; 32];
1382                        b[32 - $n..].copy_from_slice(x);
1383                        U(b)
1384                    }
1385                }
1386
1387                impl From<[u8; $n]> for U {
1388                    fn from(x: [u8; $n]) -> Self {
1389                        U::from(&x)
1390                    }
1391                }
1392
1393                impl U {
1394                    pub const fn [<const_ $n _slice>](self) -> [u8; $n] {
1395                        let mut b = [0u8; $n];
1396                        let mut i = 0;
1397                        while i < $n {
1398                            b[i] = self.0[32-$n+i];
1399                            i += 1;
1400                        }
1401                        b
1402                    }
1403                }
1404
1405                impl From<U> for [u8; $n] {
1406                    fn from(x: U) -> Self {
1407                        unsafe { *(x.as_ptr().add(32 - $n) as *const [u8; $n]) }
1408                    }
1409                }
1410            }
1411        )+
1412    };
1413}
1414
1415from_slices!(
1416    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,
1417    27, 28, 29, 30, 31
1418);
1419
1420impl From<&U> for Address {
1421    fn from(x: &U) -> Self {
1422        (*x).into()
1423    }
1424}
1425
1426macro_rules! from_ints {
1427    ($($t:ty),+ $(,)?) => {
1428        $(
1429            paste::paste! {
1430                impl U {
1431                    pub const fn [<from_ $t>](x: $t) -> U {
1432                        U(array_concat::concat_arrays!(
1433                            [0u8; 32-core::mem::size_of::<$t>()],
1434                            x.to_be_bytes())
1435                        )
1436                    }
1437                }
1438
1439                impl From<$t> for U {
1440                    fn from(x: $t) -> Self {
1441                        U::[<from_ $t>](x)
1442                    }
1443                }
1444
1445                impl From<U> for $t {
1446                    fn from(x: U) -> Self {
1447                        Self::from_be_bytes(x.into())
1448                    }
1449                }
1450            }
1451        )+
1452    };
1453}
1454
1455#[macro_export]
1456macro_rules! u {
1457    ($e:expr) => {
1458        $crate::U::from_u32($e)
1459    };
1460}
1461
1462from_ints! { u8, u16, u32, u64, u128, usize }
1463
1464impl From<I> for [u8; 32] {
1465    fn from(x: I) -> Self {
1466        x.0
1467    }
1468}
1469
1470impl From<[u8; 32]> for I {
1471    fn from(x: [u8; 32]) -> Self {
1472        I(x)
1473    }
1474}
1475
1476fn i_add(x: &I, y: &I) -> I {
1477    I(wrapping_add(&U(x.0), &U(y.0)).0)
1478}
1479
1480fn i_sub(x: &I, y: &I) -> I {
1481    I(wrapping_sub(&U(x.0), &U(y.0)).0)
1482}
1483
1484fn i_mul(x: &I, y: &I) -> I {
1485    let result = wrapping_mul(&U(x.0), &U(y.0));
1486    I(result.0)
1487}
1488
1489fn i_div(x: &I, y: &I) -> I {
1490    let r = wrapping_div(&x.abs(), &y.abs());
1491    if x.is_neg() ^ y.is_neg() {
1492        I(r.0).neg()
1493    } else {
1494        I(r.0)
1495    }
1496}
1497
1498fn i_rem(x: &I, y: &I) -> I {
1499    let r = modd(&x.abs(), &y.abs());
1500    if x.is_neg() {
1501        I(r.0).neg()
1502    } else {
1503        I(r.0)
1504    }
1505}
1506
1507impl Add for I {
1508    type Output = I;
1509    fn add(self, rhs: I) -> I {
1510        i_add(&self, &rhs)
1511    }
1512}
1513
1514impl Add for &I {
1515    type Output = I;
1516    fn add(self, rhs: &I) -> I {
1517        i_add(self, rhs)
1518    }
1519}
1520
1521impl Sub for I {
1522    type Output = I;
1523    fn sub(self, rhs: I) -> I {
1524        i_sub(&self, &rhs)
1525    }
1526}
1527
1528impl Sub for &I {
1529    type Output = I;
1530    fn sub(self, rhs: &I) -> I {
1531        i_sub(self, rhs)
1532    }
1533}
1534
1535impl Mul for I {
1536    type Output = I;
1537    fn mul(self, rhs: I) -> I {
1538        i_mul(&self, &rhs)
1539    }
1540}
1541
1542impl Mul for &I {
1543    type Output = I;
1544    fn mul(self, rhs: &I) -> I {
1545        i_mul(self, rhs)
1546    }
1547}
1548
1549impl Div for I {
1550    type Output = I;
1551    fn div(self, rhs: I) -> I {
1552        i_div(&self, &rhs)
1553    }
1554}
1555
1556impl Div for &I {
1557    type Output = I;
1558    fn div(self, rhs: &I) -> I {
1559        i_div(self, rhs)
1560    }
1561}
1562
1563impl Rem for I {
1564    type Output = I;
1565    fn rem(self, rhs: I) -> I {
1566        i_rem(&self, &rhs)
1567    }
1568}
1569
1570impl Eq for I {}
1571
1572impl PartialOrd for I {
1573    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1574        Some(self.cmp(other))
1575    }
1576}
1577
1578impl Ord for I {
1579    fn cmp(&self, other: &Self) -> Ordering {
1580        let self_sign = self.0[0] & 0x80;
1581        let other_sign = other.0[0] & 0x80;
1582        match (self_sign, other_sign) {
1583            (0, 0x80) => Ordering::Greater,
1584            (0x80, 0) => Ordering::Less,
1585            _ => self.0.cmp(&other.0),
1586        }
1587    }
1588}
1589
1590impl Rem for &I {
1591    type Output = I;
1592    fn rem(self, rhs: &I) -> I {
1593        i_rem(self, rhs)
1594    }
1595}
1596
1597impl I {
1598    pub const ZERO: Self = I([0u8; 32]);
1599
1600    pub const ONE: Self = I([
1601        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,
1602        0, 1,
1603    ]);
1604}
1605
1606impl Zero for I {
1607    fn zero() -> Self {
1608        I::ZERO
1609    }
1610    fn is_zero(&self) -> bool {
1611        self.0.iter().all(|&b| b == 0)
1612    }
1613}
1614
1615impl Default for I {
1616    fn default() -> Self {
1617        I::ZERO
1618    }
1619}
1620
1621impl One for I {
1622    fn one() -> Self {
1623        I::ONE
1624    }
1625}
1626
1627#[test]
1628fn test_is_zeroes() {
1629    assert!(U::ZERO.is_zero());
1630    assert!(U::ONE.is_some());
1631    assert!(I::ZERO.is_zero());
1632    assert!(I::ONE.is_some());
1633}
1634
1635#[cfg(all(
1636    test,
1637    feature = "alloy-enabled",
1638    feature = "proptest",
1639    feature = "std",
1640    not(target_arch = "wasm32")
1641))]
1642mod test {
1643    use proptest::prelude::*;
1644
1645    use super::*;
1646
1647    fn strat_any_u256() -> impl Strategy<Value = U256> {
1648        // Arbitrary seems to be having some issues with U256:
1649        any::<[u8; 32]>().prop_map(U256::from_be_bytes)
1650    }
1651
1652    proptest! {
1653        #[test]
1654        fn wrapping_div_b_zero_denominator_yields_zero(numerator in any::<[u8; 4]>()) {
1655            let zero = [0u8; 4];
1656            prop_assert_eq!(wrapping_div_quo_rem_b::<4>(&numerator, &zero).0, zero);
1657        }
1658
1659        #[test]
1660        fn wrapping_div_b_matches_integer_division(
1661            numerator in any::<[u8; 4]>(),
1662            denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1663        ) {
1664            let numerator_u32 = u32::from_be_bytes(numerator);
1665            let denominator_u32 = u32::from_be_bytes(denominator);
1666            let expected = numerator_u32 / denominator_u32;
1667            prop_assert_eq!(
1668                wrapping_div_quo_rem_b::<4>(&numerator, &denominator).0,
1669                expected.to_be_bytes()
1670            );
1671        }
1672
1673        #[test]
1674        fn wrapping_mod_b_matches_integer_modulo(
1675            numerator in any::<[u8; 4]>(),
1676            denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1677        ) {
1678            let numerator_u32 = u32::from_be_bytes(numerator);
1679            let denominator_u32 = u32::from_be_bytes(denominator);
1680            let expected = numerator_u32 % denominator_u32;
1681            prop_assert_eq!(
1682                wrapping_div_quo_rem_b::<4>(&numerator, &denominator).1,
1683                expected.to_be_bytes()
1684            );
1685        }
1686
1687        #[test]
1688        fn wrapping_add_b_handles_carry(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1689            let lhs_u32 = u32::from_be_bytes(lhs);
1690            let rhs_u32 = u32::from_be_bytes(rhs);
1691            let expected = lhs_u32.wrapping_add(rhs_u32);
1692            prop_assert_eq!(wrapping_add_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1693        }
1694
1695        #[test]
1696        fn wrapping_sub_b_handles_borrow(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1697            let lhs_u32 = u32::from_be_bytes(lhs);
1698            let rhs_u32 = u32::from_be_bytes(rhs);
1699            let expected = lhs_u32.wrapping_sub(rhs_u32);
1700            prop_assert_eq!(wrapping_sub_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1701        }
1702
1703        #[test]
1704        fn wrapping_mul_b_matches_wrapping_arithmetic(lhs in any::<[u8; 32]>(), rhs in any::<[u8; 32]>()) {
1705            let lhs_u = U::from(lhs);
1706            let rhs_u = U::from(rhs);
1707            let expected = lhs_u.wrapping_mul(&rhs_u);
1708            prop_assert_eq!(wrapping_mul_b::<32>(&lhs, &rhs), expected.0);
1709        }
1710
1711        #[test]
1712        fn const_wrapping_div_agrees_with_wrapping_div_b(
1713            numerator in any::<[u8; 32]>(),
1714            denominator in any::<[u8; 32]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 32])
1715        ) {
1716            let numerator_u = U::from(numerator);
1717            let denominator_u = U::from(denominator);
1718            prop_assert_eq!(
1719                const_wrapping_div(&numerator_u, &denominator_u).0,
1720                wrapping_div_quo_rem_b::<32>(&numerator, &denominator).0
1721            );
1722        }
1723
1724        #[test]
1725        fn u_predicates_track_zero_and_true(bytes in any::<[u8; 32]>()) {
1726            let value = U::from(bytes);
1727            let is_zero = bytes.iter().all(|&b| b == 0);
1728            prop_assert_eq!(value.is_zero(), is_zero);
1729            prop_assert_eq!(value.is_some(), !is_zero);
1730            prop_assert_eq!(value.is_true(), bytes[31] == 1);
1731        }
1732
1733        #[test]
1734        fn test_u_is_zero(x in any::<[u8; 32]>()) {
1735            let x = U::from(x);
1736            let ex = U256::from_be_bytes(x.0);
1737            assert_eq!(ex.is_zero(), x.is_zero());
1738        }
1739
1740        #[test]
1741        fn test_u_div(x in any::<U>(), y in any::<U>()) {
1742            let ex = U256::from_be_bytes(x.0);
1743            let ey = U256::from_be_bytes(y.0);
1744            assert_eq!((ex.wrapping_div(ey)).to_be_bytes(), x.wrapping_div(&y).0);
1745        }
1746
1747        #[test]
1748        fn test_u_mul(x in any::<U>(), y in any::<U>()) {
1749            let ex = U256::from_be_bytes(x.0);
1750            let ey = U256::from_be_bytes(y.0);
1751            assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), wrapping_mul(&x,  &y).0);
1752        }
1753
1754        #[test]
1755        fn test_u_mod(x in any::<U>(), y in any::<U>()) {
1756            let ex = U256::from_be_bytes(x.0);
1757            let ey = U256::from_be_bytes(y.0);
1758            assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1759        }
1760
1761        #[test]
1762        fn test_u_add(x in any::<U>(), y in any::<U>()) {
1763            let ex = U256::from_be_bytes(x.0);
1764            let ey = U256::from_be_bytes(y.0);
1765            let e = U::from(ex.wrapping_add(ey).to_be_bytes::<32>());
1766            assert_eq!(e, x.wrapping_add(&y), "{e} != {}", x + y);
1767        }
1768
1769        #[test]
1770        fn test_u_sub(x in any::<U>(), y in any::<U>()) {
1771            let ex = U256::from_be_bytes(x.0);
1772            let ey = U256::from_be_bytes(y.0);
1773            assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), x.wrapping_sub(&y).0);
1774        }
1775
1776        #[test]
1777        fn test_u_cmp(x in any::<U>(), y in any::<U>()) {
1778            let ex = U256::from_be_bytes(x.0);
1779            let ey = U256::from_be_bytes(y.0);
1780            assert_eq!(ex.cmp(&ey), x.cmp(&y));
1781        }
1782
1783        #[test]
1784        fn test_u_to_str(x in any::<U>()) {
1785            assert_eq!(U256::from_be_bytes(x.0).to_string(), x.to_string());
1786        }
1787
1788        #[test]
1789        fn test_u_shl(x in any::<U>(), i in any::<usize>()) {
1790            let l = U((U256::from_be_bytes(x.0) << i).to_be_bytes::<32>());
1791            assert_eq!(l, x << i);
1792        }
1793
1794        #[test]
1795        fn test_u_shr(x in any::<U>(), i in any::<usize>()) {
1796            let l = U((U256::from_be_bytes(x.0) >> i).to_be_bytes::<32>());
1797            assert_eq!(l, x >> i);
1798        }
1799
1800        #[test]
1801        fn test_trailing_zeros(x in any::<U>()) {
1802            assert_eq!(U256::from_be_bytes(x.0).trailing_zeros(), x.trailing_zeros());
1803        }
1804
1805        #[test]
1806        fn test_i_is_zero(x in any::<U>()) {
1807            let ex = I256::from_be_bytes(x.0);
1808            assert_eq!(ex.is_zero(), x.is_zero());
1809        }
1810
1811        #[test]
1812        fn test_i_div(x in any::<I>(), y in any::<I>()) {
1813            let ex = I256::from_be_bytes(x.0);
1814            let ey = I256::from_be_bytes(y.0);
1815            assert_eq!((ex / ey).to_be_bytes(), (x / y).0);
1816        }
1817
1818        #[test]
1819        fn test_i_mul(x in any::<I>(), y in any::<I>()) {
1820            let ex = I256::from_be_bytes(x.0);
1821            let ey = I256::from_be_bytes(y.0);
1822            assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), (x * y).0);
1823        }
1824
1825        #[test]
1826        fn test_i_mod(x in any::<I>(), y in any::<I>()) {
1827            let ex = I256::from_be_bytes(x.0);
1828            let ey = I256::from_be_bytes(y.0);
1829            assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1830        }
1831
1832        #[test]
1833        fn test_i_add(x in any::<I>(), y in any::<I>()) {
1834            let ex = I256::from_be_bytes(x.0);
1835            let ey = I256::from_be_bytes(y.0);
1836            assert_eq!((ex.wrapping_add(ey)).to_be_bytes(), (x + y).0);
1837        }
1838
1839        #[test]
1840        fn test_i_sub(x in any::<I>(), y in any::<I>()) {
1841            let ex = I256::from_be_bytes(x.0);
1842            let ey = I256::from_be_bytes(y.0);
1843            assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), (x - y).0);
1844        }
1845
1846        #[test]
1847        fn test_i_cmp(x in any::<I>(), y in any::<I>()) {
1848            let ex = I256::from_be_bytes(x.0);
1849            let ey = I256::from_be_bytes(y.0);
1850            assert_eq!(ex.cmp(&ey), x.cmp(&y));
1851        }
1852
1853        #[test]
1854        fn test_u_u8(x in any::<u8>()) {
1855            let mut b = [0u8; 32];
1856            b[32-size_of::<u8>()..].copy_from_slice(&x.to_be_bytes());
1857            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1858        }
1859
1860        #[test]
1861        fn test_u_u16(x in any::<u16>()) {
1862            let mut b = [0u8; 32];
1863            b[32-size_of::<u16>()..].copy_from_slice(&x.to_be_bytes());
1864            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1865        }
1866
1867        #[test]
1868        fn test_u_u32(x in any::<u32>()) {
1869            let mut b = [0u8; 32];
1870            b[32-size_of::<u32>()..].copy_from_slice(&x.to_be_bytes());
1871            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1872        }
1873
1874        #[test]
1875        fn test_u_u64(x in any::<u64>()) {
1876            let mut b = [0u8; 32];
1877            b[32-size_of::<u64>()..].copy_from_slice(&x.to_be_bytes());
1878            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1879        }
1880
1881        #[test]
1882        fn test_u_u128(x in any::<u128>()) {
1883            let mut b = [0u8; 32];
1884            b[32-size_of::<u128>()..].copy_from_slice(&x.to_be_bytes());
1885            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1886        }
1887
1888        #[test]
1889        fn test_to_and_from_addrs(x in any::<Address>()) {
1890            let y: Address = U::from(x).into();
1891            assert_eq!(x, y)
1892        }
1893
1894        #[test]
1895        fn test_u_conv_to_and_from_u8(x in any::<u8>()) {
1896            assert_eq!(x.wrapping_add(1), U::from(x).wrapping_add(&U::ONE).into());
1897        }
1898
1899        #[test]
1900        fn test_print_to_and_from(x in any::<[u8; 32]>()) {
1901            let e = format!("{}", U256::from_be_bytes(x));
1902            let v = format!("{}", U(x));
1903            assert_eq!(e, v);
1904        }
1905
1906        #[test]
1907        fn test_u_from_str(x in strat_any_u256()) {
1908            let v = U::from_str(x.to_string().as_str()).unwrap();
1909            assert_eq!(
1910                U::from(x.to_be_bytes::<32>()),
1911                v,
1912                "{x} != {v}",
1913            )
1914        }
1915
1916        #[test]
1917        fn array_truncate(x in any::<[u8; 20]>()) {
1918            assert_eq!(x, U::from(x).const_addr());
1919        }
1920    }
1921}