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 pub fn addr(self) -> [u8; 20] {
1118 self.into()
1119 }
1120
1121 #[cfg(feature = "alloc")]
1122 pub fn as_vec(self) -> Vec<u8> {
1123 self.0.to_vec()
1124 }
1125
1126 pub fn checked_add_opt(&self, y: &Self) -> Option<Self> {
1127 checked_add_opt(self, y)
1128 }
1129
1130 pub fn checked_add(&self, y: &Self) -> Self {
1131 checked_add(self, y)
1132 }
1133
1134 pub fn checked_mul_opt(&self, y: &Self) -> Option<Self> {
1135 checked_mul_opt(self, y)
1136 }
1137
1138 pub fn checked_mul(&self, y: &Self) -> Self {
1139 checked_mul(self, y)
1140 }
1141
1142 pub fn checked_sub_opt(&self, y: &Self) -> Option<Self> {
1143 checked_sub_opt(self, y)
1144 }
1145
1146 pub fn checked_sub(&self, y: &Self) -> Self {
1147 checked_sub(self, y)
1148 }
1149
1150 pub fn checked_div_opt(&self, y: &Self) -> Option<Self> {
1151 checked_div_opt(self, y)
1152 }
1153
1154 pub fn checked_div(&self, y: &Self) -> Self {
1155 checked_div(self, y)
1156 }
1157
1158 pub fn checked_pow(&self, exp: &U) -> Option<Self> {
1159 checked_pow(self, exp)
1160 }
1161
1162 pub fn wrapping_add(&self, y: &Self) -> U {
1163 wrapping_add(self, y)
1164 }
1165
1166 pub fn wrapping_sub(&self, y: &Self) -> U {
1167 wrapping_sub(self, y)
1168 }
1169
1170 pub fn wrapping_mul(&self, y: &Self) -> U {
1171 wrapping_mul(self, y)
1172 }
1173
1174 pub fn wrapping_div(&self, y: &Self) -> U {
1175 wrapping_div(self, y)
1176 }
1177
1178 pub fn saturating_add(&self, y: &Self) -> U {
1179 saturating_add(self, y)
1180 }
1181
1182 pub fn saturating_sub(&self, y: &Self) -> U {
1183 saturating_sub(self, y)
1184 }
1185
1186 pub fn saturating_mul(&self, y: &Self) -> U {
1187 saturating_mul(self, y)
1188 }
1189
1190 pub fn saturating_div(&self, y: &Self) -> Self {
1191 saturating_div(self, y)
1192 }
1193
1194 pub fn wrapping_neg(self) -> Self {
1195 let mut x = self;
1196 let mut carry = 1u8;
1197 for b in x.iter_mut().rev() {
1198 *b = (!*b).wrapping_add(carry);
1199 carry = b.is_zero() as u8;
1200 }
1201 x
1202 }
1203
1204 pub fn mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1205 mul_div(self, y, z)
1206 }
1207
1208 pub fn mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1209 mul_div_round_up(self, y, z)
1210 }
1211
1212 pub fn widening_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1213 widening_mul_div(self, y, z)
1214 }
1215
1216 pub fn widening_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1217 widening_mul_div_round_up(self, y, z)
1218 }
1219
1220 #[cfg(feature = "ruint-enabled")]
1221 pub fn ruint_mul_div(&self, y: &Self, z: Self) -> Option<(Self, bool)> {
1222 ruint_mul_div(self, y, z)
1223 }
1224
1225 #[cfg(feature = "ruint-enabled")]
1226 pub fn ruint_mul_div_round_up(&self, y: &Self, z: Self) -> Option<Self> {
1227 ruint_mul_div_round_up(self, y, z)
1228 }
1229
1230 pub fn mul_mod(&self, y: &Self, z: &Self) -> Self {
1231 mul_mod(*self, y, z)
1232 }
1233
1234 pub fn add_mod(&self, y: &Self, z: &Self) -> Self {
1235 let mut b = self.0;
1236 unsafe { math_add_mod(b.as_mut_ptr(), y.as_ptr(), z.as_ptr()) }
1237 Self(b)
1238 }
1239
1240 pub fn checked_rooti(self, x: u32) -> Option<Self> {
1241 checked_rooti(self, x)
1242 }
1243
1244 pub fn from_hex(x: &str) -> Option<U> {
1245 match const_hex::decode_to_array::<_, 32>(x) {
1246 Ok(v) => Some(U(v)),
1247 Err(_) => None,
1248 }
1249 }
1250
1251 pub const fn const_from_hex(x: &[u8]) -> Option<U> {
1252 match const_hex::const_decode_to_array::<32>(x) {
1253 Ok(v) => Some(U(v)),
1254 Err(_) => None,
1255 }
1256 }
1257}
1258
1259impl Display for U {
1260 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
1261 if self.is_zero() {
1262 return write!(f, "0");
1263 }
1264 let mut result = [0u8; 78];
1265 let mut i = 0;
1266 for byte in self.0 {
1267 let mut carry = byte as u32;
1268 for digit in result[..i].iter_mut() {
1269 let temp = (*digit as u32) * 256 + carry;
1270 *digit = (temp % 10) as u8;
1271 carry = temp / 10;
1272 }
1273 while carry > 0 {
1274 result[i] = (carry % 10) as u8;
1275 i += 1;
1276 debug_assert!(78 >= i, "{} > {i}", result.len());
1277 carry /= 10;
1278 }
1279 }
1280 for &digit in result[..i].iter().rev() {
1281 write!(f, "{}", digit)?;
1282 }
1283 Ok(())
1284 }
1285}
1286
1287impl From<U> for [u8; 32] {
1288 fn from(x: U) -> Self {
1289 x.0
1290 }
1291}
1292
1293impl From<&U> for U {
1294 fn from(x: &U) -> Self {
1295 *x
1296 }
1297}
1298
1299impl From<U> for bool {
1300 fn from(x: U) -> Self {
1301 x.0[31] == 1
1302 }
1303}
1304
1305impl From<&[u8]> for U {
1306 fn from(x: &[u8]) -> Self {
1307 let x: &[u8; 32] = x.try_into().unwrap();
1308 (*x).into()
1309 }
1310}
1311
1312impl From<&[u8; 32]> for &U {
1313 fn from(x: &[u8; 32]) -> Self {
1314 unsafe { &*(x as *const [u8; 32] as *const U) }
1315 }
1316}
1317
1318impl From<[u8; 32]> for U {
1319 fn from(x: [u8; 32]) -> Self {
1320 U(x)
1321 }
1322}
1323
1324impl Deref for U {
1325 type Target = [u8; 32];
1326
1327 fn deref(&self) -> &Self::Target {
1328 &self.0
1329 }
1330}
1331
1332impl DerefMut for U {
1333 fn deref_mut(&mut self) -> &mut Self::Target {
1334 &mut self.0
1335 }
1336}
1337
1338impl From<bool> for U {
1339 fn from(x: bool) -> Self {
1340 U::from(&[x as u8])
1341 }
1342}
1343
1344impl Zero for U {
1345 fn zero() -> Self {
1346 U::ZERO
1347 }
1348
1349 fn is_zero(&self) -> bool {
1350 self.0.iter().all(|&b| b == 0)
1351 }
1352}
1353
1354impl Default for U {
1355 fn default() -> Self {
1356 U::ZERO
1357 }
1358}
1359
1360impl One for U {
1361 fn one() -> Self {
1362 U::ONE
1363 }
1364}
1365
1366impl Index<usize> for U {
1367 type Output = u8;
1368
1369 fn index(&self, index: usize) -> &Self::Output {
1370 &self.0[index]
1371 }
1372}
1373
1374impl IndexMut<usize> for U {
1375 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1376 &mut self.0[index]
1377 }
1378}
1379
1380impl I {
1381 fn is_neg(&self) -> bool {
1382 self.0[0] & 0x80 != 0
1383 }
1384
1385 pub fn is_zero(&self) -> bool {
1386 *self == Self::ZERO
1387 }
1388
1389 pub fn is_some(&self) -> bool {
1390 !self.is_zero()
1391 }
1392
1393 pub fn as_slice(&self) -> &[u8; 32] {
1394 &self.0
1395 }
1396
1397 fn neg(&self) -> Self {
1398 let x = wrapping_add(&U(self.0.map(|b| !b)), &U::ONE);
1399 I(x.0)
1400 }
1401
1402 fn abs(self) -> U {
1403 if self.is_neg() {
1404 U(self.neg().0)
1405 } else {
1406 U(self.0)
1407 }
1408 }
1409}
1410
1411macro_rules! from_slices {
1412 ($($n:expr),+ $(,)?) => {
1413 $(
1414 paste::paste! {
1415 impl From<&[u8; $n]> for U {
1416 fn from(x: &[u8; $n]) -> Self {
1417 let mut b = [0u8; 32];
1418 b[32 - $n..].copy_from_slice(x);
1419 U(b)
1420 }
1421 }
1422
1423 impl From<[u8; $n]> for U {
1424 fn from(x: [u8; $n]) -> Self {
1425 U::from(&x)
1426 }
1427 }
1428
1429 impl U {
1430 pub const fn [<const_ $n _slice>](self) -> [u8; $n] {
1431 let mut b = [0u8; $n];
1432 let mut i = 0;
1433 while i < $n {
1434 b[i] = self.0[32-$n+i];
1435 i += 1;
1436 }
1437 b
1438 }
1439 }
1440
1441 impl From<U> for [u8; $n] {
1442 fn from(x: U) -> Self {
1443 unsafe { *(x.as_ptr().add(32 - $n) as *const [u8; $n]) }
1444 }
1445 }
1446 }
1447 )+
1448 };
1449}
1450
1451from_slices!(
1452 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,
1453 27, 28, 29, 30, 31
1454);
1455
1456impl From<&U> for Address {
1457 fn from(x: &U) -> Self {
1458 (*x).into()
1459 }
1460}
1461
1462macro_rules! from_ints {
1463 ($($t:ty),+ $(,)?) => {
1464 $(
1465 paste::paste! {
1466 impl U {
1467 pub const fn [<from_ $t>](x: $t) -> U {
1468 U(array_concat::concat_arrays!(
1469 [0u8; 32-core::mem::size_of::<$t>()],
1470 x.to_be_bytes())
1471 )
1472 }
1473 }
1474
1475 impl From<$t> for U {
1476 fn from(x: $t) -> Self {
1477 U::[<from_ $t>](x)
1478 }
1479 }
1480
1481 impl From<U> for $t {
1482 fn from(x: U) -> Self {
1483 Self::from_be_bytes(x.into())
1484 }
1485 }
1486
1487 impl PartialEq<$t> for U {
1488 fn eq(&self, rhs: &$t) -> bool {
1489 *self == U::from(*rhs)
1490 }
1491 }
1492
1493 impl PartialOrd<$t> for U {
1494 fn partial_cmp(&self, rhs: &$t) -> Option<Ordering> {
1495 let rhs = rhs.to_be_bytes();
1496 let n = core::mem::size_of::<$t>();
1497 let split = 32 - n;
1498 if self.0[..split].iter().any(|&b| b != 0) {
1499 return Some(Ordering::Greater);
1500 }
1501 Some(self.0[split..].cmp(&rhs))
1502 }
1503 }
1504 }
1505 )+
1506 };
1507}
1508
1509#[macro_export]
1510macro_rules! u {
1511 ($e:expr) => {
1512 $crate::U::from_u32($e)
1513 };
1514}
1515
1516from_ints! { u8, u16, u32, u64, u128, usize }
1517
1518impl From<I> for [u8; 32] {
1519 fn from(x: I) -> Self {
1520 x.0
1521 }
1522}
1523
1524impl From<[u8; 32]> for I {
1525 fn from(x: [u8; 32]) -> Self {
1526 I(x)
1527 }
1528}
1529
1530fn i_add(x: &I, y: &I) -> I {
1531 I(wrapping_add(&U(x.0), &U(y.0)).0)
1532}
1533
1534fn i_sub(x: &I, y: &I) -> I {
1535 I(wrapping_sub(&U(x.0), &U(y.0)).0)
1536}
1537
1538fn i_mul(x: &I, y: &I) -> I {
1539 let result = wrapping_mul(&U(x.0), &U(y.0));
1540 I(result.0)
1541}
1542
1543fn i_div(x: &I, y: &I) -> I {
1544 let r = wrapping_div(&x.abs(), &y.abs());
1545 if x.is_neg() ^ y.is_neg() {
1546 I(r.0).neg()
1547 } else {
1548 I(r.0)
1549 }
1550}
1551
1552fn i_rem(x: &I, y: &I) -> I {
1553 let r = modd(&x.abs(), &y.abs());
1554 if x.is_neg() { I(r.0).neg() } else { I(r.0) }
1555}
1556
1557impl Add for I {
1558 type Output = I;
1559 fn add(self, rhs: I) -> I {
1560 i_add(&self, &rhs)
1561 }
1562}
1563
1564impl Add for &I {
1565 type Output = I;
1566 fn add(self, rhs: &I) -> I {
1567 i_add(self, rhs)
1568 }
1569}
1570
1571impl Sub for I {
1572 type Output = I;
1573 fn sub(self, rhs: I) -> I {
1574 i_sub(&self, &rhs)
1575 }
1576}
1577
1578impl Sub for &I {
1579 type Output = I;
1580 fn sub(self, rhs: &I) -> I {
1581 i_sub(self, rhs)
1582 }
1583}
1584
1585impl Mul for I {
1586 type Output = I;
1587 fn mul(self, rhs: I) -> I {
1588 i_mul(&self, &rhs)
1589 }
1590}
1591
1592impl Mul for &I {
1593 type Output = I;
1594 fn mul(self, rhs: &I) -> I {
1595 i_mul(self, rhs)
1596 }
1597}
1598
1599impl Div for I {
1600 type Output = I;
1601 fn div(self, rhs: I) -> I {
1602 i_div(&self, &rhs)
1603 }
1604}
1605
1606impl Div for &I {
1607 type Output = I;
1608 fn div(self, rhs: &I) -> I {
1609 i_div(self, rhs)
1610 }
1611}
1612
1613impl Rem for I {
1614 type Output = I;
1615 fn rem(self, rhs: I) -> I {
1616 i_rem(&self, &rhs)
1617 }
1618}
1619
1620impl Eq for I {}
1621
1622impl PartialOrd for I {
1623 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1624 Some(self.cmp(other))
1625 }
1626}
1627
1628impl Ord for I {
1629 fn cmp(&self, other: &Self) -> Ordering {
1630 let self_sign = self.0[0] & 0x80;
1631 let other_sign = other.0[0] & 0x80;
1632 match (self_sign, other_sign) {
1633 (0, 0x80) => Ordering::Greater,
1634 (0x80, 0) => Ordering::Less,
1635 _ => self.0.cmp(&other.0),
1636 }
1637 }
1638}
1639
1640impl Rem for &I {
1641 type Output = I;
1642 fn rem(self, rhs: &I) -> I {
1643 i_rem(self, rhs)
1644 }
1645}
1646
1647impl I {
1648 pub const ZERO: Self = I([0u8; 32]);
1649
1650 pub const ONE: Self = I([
1651 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,
1652 0, 1,
1653 ]);
1654}
1655
1656impl Zero for I {
1657 fn zero() -> Self {
1658 I::ZERO
1659 }
1660 fn is_zero(&self) -> bool {
1661 self.0.iter().all(|&b| b == 0)
1662 }
1663}
1664
1665impl Default for I {
1666 fn default() -> Self {
1667 I::ZERO
1668 }
1669}
1670
1671impl One for I {
1672 fn one() -> Self {
1673 I::ONE
1674 }
1675}
1676
1677#[test]
1678fn test_is_zeroes() {
1679 assert!(U::ZERO.is_zero());
1680 assert!(U::ONE.is_some());
1681 assert!(I::ZERO.is_zero());
1682 assert!(I::ONE.is_some());
1683}
1684
1685#[cfg(all(
1686 test,
1687 feature = "alloy-enabled",
1688 feature = "proptest",
1689 feature = "std",
1690 not(target_arch = "wasm32")
1691))]
1692mod test {
1693 use proptest::prelude::*;
1694
1695 use super::*;
1696
1697 fn strat_any_u256() -> impl Strategy<Value = U256> {
1698 any::<[u8; 32]>().prop_map(U256::from_be_bytes)
1700 }
1701
1702 proptest! {
1703 #[test]
1704 fn wrapping_div_b_zero_denominator_yields_zero(numerator in any::<[u8; 4]>()) {
1705 let zero = [0u8; 4];
1706 prop_assert_eq!(wrapping_div_quo_rem_b::<4>(&numerator, &zero).0, zero);
1707 }
1708
1709 #[test]
1710 fn wrapping_div_b_matches_integer_division(
1711 numerator in any::<[u8; 4]>(),
1712 denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1713 ) {
1714 let numerator_u32 = u32::from_be_bytes(numerator);
1715 let denominator_u32 = u32::from_be_bytes(denominator);
1716 let expected = numerator_u32 / denominator_u32;
1717 prop_assert_eq!(
1718 wrapping_div_quo_rem_b::<4>(&numerator, &denominator).0,
1719 expected.to_be_bytes()
1720 );
1721 }
1722
1723 #[test]
1724 fn wrapping_mod_b_matches_integer_modulo(
1725 numerator in any::<[u8; 4]>(),
1726 denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1727 ) {
1728 let numerator_u32 = u32::from_be_bytes(numerator);
1729 let denominator_u32 = u32::from_be_bytes(denominator);
1730 let expected = numerator_u32 % denominator_u32;
1731 prop_assert_eq!(
1732 wrapping_div_quo_rem_b::<4>(&numerator, &denominator).1,
1733 expected.to_be_bytes()
1734 );
1735 }
1736
1737 #[test]
1738 fn wrapping_add_b_handles_carry(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1739 let lhs_u32 = u32::from_be_bytes(lhs);
1740 let rhs_u32 = u32::from_be_bytes(rhs);
1741 let expected = lhs_u32.wrapping_add(rhs_u32);
1742 prop_assert_eq!(wrapping_add_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1743 }
1744
1745 #[test]
1746 fn wrapping_sub_b_handles_borrow(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1747 let lhs_u32 = u32::from_be_bytes(lhs);
1748 let rhs_u32 = u32::from_be_bytes(rhs);
1749 let expected = lhs_u32.wrapping_sub(rhs_u32);
1750 prop_assert_eq!(wrapping_sub_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1751 }
1752
1753 #[test]
1754 fn wrapping_mul_b_matches_wrapping_arithmetic(lhs in any::<[u8; 32]>(), rhs in any::<[u8; 32]>()) {
1755 let lhs_u = U::from(lhs);
1756 let rhs_u = U::from(rhs);
1757 let expected = lhs_u.wrapping_mul(&rhs_u);
1758 prop_assert_eq!(wrapping_mul_b::<32>(&lhs, &rhs), expected.0);
1759 }
1760
1761 #[test]
1762 fn const_wrapping_div_agrees_with_wrapping_div_b(
1763 numerator in any::<[u8; 32]>(),
1764 denominator in any::<[u8; 32]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 32])
1765 ) {
1766 let numerator_u = U::from(numerator);
1767 let denominator_u = U::from(denominator);
1768 prop_assert_eq!(
1769 const_wrapping_div(&numerator_u, &denominator_u).0,
1770 wrapping_div_quo_rem_b::<32>(&numerator, &denominator).0
1771 );
1772 }
1773
1774 #[test]
1775 fn u_predicates_track_zero_and_true(bytes in any::<[u8; 32]>()) {
1776 let value = U::from(bytes);
1777 let is_zero = bytes.iter().all(|&b| b == 0);
1778 prop_assert_eq!(value.is_zero(), is_zero);
1779 prop_assert_eq!(value.is_some(), !is_zero);
1780 prop_assert_eq!(value.is_true(), bytes[31] == 1);
1781 }
1782
1783 #[test]
1784 fn test_u_is_zero(x in any::<[u8; 32]>()) {
1785 let x = U::from(x);
1786 let ex = U256::from_be_bytes(x.0);
1787 assert_eq!(ex.is_zero(), x.is_zero());
1788 }
1789
1790 #[test]
1791 fn test_u_div(x in any::<U>(), y in any::<U>()) {
1792 let ex = U256::from_be_bytes(x.0);
1793 let ey = U256::from_be_bytes(y.0);
1794 assert_eq!((ex.wrapping_div(ey)).to_be_bytes(), x.wrapping_div(&y).0);
1795 }
1796
1797 #[test]
1798 fn test_u_mul(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_mul(ey)).to_be_bytes(), wrapping_mul(&x, &y).0);
1802 }
1803
1804 #[test]
1805 fn test_u_mod(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 % ey).to_be_bytes(), (x % y).0);
1809 }
1810
1811 #[test]
1812 fn test_u_add(x in any::<U>(), y in any::<U>()) {
1813 let ex = U256::from_be_bytes(x.0);
1814 let ey = U256::from_be_bytes(y.0);
1815 let e = U::from(ex.wrapping_add(ey).to_be_bytes::<32>());
1816 assert_eq!(e, x.wrapping_add(&y), "{e} != {}", x + y);
1817 }
1818
1819 #[test]
1820 fn test_u_sub(x in any::<U>(), y in any::<U>()) {
1821 let ex = U256::from_be_bytes(x.0);
1822 let ey = U256::from_be_bytes(y.0);
1823 assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), x.wrapping_sub(&y).0);
1824 }
1825
1826 #[test]
1827 fn test_u_cmp(x in any::<U>(), y in any::<U>()) {
1828 let ex = U256::from_be_bytes(x.0);
1829 let ey = U256::from_be_bytes(y.0);
1830 assert_eq!(ex.cmp(&ey), x.cmp(&y));
1831 }
1832
1833 #[test]
1834 fn test_u_to_str(x in any::<U>()) {
1835 assert_eq!(U256::from_be_bytes(x.0).to_string(), x.to_string());
1836 }
1837
1838 #[test]
1839 fn test_u_shl(x in any::<U>(), i in any::<usize>()) {
1840 let l = U((U256::from_be_bytes(x.0) << i).to_be_bytes::<32>());
1841 assert_eq!(l, x << i);
1842 }
1843
1844 #[test]
1845 fn test_u_shr(x in any::<U>(), i in any::<usize>()) {
1846 let l = U((U256::from_be_bytes(x.0) >> i).to_be_bytes::<32>());
1847 assert_eq!(l, x >> i);
1848 }
1849
1850 #[test]
1851 fn test_trailing_zeros(x in any::<U>()) {
1852 assert_eq!(U256::from_be_bytes(x.0).trailing_zeros(), x.trailing_zeros());
1853 }
1854
1855 #[test]
1856 fn test_i_is_zero(x in any::<U>()) {
1857 let ex = I256::from_be_bytes(x.0);
1858 assert_eq!(ex.is_zero(), x.is_zero());
1859 }
1860
1861 #[test]
1862 fn test_i_div(x in any::<I>(), y in any::<I>()) {
1863 let ex = I256::from_be_bytes(x.0);
1864 let ey = I256::from_be_bytes(y.0);
1865 assert_eq!((ex / ey).to_be_bytes(), (x / y).0);
1866 }
1867
1868 #[test]
1869 fn test_i_mul(x in any::<I>(), y in any::<I>()) {
1870 let ex = I256::from_be_bytes(x.0);
1871 let ey = I256::from_be_bytes(y.0);
1872 assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), (x * y).0);
1873 }
1874
1875 #[test]
1876 fn test_i_mod(x in any::<I>(), y in any::<I>()) {
1877 let ex = I256::from_be_bytes(x.0);
1878 let ey = I256::from_be_bytes(y.0);
1879 assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1880 }
1881
1882 #[test]
1883 fn test_i_add(x in any::<I>(), y in any::<I>()) {
1884 let ex = I256::from_be_bytes(x.0);
1885 let ey = I256::from_be_bytes(y.0);
1886 assert_eq!((ex.wrapping_add(ey)).to_be_bytes(), (x + y).0);
1887 }
1888
1889 #[test]
1890 fn test_i_sub(x in any::<I>(), y in any::<I>()) {
1891 let ex = I256::from_be_bytes(x.0);
1892 let ey = I256::from_be_bytes(y.0);
1893 assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), (x - y).0);
1894 }
1895
1896 #[test]
1897 fn test_i_cmp(x in any::<I>(), y in any::<I>()) {
1898 let ex = I256::from_be_bytes(x.0);
1899 let ey = I256::from_be_bytes(y.0);
1900 assert_eq!(ex.cmp(&ey), x.cmp(&y));
1901 }
1902
1903 #[test]
1904 fn test_u_u8(x in any::<u8>()) {
1905 let mut b = [0u8; 32];
1906 b[32-size_of::<u8>()..].copy_from_slice(&x.to_be_bytes());
1907 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1908 }
1909
1910 #[test]
1911 fn test_u_u16(x in any::<u16>()) {
1912 let mut b = [0u8; 32];
1913 b[32-size_of::<u16>()..].copy_from_slice(&x.to_be_bytes());
1914 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1915 }
1916
1917 #[test]
1918 fn test_u_u32(x in any::<u32>()) {
1919 let mut b = [0u8; 32];
1920 b[32-size_of::<u32>()..].copy_from_slice(&x.to_be_bytes());
1921 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1922 }
1923
1924 #[test]
1925 fn test_u_u64(x in any::<u64>()) {
1926 let mut b = [0u8; 32];
1927 b[32-size_of::<u64>()..].copy_from_slice(&x.to_be_bytes());
1928 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1929 }
1930
1931 #[test]
1932 fn test_u_u128(x in any::<u128>()) {
1933 let mut b = [0u8; 32];
1934 b[32-size_of::<u128>()..].copy_from_slice(&x.to_be_bytes());
1935 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1936 }
1937
1938 #[test]
1939 fn test_to_and_from_addrs(x in any::<Address>()) {
1940 let y: Address = U::from(x).into();
1941 assert_eq!(x, y)
1942 }
1943
1944 #[test]
1945 fn test_u_conv_to_and_from_u8(x in any::<u8>()) {
1946 assert_eq!(x.wrapping_add(1), U::from(x).wrapping_add(&U::ONE).into());
1947 }
1948
1949 #[test]
1950 fn test_print_to_and_from(x in any::<[u8; 32]>()) {
1951 let e = format!("{}", U256::from_be_bytes(x));
1952 let v = format!("{}", U(x));
1953 assert_eq!(e, v);
1954 }
1955
1956 #[test]
1957 fn test_u_from_str(x in strat_any_u256()) {
1958 let v = U::from_str(x.to_string().as_str()).unwrap();
1959 assert_eq!(
1960 U::from(x.to_be_bytes::<32>()),
1961 v,
1962 "{x} != {v}",
1963 )
1964 }
1965
1966 #[test]
1967 fn array_truncate(x in any::<[u8; 20]>()) {
1968 assert_eq!(x, U::from(x).const_addr());
1969 }
1970 }
1971}