Skip to main content

bobcat_maths/
lib.rs

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