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