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