Skip to main content

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