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