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