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