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