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