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