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