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