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