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]) -> 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 impl PartialEq<$t> for U {
1484 fn eq(&self, rhs: &$t) -> bool {
1485 *self == U::from(*rhs)
1486 }
1487 }
1488
1489 impl PartialOrd<$t> for U {
1490 fn partial_cmp(&self, rhs: &$t) -> Option<Ordering> {
1491 let rhs = rhs.to_be_bytes();
1492 let n = core::mem::size_of::<$t>();
1493 let split = 32 - n;
1494 if self.0[..split].iter().any(|&b| b != 0) {
1495 return Some(Ordering::Greater);
1496 }
1497 Some(self.0[split..].cmp(&rhs))
1498 }
1499 }
1500 }
1501 )+
1502 };
1503}
1504
1505#[macro_export]
1506macro_rules! u {
1507 ($e:expr) => {
1508 $crate::U::from_u32($e)
1509 };
1510}
1511
1512from_ints! { u8, u16, u32, u64, u128, usize }
1513
1514impl From<I> for [u8; 32] {
1515 fn from(x: I) -> Self {
1516 x.0
1517 }
1518}
1519
1520impl From<[u8; 32]> for I {
1521 fn from(x: [u8; 32]) -> Self {
1522 I(x)
1523 }
1524}
1525
1526fn i_add(x: &I, y: &I) -> I {
1527 I(wrapping_add(&U(x.0), &U(y.0)).0)
1528}
1529
1530fn i_sub(x: &I, y: &I) -> I {
1531 I(wrapping_sub(&U(x.0), &U(y.0)).0)
1532}
1533
1534fn i_mul(x: &I, y: &I) -> I {
1535 let result = wrapping_mul(&U(x.0), &U(y.0));
1536 I(result.0)
1537}
1538
1539fn i_div(x: &I, y: &I) -> I {
1540 let r = wrapping_div(&x.abs(), &y.abs());
1541 if x.is_neg() ^ y.is_neg() {
1542 I(r.0).neg()
1543 } else {
1544 I(r.0)
1545 }
1546}
1547
1548fn i_rem(x: &I, y: &I) -> I {
1549 let r = modd(&x.abs(), &y.abs());
1550 if x.is_neg() { I(r.0).neg() } else { I(r.0) }
1551}
1552
1553impl Add for I {
1554 type Output = I;
1555 fn add(self, rhs: I) -> I {
1556 i_add(&self, &rhs)
1557 }
1558}
1559
1560impl Add for &I {
1561 type Output = I;
1562 fn add(self, rhs: &I) -> I {
1563 i_add(self, rhs)
1564 }
1565}
1566
1567impl Sub for I {
1568 type Output = I;
1569 fn sub(self, rhs: I) -> I {
1570 i_sub(&self, &rhs)
1571 }
1572}
1573
1574impl Sub for &I {
1575 type Output = I;
1576 fn sub(self, rhs: &I) -> I {
1577 i_sub(self, rhs)
1578 }
1579}
1580
1581impl Mul for I {
1582 type Output = I;
1583 fn mul(self, rhs: I) -> I {
1584 i_mul(&self, &rhs)
1585 }
1586}
1587
1588impl Mul for &I {
1589 type Output = I;
1590 fn mul(self, rhs: &I) -> I {
1591 i_mul(self, rhs)
1592 }
1593}
1594
1595impl Div for I {
1596 type Output = I;
1597 fn div(self, rhs: I) -> I {
1598 i_div(&self, &rhs)
1599 }
1600}
1601
1602impl Div for &I {
1603 type Output = I;
1604 fn div(self, rhs: &I) -> I {
1605 i_div(self, rhs)
1606 }
1607}
1608
1609impl Rem for I {
1610 type Output = I;
1611 fn rem(self, rhs: I) -> I {
1612 i_rem(&self, &rhs)
1613 }
1614}
1615
1616impl Eq for I {}
1617
1618impl PartialOrd for I {
1619 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1620 Some(self.cmp(other))
1621 }
1622}
1623
1624impl Ord for I {
1625 fn cmp(&self, other: &Self) -> Ordering {
1626 let self_sign = self.0[0] & 0x80;
1627 let other_sign = other.0[0] & 0x80;
1628 match (self_sign, other_sign) {
1629 (0, 0x80) => Ordering::Greater,
1630 (0x80, 0) => Ordering::Less,
1631 _ => self.0.cmp(&other.0),
1632 }
1633 }
1634}
1635
1636impl Rem for &I {
1637 type Output = I;
1638 fn rem(self, rhs: &I) -> I {
1639 i_rem(self, rhs)
1640 }
1641}
1642
1643impl I {
1644 pub const ZERO: Self = I([0u8; 32]);
1645
1646 pub const ONE: Self = I([
1647 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,
1648 0, 1,
1649 ]);
1650}
1651
1652impl Zero for I {
1653 fn zero() -> Self {
1654 I::ZERO
1655 }
1656 fn is_zero(&self) -> bool {
1657 self.0.iter().all(|&b| b == 0)
1658 }
1659}
1660
1661impl Default for I {
1662 fn default() -> Self {
1663 I::ZERO
1664 }
1665}
1666
1667impl One for I {
1668 fn one() -> Self {
1669 I::ONE
1670 }
1671}
1672
1673#[test]
1674fn test_is_zeroes() {
1675 assert!(U::ZERO.is_zero());
1676 assert!(U::ONE.is_some());
1677 assert!(I::ZERO.is_zero());
1678 assert!(I::ONE.is_some());
1679}
1680
1681#[cfg(all(
1682 test,
1683 feature = "alloy-enabled",
1684 feature = "proptest",
1685 feature = "std",
1686 not(target_arch = "wasm32")
1687))]
1688mod test {
1689 use proptest::prelude::*;
1690
1691 use super::*;
1692
1693 fn strat_any_u256() -> impl Strategy<Value = U256> {
1694 any::<[u8; 32]>().prop_map(U256::from_be_bytes)
1696 }
1697
1698 proptest! {
1699 #[test]
1700 fn wrapping_div_b_zero_denominator_yields_zero(numerator in any::<[u8; 4]>()) {
1701 let zero = [0u8; 4];
1702 prop_assert_eq!(wrapping_div_quo_rem_b::<4>(&numerator, &zero).0, zero);
1703 }
1704
1705 #[test]
1706 fn wrapping_div_b_matches_integer_division(
1707 numerator in any::<[u8; 4]>(),
1708 denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1709 ) {
1710 let numerator_u32 = u32::from_be_bytes(numerator);
1711 let denominator_u32 = u32::from_be_bytes(denominator);
1712 let expected = numerator_u32 / denominator_u32;
1713 prop_assert_eq!(
1714 wrapping_div_quo_rem_b::<4>(&numerator, &denominator).0,
1715 expected.to_be_bytes()
1716 );
1717 }
1718
1719 #[test]
1720 fn wrapping_mod_b_matches_integer_modulo(
1721 numerator in any::<[u8; 4]>(),
1722 denominator in any::<[u8; 4]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 4])
1723 ) {
1724 let numerator_u32 = u32::from_be_bytes(numerator);
1725 let denominator_u32 = u32::from_be_bytes(denominator);
1726 let expected = numerator_u32 % denominator_u32;
1727 prop_assert_eq!(
1728 wrapping_div_quo_rem_b::<4>(&numerator, &denominator).1,
1729 expected.to_be_bytes()
1730 );
1731 }
1732
1733 #[test]
1734 fn wrapping_add_b_handles_carry(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1735 let lhs_u32 = u32::from_be_bytes(lhs);
1736 let rhs_u32 = u32::from_be_bytes(rhs);
1737 let expected = lhs_u32.wrapping_add(rhs_u32);
1738 prop_assert_eq!(wrapping_add_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1739 }
1740
1741 #[test]
1742 fn wrapping_sub_b_handles_borrow(lhs in any::<[u8; 4]>(), rhs in any::<[u8; 4]>()) {
1743 let lhs_u32 = u32::from_be_bytes(lhs);
1744 let rhs_u32 = u32::from_be_bytes(rhs);
1745 let expected = lhs_u32.wrapping_sub(rhs_u32);
1746 prop_assert_eq!(wrapping_sub_b::<4>(&lhs, &rhs), expected.to_be_bytes());
1747 }
1748
1749 #[test]
1750 fn wrapping_mul_b_matches_wrapping_arithmetic(lhs in any::<[u8; 32]>(), rhs in any::<[u8; 32]>()) {
1751 let lhs_u = U::from(lhs);
1752 let rhs_u = U::from(rhs);
1753 let expected = lhs_u.wrapping_mul(&rhs_u);
1754 prop_assert_eq!(wrapping_mul_b::<32>(&lhs, &rhs), expected.0);
1755 }
1756
1757 #[test]
1758 fn const_wrapping_div_agrees_with_wrapping_div_b(
1759 numerator in any::<[u8; 32]>(),
1760 denominator in any::<[u8; 32]>().prop_filter("denominator must be non-zero", |d| *d != [0u8; 32])
1761 ) {
1762 let numerator_u = U::from(numerator);
1763 let denominator_u = U::from(denominator);
1764 prop_assert_eq!(
1765 const_wrapping_div(&numerator_u, &denominator_u).0,
1766 wrapping_div_quo_rem_b::<32>(&numerator, &denominator).0
1767 );
1768 }
1769
1770 #[test]
1771 fn u_predicates_track_zero_and_true(bytes in any::<[u8; 32]>()) {
1772 let value = U::from(bytes);
1773 let is_zero = bytes.iter().all(|&b| b == 0);
1774 prop_assert_eq!(value.is_zero(), is_zero);
1775 prop_assert_eq!(value.is_some(), !is_zero);
1776 prop_assert_eq!(value.is_true(), bytes[31] == 1);
1777 }
1778
1779 #[test]
1780 fn test_u_is_zero(x in any::<[u8; 32]>()) {
1781 let x = U::from(x);
1782 let ex = U256::from_be_bytes(x.0);
1783 assert_eq!(ex.is_zero(), x.is_zero());
1784 }
1785
1786 #[test]
1787 fn test_u_div(x in any::<U>(), y in any::<U>()) {
1788 let ex = U256::from_be_bytes(x.0);
1789 let ey = U256::from_be_bytes(y.0);
1790 assert_eq!((ex.wrapping_div(ey)).to_be_bytes(), x.wrapping_div(&y).0);
1791 }
1792
1793 #[test]
1794 fn test_u_mul(x in any::<U>(), y in any::<U>()) {
1795 let ex = U256::from_be_bytes(x.0);
1796 let ey = U256::from_be_bytes(y.0);
1797 assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), wrapping_mul(&x, &y).0);
1798 }
1799
1800 #[test]
1801 fn test_u_mod(x in any::<U>(), y in any::<U>()) {
1802 let ex = U256::from_be_bytes(x.0);
1803 let ey = U256::from_be_bytes(y.0);
1804 assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1805 }
1806
1807 #[test]
1808 fn test_u_add(x in any::<U>(), y in any::<U>()) {
1809 let ex = U256::from_be_bytes(x.0);
1810 let ey = U256::from_be_bytes(y.0);
1811 let e = U::from(ex.wrapping_add(ey).to_be_bytes::<32>());
1812 assert_eq!(e, x.wrapping_add(&y), "{e} != {}", x + y);
1813 }
1814
1815 #[test]
1816 fn test_u_sub(x in any::<U>(), y in any::<U>()) {
1817 let ex = U256::from_be_bytes(x.0);
1818 let ey = U256::from_be_bytes(y.0);
1819 assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), x.wrapping_sub(&y).0);
1820 }
1821
1822 #[test]
1823 fn test_u_cmp(x in any::<U>(), y in any::<U>()) {
1824 let ex = U256::from_be_bytes(x.0);
1825 let ey = U256::from_be_bytes(y.0);
1826 assert_eq!(ex.cmp(&ey), x.cmp(&y));
1827 }
1828
1829 #[test]
1830 fn test_u_to_str(x in any::<U>()) {
1831 assert_eq!(U256::from_be_bytes(x.0).to_string(), x.to_string());
1832 }
1833
1834 #[test]
1835 fn test_u_shl(x in any::<U>(), i in any::<usize>()) {
1836 let l = U((U256::from_be_bytes(x.0) << i).to_be_bytes::<32>());
1837 assert_eq!(l, x << i);
1838 }
1839
1840 #[test]
1841 fn test_u_shr(x in any::<U>(), i in any::<usize>()) {
1842 let l = U((U256::from_be_bytes(x.0) >> i).to_be_bytes::<32>());
1843 assert_eq!(l, x >> i);
1844 }
1845
1846 #[test]
1847 fn test_trailing_zeros(x in any::<U>()) {
1848 assert_eq!(U256::from_be_bytes(x.0).trailing_zeros(), x.trailing_zeros());
1849 }
1850
1851 #[test]
1852 fn test_i_is_zero(x in any::<U>()) {
1853 let ex = I256::from_be_bytes(x.0);
1854 assert_eq!(ex.is_zero(), x.is_zero());
1855 }
1856
1857 #[test]
1858 fn test_i_div(x in any::<I>(), y in any::<I>()) {
1859 let ex = I256::from_be_bytes(x.0);
1860 let ey = I256::from_be_bytes(y.0);
1861 assert_eq!((ex / ey).to_be_bytes(), (x / y).0);
1862 }
1863
1864 #[test]
1865 fn test_i_mul(x in any::<I>(), y in any::<I>()) {
1866 let ex = I256::from_be_bytes(x.0);
1867 let ey = I256::from_be_bytes(y.0);
1868 assert_eq!((ex.wrapping_mul(ey)).to_be_bytes(), (x * y).0);
1869 }
1870
1871 #[test]
1872 fn test_i_mod(x in any::<I>(), y in any::<I>()) {
1873 let ex = I256::from_be_bytes(x.0);
1874 let ey = I256::from_be_bytes(y.0);
1875 assert_eq!((ex % ey).to_be_bytes(), (x % y).0);
1876 }
1877
1878 #[test]
1879 fn test_i_add(x in any::<I>(), y in any::<I>()) {
1880 let ex = I256::from_be_bytes(x.0);
1881 let ey = I256::from_be_bytes(y.0);
1882 assert_eq!((ex.wrapping_add(ey)).to_be_bytes(), (x + y).0);
1883 }
1884
1885 #[test]
1886 fn test_i_sub(x in any::<I>(), y in any::<I>()) {
1887 let ex = I256::from_be_bytes(x.0);
1888 let ey = I256::from_be_bytes(y.0);
1889 assert_eq!((ex.wrapping_sub(ey)).to_be_bytes(), (x - y).0);
1890 }
1891
1892 #[test]
1893 fn test_i_cmp(x in any::<I>(), y in any::<I>()) {
1894 let ex = I256::from_be_bytes(x.0);
1895 let ey = I256::from_be_bytes(y.0);
1896 assert_eq!(ex.cmp(&ey), x.cmp(&y));
1897 }
1898
1899 #[test]
1900 fn test_u_u8(x in any::<u8>()) {
1901 let mut b = [0u8; 32];
1902 b[32-size_of::<u8>()..].copy_from_slice(&x.to_be_bytes());
1903 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1904 }
1905
1906 #[test]
1907 fn test_u_u16(x in any::<u16>()) {
1908 let mut b = [0u8; 32];
1909 b[32-size_of::<u16>()..].copy_from_slice(&x.to_be_bytes());
1910 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1911 }
1912
1913 #[test]
1914 fn test_u_u32(x in any::<u32>()) {
1915 let mut b = [0u8; 32];
1916 b[32-size_of::<u32>()..].copy_from_slice(&x.to_be_bytes());
1917 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1918 }
1919
1920 #[test]
1921 fn test_u_u64(x in any::<u64>()) {
1922 let mut b = [0u8; 32];
1923 b[32-size_of::<u64>()..].copy_from_slice(&x.to_be_bytes());
1924 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1925 }
1926
1927 #[test]
1928 fn test_u_u128(x in any::<u128>()) {
1929 let mut b = [0u8; 32];
1930 b[32-size_of::<u128>()..].copy_from_slice(&x.to_be_bytes());
1931 assert_eq!(&U256::from_be_bytes(b).to_be_bytes(), U::from(x).as_slice());
1932 }
1933
1934 #[test]
1935 fn test_to_and_from_addrs(x in any::<Address>()) {
1936 let y: Address = U::from(x).into();
1937 assert_eq!(x, y)
1938 }
1939
1940 #[test]
1941 fn test_u_conv_to_and_from_u8(x in any::<u8>()) {
1942 assert_eq!(x.wrapping_add(1), U::from(x).wrapping_add(&U::ONE).into());
1943 }
1944
1945 #[test]
1946 fn test_print_to_and_from(x in any::<[u8; 32]>()) {
1947 let e = format!("{}", U256::from_be_bytes(x));
1948 let v = format!("{}", U(x));
1949 assert_eq!(e, v);
1950 }
1951
1952 #[test]
1953 fn test_u_from_str(x in strat_any_u256()) {
1954 let v = U::from_str(x.to_string().as_str()).unwrap();
1955 assert_eq!(
1956 U::from(x.to_be_bytes::<32>()),
1957 v,
1958 "{x} != {v}",
1959 )
1960 }
1961
1962 #[test]
1963 fn array_truncate(x in any::<[u8; 20]>()) {
1964 assert_eq!(x, U::from(x).const_addr());
1965 }
1966 }
1967}