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 impl From<$t> for U {
1194 fn from(x: $t) -> Self {
1195 let mut b = [0u8; 32];
1196 b[32 - core::mem::size_of::<$t>()..].copy_from_slice(&x.to_be_bytes());
1197 U(b)
1198 }
1199 }
1200
1201 impl From<U> for $t {
1202 fn from(x: U) -> Self {
1203 Self::from_be_bytes(x.into())
1204 }
1205 }
1206 )+
1207 };
1208}
1209
1210from_ints! { u8, u16, u32, u64, u128, usize }
1211
1212impl From<I> for [u8; 32] {
1213 fn from(x: I) -> Self {
1214 x.0
1215 }
1216}
1217
1218impl From<[u8; 32]> for I {
1219 fn from(x: [u8; 32]) -> Self {
1220 I(x)
1221 }
1222}
1223
1224fn i_add(x: &I, y: &I) -> I {
1225 I(wrapping_add(&U(x.0), &U(y.0)).0)
1226}
1227
1228fn i_sub(x: &I, y: &I) -> I {
1229 I(wrapping_sub(&U(x.0), &U(y.0)).0)
1230}
1231
1232fn i_mul(x: &I, y: &I) -> I {
1233 let result = wrapping_mul(&U(x.0), &U(y.0));
1234 I(result.0)
1235}
1236
1237fn i_div(x: &I, y: &I) -> I {
1238 let r = wrapping_div(&x.abs(), &y.abs());
1239 if x.is_neg() ^ y.is_neg() {
1240 I(r.0).neg()
1241 } else {
1242 I(r.0)
1243 }
1244}
1245
1246fn i_rem(x: &I, y: &I) -> I {
1247 let r = modd(&x.abs(), &y.abs());
1248 if x.is_neg() {
1249 I(r.0).neg()
1250 } else {
1251 I(r.0)
1252 }
1253}
1254
1255impl Add for I {
1256 type Output = I;
1257 fn add(self, rhs: I) -> I {
1258 i_add(&self, &rhs)
1259 }
1260}
1261
1262impl Add for &I {
1263 type Output = I;
1264 fn add(self, rhs: &I) -> I {
1265 i_add(self, rhs)
1266 }
1267}
1268
1269impl Sub for I {
1270 type Output = I;
1271 fn sub(self, rhs: I) -> I {
1272 i_sub(&self, &rhs)
1273 }
1274}
1275
1276impl Sub for &I {
1277 type Output = I;
1278 fn sub(self, rhs: &I) -> I {
1279 i_sub(self, rhs)
1280 }
1281}
1282
1283impl Mul for I {
1284 type Output = I;
1285 fn mul(self, rhs: I) -> I {
1286 i_mul(&self, &rhs)
1287 }
1288}
1289
1290impl Mul for &I {
1291 type Output = I;
1292 fn mul(self, rhs: &I) -> I {
1293 i_mul(self, rhs)
1294 }
1295}
1296
1297impl Div for I {
1298 type Output = I;
1299 fn div(self, rhs: I) -> I {
1300 i_div(&self, &rhs)
1301 }
1302}
1303
1304impl Div for &I {
1305 type Output = I;
1306 fn div(self, rhs: &I) -> I {
1307 i_div(self, rhs)
1308 }
1309}
1310
1311impl Rem for I {
1312 type Output = I;
1313 fn rem(self, rhs: I) -> I {
1314 i_rem(&self, &rhs)
1315 }
1316}
1317
1318impl Eq for I {}
1319
1320impl PartialOrd for I {
1321 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1322 Some(self.cmp(other))
1323 }
1324}
1325
1326impl Ord for I {
1327 fn cmp(&self, other: &Self) -> Ordering {
1328 let self_sign = self.0[0] & 0x80;
1329 let other_sign = other.0[0] & 0x80;
1330 match (self_sign, other_sign) {
1331 (0, 0x80) => Ordering::Greater,
1332 (0x80, 0) => Ordering::Less,
1333 _ => self.0.cmp(&other.0),
1334 }
1335 }
1336}
1337
1338impl Rem for &I {
1339 type Output = I;
1340 fn rem(self, rhs: &I) -> I {
1341 i_rem(self, rhs)
1342 }
1343}
1344
1345impl I {
1346 pub const ZERO: Self = I([0u8; 32]);
1347
1348 pub const ONE: Self = I([
1349 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,
1350 0, 1,
1351 ]);
1352}
1353
1354impl Zero for I {
1355 fn zero() -> Self {
1356 I::ZERO
1357 }
1358 fn is_zero(&self) -> bool {
1359 self.0.iter().all(|&b| b == 0)
1360 }
1361}
1362
1363impl Default for I {
1364 fn default() -> Self {
1365 I::ZERO
1366 }
1367}
1368
1369impl One for I {
1370 fn one() -> Self {
1371 I::ONE
1372 }
1373}
1374
1375#[test]
1376fn test_is_zeroes() {
1377 assert!(U::ZERO.is_zero());
1378 assert!(U::ONE.is_some());
1379 assert!(I::ZERO.is_zero());
1380 assert!(I::ONE.is_some());
1381}
1382
1383#[cfg(all(
1384 test,
1385 feature = "alloy-enabled",
1386 feature = "proptest-enabled",
1387 feature = "std",
1388 not(target_arch = "wasm32")
1389))]
1390mod test {
1391 use proptest::prelude::*;
1392
1393 use super::*;
1394
1395 proptest! {
1396 #[test]
1397 fn wrapping_div_b_zero_denominator_yields_zero(numerator in any::<[u8; 4]>()) {
1398 let zero = [0u8; 4];
1399 prop_assert_eq!(wrapping_div_quo_rem_b::<4>(&numerator, &zero).0, zero);
1400 }
1401
1402 #[test]
1403 fn wrapping_div_b_matches_integer_division(
1404 numerator in any::<[u8; 4]>(),
1405 denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1406 ) {
1407 let numerator_u32 = u32::from_be_bytes(numerator);
1408 let denominator_u32 = u32::from_be_bytes(denominator);
1409 let expected = numerator_u32 / denominator_u32;
1410 prop_assert_eq!(
1411 wrapping_div_quo_rem_b::<4>(&numerator, &denominator).0,
1412 expected.to_be_bytes()
1413 );
1414 }
1415
1416 #[test]
1417 fn wrapping_mod_b_matches_integer_modulo(
1418 numerator in any::<[u8; 4]>(),
1419 denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1420 ) {
1421 let numerator_u32 = u32::from_be_bytes(numerator);
1422 let denominator_u32 = u32::from_be_bytes(denominator);
1423 let expected = numerator_u32 % denominator_u32;
1424 prop_assert_eq!(
1425 wrapping_div_quo_rem_b::<4>(&numerator, &denominator).1,
1426 expected.to_be_bytes()
1427 );
1428 }
1429
1430 #[test]
1431 fn wrapping_add_b_handles_carry(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1432 let lhs_u32 = u32::from_be_bytes(lhs);
1433 let rhs_u32 = u32::from_be_bytes(rhs);
1434 let expected = lhs_u32.wrapping_add(rhs_u32);
1435 prop_assert_eq!(wrapping_add_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1436 }
1437
1438 #[test]
1439 fn wrapping_sub_b_handles_borrow(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1440 let lhs_u32 = u32::from_be_bytes(lhs);
1441 let rhs_u32 = u32::from_be_bytes(rhs);
1442 let expected = lhs_u32.wrapping_sub(rhs_u32);
1443 prop_assert_eq!(wrapping_sub_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1444 }
1445
1446 #[test]
1447 fn wrapping_mul_b_matches_wrapping_arithmetic(lhs in any::<[u8; 32]>(), rhs in any::<[u8; 32]>()) {
1448 let lhs_u = U::from(lhs);
1449 let rhs_u = U::from(rhs);
1450 let expected = lhs_u.wrapping_mul(&rhs_u);
1451 prop_assert_eq!(wrapping_mul_b::<32>(&lhs, &rhs), expected.0);
1452 }
1453
1454 #[test]
1455 fn const_wrapping_div_agrees_with_wrapping_div_b(
1456 numerator in any::<[u8; 32]>(),
1457 denominator in any::<[u8; 32]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 32])
1458 ) {
1459 let numerator_u = U::from(numerator);
1460 let denominator_u = U::from(denominator);
1461 prop_assert_eq!(
1462 const_wrapping_div(&numerator_u, &denominator_u).0,
1463 wrapping_div_quo_rem_b::<32>(&numerator, &denominator).0
1464 );
1465 }
1466
1467 #[test]
1468 fn u_predicates_track_zero_and_true(bytes in any::<[u8; 32]>()) {
1469 let value = U::from(bytes);
1470 let is_zero = bytes.iter().all(|&b| b == 0);
1471 prop_assert_eq!(value.is_zero(), is_zero);
1472 prop_assert_eq!(value.is_some(), !is_zero);
1473 prop_assert_eq!(value.is_true(), bytes[31] == 1);
1474 }
1475
1476 #[test]
1477 fn test_u_is_zero(x in any::<[u8; 32]>()) {
1478 let x = U::from(x);
1479 let ex = U256::from_be_bytes(x.0);
1480 assert_eq!(ex.is_zero(), x.is_zero());
1481 }
1482
1483 #[test]
1484 fn test_u_div(x in any::<U>(), y in any::<U>()) {
1485 let ex = U256::from_be_bytes(x.0);
1486 let ey = U256::from_be_bytes(y.0);
1487 assert_eq!((ex.wrapping_div(ey)).to_be_bytes(), x.wrapping_div(&y).0);
1488 }
1489
1490 #[test]
1491 fn test_u_mul(x in any::<U>(), y in any::<U>()) {
1492 let ex = U256::from_be_bytes(x.0);
1493 let ey = U256::from_be_bytes(y.0);
1494 assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), wrapping_mul(&x, &y).0);
1495 }
1496
1497 #[test]
1498 fn test_u_mod(x in any::<U>(), y in any::<U>()) {
1499 let ex = U256::from_be_bytes(x.0);
1500 let ey = U256::from_be_bytes(y.0);
1501 assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1502 }
1503
1504 #[test]
1505 fn test_u_add(x in any::<U>(), y in any::<U>()) {
1506 let ex = U256::from_be_bytes(x.0);
1507 let ey = U256::from_be_bytes(y.0);
1508 let e = U::from(ex.wrapping_add(ey).to_be_bytes::<32>());
1509 assert_eq!(e, x.wrapping_add(&y), "{e} != {}", x + y);
1510 }
1511
1512 #[test]
1513 fn test_u_sub(x in any::<U>(), y in any::<U>()) {
1514 let ex = U256::from_be_bytes(x.0);
1515 let ey = U256::from_be_bytes(y.0);
1516 assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), x.wrapping_sub(&y).0);
1517 }
1518
1519 #[test]
1520 fn test_u_cmp(x in any::<U>(), y in any::<U>()) {
1521 let ex = U256::from_be_bytes(x.0);
1522 let ey = U256::from_be_bytes(y.0);
1523 assert_eq!(ex.cmp(&ey), x.cmp(&y));
1524 }
1525
1526 #[test]
1527 #[cfg(feature = "alloc")]
1528 fn test_u_str(x in any::<U>()) {
1529 assert_eq!(U256::from_be_bytes(x.0).to_string(), x.to_string());
1530 }
1531
1532 #[test]
1533 fn test_u_shl(x in any::<U>(), i in any::<usize>()) {
1534 let l = U((U256::from_be_bytes(x.0) << i).to_be_bytes::<32>());
1535 assert_eq!(l, x << i);
1536 }
1537
1538 #[test]
1539 fn test_u_shr(x in any::<U>(), i in any::<usize>()) {
1540 let l = U((U256::from_be_bytes(x.0) >> i).to_be_bytes::<32>());
1541 assert_eq!(l, x >> i);
1542 }
1543
1544 #[test]
1545 fn test_trailing_zeros(x in any::<U>()) {
1546 assert_eq!(U256::from_be_bytes(x.0).trailing_zeros(), x.trailing_zeros());
1547 }
1548
1549 #[test]
1550 fn test_i_is_zero(x in any::<U>()) {
1551 let ex = I256::from_be_bytes(x.0);
1552 assert_eq!(ex.is_zero(), x.is_zero());
1553 }
1554
1555 #[test]
1556 fn test_i_div(x in any::<I>(), y in any::<I>()) {
1557 let ex = I256::from_be_bytes(x.0);
1558 let ey = I256::from_be_bytes(y.0);
1559 assert_eq!((ex / ey).to_be_bytes(), (x / y).0);
1560 }
1561
1562 #[test]
1563 fn test_i_mul(x in any::<I>(), y in any::<I>()) {
1564 let ex = I256::from_be_bytes(x.0);
1565 let ey = I256::from_be_bytes(y.0);
1566 assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), (x * y).0);
1567 }
1568
1569 #[test]
1570 fn test_i_mod(x in any::<I>(), y in any::<I>()) {
1571 let ex = I256::from_be_bytes(x.0);
1572 let ey = I256::from_be_bytes(y.0);
1573 assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1574 }
1575
1576 #[test]
1577 fn test_i_add(x in any::<I>(), y in any::<I>()) {
1578 let ex = I256::from_be_bytes(x.0);
1579 let ey = I256::from_be_bytes(y.0);
1580 assert_eq!((ex.wrapping_add(ey)).to_be_bytes(), (x + y).0);
1581 }
1582
1583 #[test]
1584 fn test_i_sub(x in any::<I>(), y in any::<I>()) {
1585 let ex = I256::from_be_bytes(x.0);
1586 let ey = I256::from_be_bytes(y.0);
1587 assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), (x - y).0);
1588 }
1589
1590 #[test]
1591 fn test_i_cmp(x in any::<I>(), y in any::<I>()) {
1592 let ex = I256::from_be_bytes(x.0);
1593 let ey = I256::from_be_bytes(y.0);
1594 assert_eq!(ex.cmp(&ey), x.cmp(&y));
1595 }
1596
1597 #[test]
1598 fn test_u_u8(x in any::<u8>()) {
1599 let mut b = [0u8; 32];
1600 b[32-std::mem::size_of::<u8>()..].copy_from_slice(&x.to_be_bytes());
1601 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1602 }
1603
1604 #[test]
1605 fn test_u_u16(x in any::<u16>()) {
1606 let mut b = [0u8; 32];
1607 b[32-std::mem::size_of::<u16>()..].copy_from_slice(&x.to_be_bytes());
1608 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1609 }
1610
1611 #[test]
1612 fn test_u_u32(x in any::<u32>()) {
1613 let mut b = [0u8; 32];
1614 b[32-std::mem::size_of::<u32>()..].copy_from_slice(&x.to_be_bytes());
1615 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1616 }
1617
1618 #[test]
1619 fn test_u_u64(x in any::<u64>()) {
1620 let mut b = [0u8; 32];
1621 b[32-std::mem::size_of::<u64>()..].copy_from_slice(&x.to_be_bytes());
1622 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1623 }
1624
1625 #[test]
1626 fn test_u_u128(x in any::<u128>()) {
1627 let mut b = [0u8; 32];
1628 b[32-std::mem::size_of::<u128>()..].copy_from_slice(&x.to_be_bytes());
1629 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1630 }
1631
1632 #[test]
1633 fn test_to_and_from_addrs(x in any::<Address>()) {
1634 let y: Address = U::from(x).into();
1635 assert_eq!(x, y)
1636 }
1637
1638 #[test]
1639 fn test_u_conv_to_and_from_u8(x in any::<u8>()) {
1640 assert_eq!(x.wrapping_add(1), U::from(x).wrapping_add(&U::ONE).into());
1641 }
1642 }
1643}