Skip to main content

bobcat_maths/
lib.rs

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