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]) -> 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                impl PartialEq<$t> for U {
1484                    fn eq(&self, rhs: &$t) -> bool {
1485                        *self == U::from(*rhs)
1486                    }
1487                }
1488
1489                impl PartialOrd<$t> for U {
1490                    fn partial_cmp(&self, rhs: &$t) -> Option<Ordering> {
1491                        let rhs = rhs.to_be_bytes();
1492                        let n = core::mem::size_of::<$t>();
1493                        let split = 32 - n;
1494                        if self.0[..split].iter().any(|&b| b != 0) {
1495                            return Some(Ordering::Greater);
1496                        }
1497                        Some(self.0[split..].cmp(&rhs))
1498                    }
1499                }
1500            }
1501        )+
1502    };
1503}
1504
1505#[macro_export]
1506macro_rules! u {
1507    ($e:expr) => {
1508        $crate::U::from_u32($e)
1509    };
1510}
1511
1512from_ints! { u8, u16, u32, u64, u128, usize }
1513
1514impl From<I> for [u8; 32] {
1515    fn from(x: I) -> Self {
1516        x.0
1517    }
1518}
1519
1520impl From<[u8; 32]> for I {
1521    fn from(x: [u8; 32]) -> Self {
1522        I(x)
1523    }
1524}
1525
1526fn i_add(x: &I, y: &I) -> I {
1527    I(wrapping_add(&U(x.0), &U(y.0)).0)
1528}
1529
1530fn i_sub(x: &I, y: &I) -> I {
1531    I(wrapping_sub(&U(x.0), &U(y.0)).0)
1532}
1533
1534fn i_mul(x: &I, y: &I) -> I {
1535    let result = wrapping_mul(&U(x.0), &U(y.0));
1536    I(result.0)
1537}
1538
1539fn i_div(x: &I, y: &I) -> I {
1540    let r = wrapping_div(&x.abs(), &y.abs());
1541    if x.is_neg() ^ y.is_neg() {
1542        I(r.0).neg()
1543    } else {
1544        I(r.0)
1545    }
1546}
1547
1548fn i_rem(x: &I, y: &I) -> I {
1549    let r = modd(&x.abs(), &y.abs());
1550    if x.is_neg() { I(r.0).neg() } else { I(r.0) }
1551}
1552
1553impl Add for I {
1554    type Output = I;
1555    fn add(self, rhs: I) -> I {
1556        i_add(&self, &rhs)
1557    }
1558}
1559
1560impl Add for &I {
1561    type Output = I;
1562    fn add(self, rhs: &I) -> I {
1563        i_add(self, rhs)
1564    }
1565}
1566
1567impl Sub for I {
1568    type Output = I;
1569    fn sub(self, rhs: I) -> I {
1570        i_sub(&self, &rhs)
1571    }
1572}
1573
1574impl Sub for &I {
1575    type Output = I;
1576    fn sub(self, rhs: &I) -> I {
1577        i_sub(self, rhs)
1578    }
1579}
1580
1581impl Mul for I {
1582    type Output = I;
1583    fn mul(self, rhs: I) -> I {
1584        i_mul(&self, &rhs)
1585    }
1586}
1587
1588impl Mul for &I {
1589    type Output = I;
1590    fn mul(self, rhs: &I) -> I {
1591        i_mul(self, rhs)
1592    }
1593}
1594
1595impl Div for I {
1596    type Output = I;
1597    fn div(self, rhs: I) -> I {
1598        i_div(&self, &rhs)
1599    }
1600}
1601
1602impl Div for &I {
1603    type Output = I;
1604    fn div(self, rhs: &I) -> I {
1605        i_div(self, rhs)
1606    }
1607}
1608
1609impl Rem for I {
1610    type Output = I;
1611    fn rem(self, rhs: I) -> I {
1612        i_rem(&self, &rhs)
1613    }
1614}
1615
1616impl Eq for I {}
1617
1618impl PartialOrd for I {
1619    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1620        Some(self.cmp(other))
1621    }
1622}
1623
1624impl Ord for I {
1625    fn cmp(&self, other: &Self) -> Ordering {
1626        let self_sign = self.0[0] & 0x80;
1627        let other_sign = other.0[0] & 0x80;
1628        match (self_sign, other_sign) {
1629            (0, 0x80) => Ordering::Greater,
1630            (0x80, 0) => Ordering::Less,
1631            _ => self.0.cmp(&other.0),
1632        }
1633    }
1634}
1635
1636impl Rem for &I {
1637    type Output = I;
1638    fn rem(self, rhs: &I) -> I {
1639        i_rem(self, rhs)
1640    }
1641}
1642
1643impl I {
1644    pub const ZERO: Self = I([0u8; 32]);
1645
1646    pub const ONE: Self = I([
1647        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,
1648        0, 1,
1649    ]);
1650}
1651
1652impl Zero for I {
1653    fn zero() -> Self {
1654        I::ZERO
1655    }
1656    fn is_zero(&self) -> bool {
1657        self.0.iter().all(|&b| b == 0)
1658    }
1659}
1660
1661impl Default for I {
1662    fn default() -> Self {
1663        I::ZERO
1664    }
1665}
1666
1667impl One for I {
1668    fn one() -> Self {
1669        I::ONE
1670    }
1671}
1672
1673#[test]
1674fn test_is_zeroes() {
1675    assert!(U::ZERO.is_zero());
1676    assert!(U::ONE.is_some());
1677    assert!(I::ZERO.is_zero());
1678    assert!(I::ONE.is_some());
1679}
1680
1681#[cfg(all(
1682    test,
1683    feature = "alloy-enabled",
1684    feature = "proptest",
1685    feature = "std",
1686    not(target_arch = "wasm32")
1687))]
1688mod test {
1689    use proptest::prelude::*;
1690
1691    use super::*;
1692
1693    fn strat_any_u256() -> impl Strategy<Value = U256> {
1694        // Arbitrary seems to be having some issues with U256:
1695        any::<[u8; 32]>().prop_map(U256::from_be_bytes)
1696    }
1697
1698    proptest! {
1699        #[test]
1700        fn wrapping_div_b_zero_denominator_yields_zero(numerator in any::<[u8; 4]>()) {
1701            let zero = [0u8; 4];
1702            prop_assert_eq!(wrapping_div_quo_rem_b::<4>(&numerator, &zero).0, zero);
1703        }
1704
1705        #[test]
1706        fn wrapping_div_b_matches_integer_division(
1707            numerator in any::<[u8; 4]>(),
1708            denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1709        ) {
1710            let numerator_u32 = u32::from_be_bytes(numerator);
1711            let denominator_u32 = u32::from_be_bytes(denominator);
1712            let expected = numerator_u32 / denominator_u32;
1713            prop_assert_eq!(
1714                wrapping_div_quo_rem_b::<4>(&numerator, &denominator).0,
1715                expected.to_be_bytes()
1716            );
1717        }
1718
1719        #[test]
1720        fn wrapping_mod_b_matches_integer_modulo(
1721            numerator in any::<[u8; 4]>(),
1722            denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1723        ) {
1724            let numerator_u32 = u32::from_be_bytes(numerator);
1725            let denominator_u32 = u32::from_be_bytes(denominator);
1726            let expected = numerator_u32 % denominator_u32;
1727            prop_assert_eq!(
1728                wrapping_div_quo_rem_b::<4>(&numerator, &denominator).1,
1729                expected.to_be_bytes()
1730            );
1731        }
1732
1733        #[test]
1734        fn wrapping_add_b_handles_carry(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1735            let lhs_u32 = u32::from_be_bytes(lhs);
1736            let rhs_u32 = u32::from_be_bytes(rhs);
1737            let expected = lhs_u32.wrapping_add(rhs_u32);
1738            prop_assert_eq!(wrapping_add_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1739        }
1740
1741        #[test]
1742        fn wrapping_sub_b_handles_borrow(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1743            let lhs_u32 = u32::from_be_bytes(lhs);
1744            let rhs_u32 = u32::from_be_bytes(rhs);
1745            let expected = lhs_u32.wrapping_sub(rhs_u32);
1746            prop_assert_eq!(wrapping_sub_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1747        }
1748
1749        #[test]
1750        fn wrapping_mul_b_matches_wrapping_arithmetic(lhs in any::<[u8; 32]>(), rhs in any::<[u8; 32]>()) {
1751            let lhs_u = U::from(lhs);
1752            let rhs_u = U::from(rhs);
1753            let expected = lhs_u.wrapping_mul(&rhs_u);
1754            prop_assert_eq!(wrapping_mul_b::<32>(&lhs, &rhs), expected.0);
1755        }
1756
1757        #[test]
1758        fn const_wrapping_div_agrees_with_wrapping_div_b(
1759            numerator in any::<[u8; 32]>(),
1760            denominator in any::<[u8; 32]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 32])
1761        ) {
1762            let numerator_u = U::from(numerator);
1763            let denominator_u = U::from(denominator);
1764            prop_assert_eq!(
1765                const_wrapping_div(&numerator_u, &denominator_u).0,
1766                wrapping_div_quo_rem_b::<32>(&numerator, &denominator).0
1767            );
1768        }
1769
1770        #[test]
1771        fn u_predicates_track_zero_and_true(bytes in any::<[u8; 32]>()) {
1772            let value = U::from(bytes);
1773            let is_zero = bytes.iter().all(|&b| b == 0);
1774            prop_assert_eq!(value.is_zero(), is_zero);
1775            prop_assert_eq!(value.is_some(), !is_zero);
1776            prop_assert_eq!(value.is_true(), bytes[31] == 1);
1777        }
1778
1779        #[test]
1780        fn test_u_is_zero(x in any::<[u8; 32]>()) {
1781            let x = U::from(x);
1782            let ex = U256::from_be_bytes(x.0);
1783            assert_eq!(ex.is_zero(), x.is_zero());
1784        }
1785
1786        #[test]
1787        fn test_u_div(x in any::<U>(), y in any::<U>()) {
1788            let ex = U256::from_be_bytes(x.0);
1789            let ey = U256::from_be_bytes(y.0);
1790            assert_eq!((ex.wrapping_div(ey)).to_be_bytes(), x.wrapping_div(&y).0);
1791        }
1792
1793        #[test]
1794        fn test_u_mul(x in any::<U>(), y in any::<U>()) {
1795            let ex = U256::from_be_bytes(x.0);
1796            let ey = U256::from_be_bytes(y.0);
1797            assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), wrapping_mul(&x,  &y).0);
1798        }
1799
1800        #[test]
1801        fn test_u_mod(x in any::<U>(), y in any::<U>()) {
1802            let ex = U256::from_be_bytes(x.0);
1803            let ey = U256::from_be_bytes(y.0);
1804            assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1805        }
1806
1807        #[test]
1808        fn test_u_add(x in any::<U>(), y in any::<U>()) {
1809            let ex = U256::from_be_bytes(x.0);
1810            let ey = U256::from_be_bytes(y.0);
1811            let e = U::from(ex.wrapping_add(ey).to_be_bytes::<32>());
1812            assert_eq!(e, x.wrapping_add(&y), "{e} != {}", x + y);
1813        }
1814
1815        #[test]
1816        fn test_u_sub(x in any::<U>(), y in any::<U>()) {
1817            let ex = U256::from_be_bytes(x.0);
1818            let ey = U256::from_be_bytes(y.0);
1819            assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), x.wrapping_sub(&y).0);
1820        }
1821
1822        #[test]
1823        fn test_u_cmp(x in any::<U>(), y in any::<U>()) {
1824            let ex = U256::from_be_bytes(x.0);
1825            let ey = U256::from_be_bytes(y.0);
1826            assert_eq!(ex.cmp(&ey), x.cmp(&y));
1827        }
1828
1829        #[test]
1830        fn test_u_to_str(x in any::<U>()) {
1831            assert_eq!(U256::from_be_bytes(x.0).to_string(), x.to_string());
1832        }
1833
1834        #[test]
1835        fn test_u_shl(x in any::<U>(), i in any::<usize>()) {
1836            let l = U((U256::from_be_bytes(x.0) << i).to_be_bytes::<32>());
1837            assert_eq!(l, x << i);
1838        }
1839
1840        #[test]
1841        fn test_u_shr(x in any::<U>(), i in any::<usize>()) {
1842            let l = U((U256::from_be_bytes(x.0) >> i).to_be_bytes::<32>());
1843            assert_eq!(l, x >> i);
1844        }
1845
1846        #[test]
1847        fn test_trailing_zeros(x in any::<U>()) {
1848            assert_eq!(U256::from_be_bytes(x.0).trailing_zeros(), x.trailing_zeros());
1849        }
1850
1851        #[test]
1852        fn test_i_is_zero(x in any::<U>()) {
1853            let ex = I256::from_be_bytes(x.0);
1854            assert_eq!(ex.is_zero(), x.is_zero());
1855        }
1856
1857        #[test]
1858        fn test_i_div(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 / ey).to_be_bytes(), (x / y).0);
1862        }
1863
1864        #[test]
1865        fn test_i_mul(x in any::<I>(), y in any::<I>()) {
1866            let ex = I256::from_be_bytes(x.0);
1867            let ey = I256::from_be_bytes(y.0);
1868            assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), (x * y).0);
1869        }
1870
1871        #[test]
1872        fn test_i_mod(x in any::<I>(), y in any::<I>()) {
1873            let ex = I256::from_be_bytes(x.0);
1874            let ey = I256::from_be_bytes(y.0);
1875            assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1876        }
1877
1878        #[test]
1879        fn test_i_add(x in any::<I>(), y in any::<I>()) {
1880            let ex = I256::from_be_bytes(x.0);
1881            let ey = I256::from_be_bytes(y.0);
1882            assert_eq!((ex.wrapping_add(ey)).to_be_bytes(), (x + y).0);
1883        }
1884
1885        #[test]
1886        fn test_i_sub(x in any::<I>(), y in any::<I>()) {
1887            let ex = I256::from_be_bytes(x.0);
1888            let ey = I256::from_be_bytes(y.0);
1889            assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), (x - y).0);
1890        }
1891
1892        #[test]
1893        fn test_i_cmp(x in any::<I>(), y in any::<I>()) {
1894            let ex = I256::from_be_bytes(x.0);
1895            let ey = I256::from_be_bytes(y.0);
1896            assert_eq!(ex.cmp(&ey), x.cmp(&y));
1897        }
1898
1899        #[test]
1900        fn test_u_u8(x in any::<u8>()) {
1901            let mut b = [0u8; 32];
1902            b[32-size_of::<u8>()..].copy_from_slice(&x.to_be_bytes());
1903            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1904        }
1905
1906        #[test]
1907        fn test_u_u16(x in any::<u16>()) {
1908            let mut b = [0u8; 32];
1909            b[32-size_of::<u16>()..].copy_from_slice(&x.to_be_bytes());
1910            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1911        }
1912
1913        #[test]
1914        fn test_u_u32(x in any::<u32>()) {
1915            let mut b = [0u8; 32];
1916            b[32-size_of::<u32>()..].copy_from_slice(&x.to_be_bytes());
1917            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1918        }
1919
1920        #[test]
1921        fn test_u_u64(x in any::<u64>()) {
1922            let mut b = [0u8; 32];
1923            b[32-size_of::<u64>()..].copy_from_slice(&x.to_be_bytes());
1924            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1925        }
1926
1927        #[test]
1928        fn test_u_u128(x in any::<u128>()) {
1929            let mut b = [0u8; 32];
1930            b[32-size_of::<u128>()..].copy_from_slice(&x.to_be_bytes());
1931            assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1932        }
1933
1934        #[test]
1935        fn test_to_and_from_addrs(x in any::<Address>()) {
1936            let y: Address = U::from(x).into();
1937            assert_eq!(x, y)
1938        }
1939
1940        #[test]
1941        fn test_u_conv_to_and_from_u8(x in any::<u8>()) {
1942            assert_eq!(x.wrapping_add(1), U::from(x).wrapping_add(&U::ONE).into());
1943        }
1944
1945        #[test]
1946        fn test_print_to_and_from(x in any::<[u8; 32]>()) {
1947            let e = format!("{}", U256::from_be_bytes(x));
1948            let v = format!("{}", U(x));
1949            assert_eq!(e, v);
1950        }
1951
1952        #[test]
1953        fn test_u_from_str(x in strat_any_u256()) {
1954            let v = U::from_str(x.to_string().as_str()).unwrap();
1955            assert_eq!(
1956                U::from(x.to_be_bytes::<32>()),
1957                v,
1958                "{x} != {v}",
1959            )
1960        }
1961
1962        #[test]
1963        fn array_truncate(x in any::<[u8; 20]>()) {
1964            assert_eq!(x, U::from(x).const_addr());
1965        }
1966    }
1967}