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