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