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