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