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