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