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