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