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