1use ethnum::U256 as EthU256;
4
5use serde::{Deserialize, Deserializer, Serialize, Serializer as SerdeSerializer};
6use std::{fmt, str::FromStr};
7
8use crate::{Decimal, NumericValue};
9
10const MAX_DECIMAL_DIGITS: usize = 78;
11const DECIMAL_CHUNK_BASE: u64 = 100_000_000;
12const DECIMAL_CHUNK_WIDTH: usize = 8;
13const DECIMAL_BUFFER_LEN: usize = 80;
14const U128_LOW_U32_MASK: u128 = 0xffff_ffff;
15
16#[derive(Clone, Copy, Debug, Eq, thiserror::Error, PartialEq)]
18#[error("value is not an unsigned 256-bit integer")]
19pub struct ParseU256Error;
20
21#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
27#[repr(transparent)]
28pub struct U256(EthU256);
29
30impl U256 {
31 pub const MIN: Self = Self::ZERO;
33
34 pub const ZERO: Self = Self(EthU256::ZERO);
36
37 pub const ONE: Self = Self(EthU256::ONE);
39
40 pub const MAX: Self = Self(EthU256::MAX);
42
43 #[must_use]
45 pub const fn from_words(high: u128, low: u128) -> Self {
46 Self(EthU256::from_words(high, low))
47 }
48
49 #[must_use]
51 pub const fn into_words(self) -> (u128, u128) {
52 self.0.into_words()
53 }
54
55 #[must_use]
57 pub fn from_be_bytes(bytes: [u8; 32]) -> Self {
58 Self(EthU256::from_be_bytes(bytes))
59 }
60
61 #[must_use]
63 pub fn to_be_bytes(self) -> [u8; 32] {
64 self.0.to_be_bytes()
65 }
66
67 #[must_use]
69 pub const fn to_u128(self) -> Option<u128> {
70 let (high, low) = self.into_words();
71 if high == 0 { Some(low) } else { None }
72 }
73
74 #[must_use]
76 pub fn checked_add(self, rhs: Self) -> Option<Self> {
77 self.0.checked_add(rhs.0).map(Self)
78 }
79
80 #[must_use]
82 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
83 self.0.checked_sub(rhs.0).map(Self)
84 }
85
86 #[must_use]
88 pub fn checked_mul(self, rhs: Self) -> Option<Self> {
89 self.0.checked_mul(rhs.0).map(Self)
90 }
91
92 #[must_use]
94 pub fn checked_div(self, rhs: Self) -> Option<Self> {
95 self.0.checked_div(rhs.0).map(Self)
96 }
97
98 #[must_use]
100 pub fn checked_rem(self, rhs: Self) -> Option<Self> {
101 self.0.checked_rem(rhs.0).map(Self)
102 }
103
104 fn decimal_text(self) -> DecimalText {
105 let (high, low) = self.into_words();
106 let mut limbs = [
107 low_u32_from_u128(high >> 96),
108 low_u32_from_u128(high >> 64),
109 low_u32_from_u128(high >> 32),
110 low_u32_from_u128(high),
111 low_u32_from_u128(low >> 96),
112 low_u32_from_u128(low >> 64),
113 low_u32_from_u128(low >> 32),
114 low_u32_from_u128(low),
115 ];
116 let mut bytes = [0_u8; DECIMAL_BUFFER_LEN];
117 let mut start = bytes.len();
118
119 loop {
120 let mut remainder = 0_u64;
121 let mut quotient_is_zero = true;
122 for limb in &mut limbs {
123 let dividend = (remainder << 32) | u64::from(*limb);
124 let quotient = dividend / DECIMAL_CHUNK_BASE;
125 remainder = dividend % DECIMAL_CHUNK_BASE;
126 *limb = u32::try_from(quotient).unwrap_or_default();
128 quotient_is_zero &= quotient == 0;
129 }
130
131 let mut chunk = u32::try_from(remainder).unwrap_or_default();
133 for _ in 0..DECIMAL_CHUNK_WIDTH {
134 start -= 1;
135 bytes[start] = b'0' + u8::try_from(chunk % 10).unwrap_or_default();
136 chunk /= 10;
137 }
138 if quotient_is_zero {
139 break;
140 }
141 }
142 while start + 1 < bytes.len() && bytes[start] == b'0' {
143 start += 1;
144 }
145
146 DecimalText { bytes, start }
147 }
148}
149
150fn low_u32_from_u128(value: u128) -> u32 {
151 u32::try_from(value & U128_LOW_U32_MASK).unwrap_or_default()
152}
153
154struct DecimalText {
155 bytes: [u8; DECIMAL_BUFFER_LEN],
156 start: usize,
157}
158
159impl DecimalText {
160 fn as_str(&self) -> &str {
161 std::str::from_utf8(&self.bytes[self.start..]).unwrap_or_default()
162 }
163}
164
165impl fmt::Debug for U256 {
166 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
167 fmt::Display::fmt(self, formatter)
168 }
169}
170
171impl fmt::Display for U256 {
172 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
173 let text = self.decimal_text();
174 formatter.write_str(text.as_str())
175 }
176}
177
178impl From<u64> for U256 {
179 fn from(value: u64) -> Self {
180 Self(EthU256::from(value))
181 }
182}
183
184impl From<u128> for U256 {
185 fn from(value: u128) -> Self {
186 Self(EthU256::from(value))
187 }
188}
189
190impl FromStr for U256 {
191 type Err = ParseU256Error;
192
193 fn from_str(value: &str) -> Result<Self, Self::Err> {
194 if value.is_empty()
195 || value.len() > MAX_DECIMAL_DIGITS
196 || !value.bytes().all(|byte| byte.is_ascii_digit())
197 {
198 return Err(ParseU256Error);
199 }
200 value
201 .parse::<EthU256>()
202 .map(Self)
203 .map_err(|_| ParseU256Error)
204 }
205}
206
207impl NumericValue for U256 {
208 fn try_to_decimal(&self) -> Option<Decimal> {
209 self.to_u128().and_then(Decimal::from_u128)
210 }
211
212 fn try_from_decimal(value: Decimal) -> Option<Self> {
213 value.to_u128().map(Self::from)
214 }
215}
216
217impl<'de> Deserialize<'de> for U256 {
218 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
219 where
220 D: Deserializer<'de>,
221 {
222 if deserializer.is_human_readable() {
223 return String::deserialize(deserializer)?
224 .parse()
225 .map_err(serde::de::Error::custom);
226 }
227 crate::atom::deserialize_fixed_bytes(deserializer).map(Self::from_be_bytes)
228 }
229}
230
231impl Serialize for U256 {
232 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
233 where
234 S: SerdeSerializer,
235 {
236 if serializer.is_human_readable() {
237 return serializer.collect_str(self);
238 }
239 serializer.serialize_bytes(&self.to_be_bytes())
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 use super::U256;
246 use crate::{Decimal, NumericValue};
247
248 #[test]
249 fn wire_uses_fixed_width_bytes_and_rejects_wrong_lengths() {
250 let bytes = crate::wire::encode_one(U256::MAX).unwrap();
251 assert_eq!(bytes, [&[32][..], &[0xff; 32][..]].concat());
252 assert_eq!(crate::wire::decode_one::<U256>(&bytes).unwrap(), U256::MAX);
253 for len in [0, 31, 33] {
254 assert!(
255 crate::wire::decode_one::<U256>(
256 &crate::wire::encode_one(serde_bytes::Bytes::new(&vec![0xff; len])).unwrap()
257 )
258 .is_err()
259 );
260 }
261 }
262
263 #[test]
264 fn fixed_bytes_and_decimal_are_exact() {
265 let value = "57896044618658097711785492504343953926634992332820282019728792003956564819968"
266 .parse::<U256>()
267 .expect("2^255 should parse");
268 assert_eq!(value.to_be_bytes()[0], 0x80);
269 assert_eq!(U256::from_be_bytes(value.to_be_bytes()), value);
270 assert_eq!(
271 value.to_string(),
272 "57896044618658097711785492504343953926634992332820282019728792003956564819968"
273 );
274 assert_eq!(U256::ZERO.to_string(), "0");
275 assert_eq!(U256::ONE.to_string(), "1");
276 assert_eq!(U256::MAX.to_string(), u256_max_decimal());
277 }
278
279 #[test]
280 fn checked_arithmetic_enforces_the_u256_domain() {
281 let two = U256::from(2_u64);
282 let three = U256::from(3_u64);
283
284 assert_eq!(two.checked_add(three), Some(U256::from(5_u64)));
285 assert_eq!(three.checked_sub(two), Some(U256::ONE));
286 assert_eq!(two.checked_mul(three), Some(U256::from(6_u64)));
287 assert_eq!(U256::from(7_u64).checked_div(two), Some(three));
288 assert_eq!(U256::from(7_u64).checked_rem(two), Some(U256::ONE));
289 assert_eq!(U256::MAX.checked_add(U256::ONE), None);
290 assert_eq!(U256::ZERO.checked_sub(U256::ONE), None);
291 assert_eq!(U256::MAX.checked_mul(two), None);
292 assert_eq!(U256::ONE.checked_div(U256::ZERO), None);
293 assert_eq!(U256::ONE.checked_rem(U256::ZERO), None);
294 }
295
296 #[test]
297 fn generic_numeric_conversion_is_fallible_without_widening_the_u256_domain() {
298 let value = U256::from(u128::try_from(i128::MAX).expect("i128::MAX should fit u128"));
299 assert_eq!(
300 value.try_to_decimal().and_then(U256::try_from_decimal),
301 Some(value),
302 );
303 assert_eq!(U256::MAX.try_to_decimal(), None);
304 let negative_one = Decimal::from_i128(-1).expect("-1 should be a valid Decimal");
305 assert_eq!(U256::try_from_decimal(negative_one), None);
306 }
307
308 fn u256_max_decimal() -> &'static str {
309 "115792089237316195423570985008687907853269984665640564039457584007913129639935"
310 }
311}