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