1use alloc::collections::BTreeMap;
2use alloy_primitives::{
3 ruint::{BaseConvertError, ParseError},
4 Bytes, B256, U256,
5};
6use core::{fmt, str::FromStr};
7use serde::{Deserialize, Deserializer, Serialize};
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
30#[serde(untagged)]
31pub enum JsonStorageKey {
32 Hash(B256),
34 Number(U256),
36}
37
38impl JsonStorageKey {
39 pub fn as_b256(&self) -> B256 {
41 match self {
42 Self::Hash(hash) => *hash,
43 Self::Number(num) => B256::from(*num),
44 }
45 }
46}
47
48impl Default for JsonStorageKey {
49 fn default() -> Self {
50 Self::Hash(Default::default())
51 }
52}
53
54impl From<B256> for JsonStorageKey {
55 fn from(value: B256) -> Self {
56 Self::Hash(value)
57 }
58}
59
60impl From<[u8; 32]> for JsonStorageKey {
61 fn from(value: [u8; 32]) -> Self {
62 B256::from(value).into()
63 }
64}
65
66impl From<U256> for JsonStorageKey {
67 fn from(value: U256) -> Self {
68 Self::Number(value)
69 }
70}
71
72impl FromStr for JsonStorageKey {
73 type Err = ParseError;
74
75 fn from_str(s: &str) -> Result<Self, Self::Err> {
76 if s.len() > 65 && !(s.len() == 66 && s.starts_with("0x")) {
77 return Err(ParseError::BaseConvertError(BaseConvertError::Overflow));
78 }
79
80 if let Ok(hash) = B256::from_str(s) {
81 return Ok(Self::Hash(hash));
82 }
83 s.parse().map(Self::Number)
84 }
85}
86
87impl fmt::Display for JsonStorageKey {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 match self {
90 Self::Hash(hash) => hash.fmt(f),
91 Self::Number(num) => alloc::format!("{num:#x}").fmt(f),
92 }
93 }
94}
95
96pub fn from_bytes_to_b256<'de, D>(bytes: Bytes) -> Result<B256, D::Error>
99where
100 D: Deserializer<'de>,
101{
102 if bytes.0.len() > 32 {
103 return Err(serde::de::Error::custom("input too long to be a B256"));
104 }
105
106 let mut padded = [0u8; 32];
108 padded[32 - bytes.0.len()..].copy_from_slice(&bytes.0);
109
110 Ok(B256::from_slice(&padded))
112}
113
114pub fn deserialize_storage_map<'de, D>(
123 deserializer: D,
124) -> Result<Option<BTreeMap<B256, B256>>, D::Error>
125where
126 D: Deserializer<'de>,
127{
128 if deserializer.is_human_readable() {
129 let map = Option::<BTreeMap<Bytes, Bytes>>::deserialize(deserializer)?;
130 match map {
131 Some(map) => {
132 let mut res_map = BTreeMap::new();
133 for (k, v) in map {
134 let k_deserialized = from_bytes_to_b256::<'de, D>(k)?;
135 let v_deserialized = from_bytes_to_b256::<'de, D>(v)?;
136 res_map.insert(k_deserialized, v_deserialized);
137 }
138 Ok(Some(res_map))
139 }
140 None => Ok(None),
141 }
142 } else {
143 Option::<BTreeMap<B256, B256>>::deserialize(deserializer)
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150 use alloc::string::{String, ToString};
151 use serde_json::json;
152
153 #[test]
154 fn default_number_storage_key() {
155 let key = JsonStorageKey::Number(Default::default());
156 assert_eq!(key.to_string(), String::from("0x0"));
157 }
158
159 #[test]
160 fn default_hash_storage_key() {
161 let key = JsonStorageKey::default();
162 assert_eq!(
163 key.to_string(),
164 String::from("0x0000000000000000000000000000000000000000000000000000000000000000")
165 );
166 }
167
168 #[test]
169 fn test_storage_key() {
170 let cases = [
171 "0x0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", ];
174
175 let key: JsonStorageKey = serde_json::from_str(&json!(cases[0]).to_string()).unwrap();
176 let key2: JsonStorageKey = serde_json::from_str(&json!(cases[1]).to_string()).unwrap();
177
178 assert_eq!(key.as_b256(), key2.as_b256());
179 }
180
181 #[test]
182 fn test_storage_key_serde_roundtrips() {
183 let test_cases = [
184 "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000abc", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xabc", "0xabcd", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", ];
194
195 for input in test_cases {
196 let key: JsonStorageKey = serde_json::from_str(&json!(input).to_string()).unwrap();
197 let output = key.to_string();
198
199 assert_eq!(
200 input, output,
201 "Storage key roundtrip failed to preserve the exact hex representation for {input}"
202 );
203 }
204 }
205
206 #[test]
207 fn test_as_b256() {
208 let cases = [
209 "0x0abc", "0x0000000000000000000000000000000000000000000000000000000000000abc", ];
212
213 let num_key: JsonStorageKey = serde_json::from_str(&json!(cases[0]).to_string()).unwrap();
214 let hash_key: JsonStorageKey = serde_json::from_str(&json!(cases[1]).to_string()).unwrap();
215
216 assert_eq!(num_key, JsonStorageKey::Number(U256::from_str(cases[0]).unwrap()));
217 assert_eq!(hash_key, JsonStorageKey::Hash(B256::from_str(cases[1]).unwrap()));
218
219 assert_eq!(num_key.as_b256(), hash_key.as_b256());
220 }
221
222 #[test]
223 fn test_json_storage_key_from_b256() {
224 let b256_value = B256::from([1u8; 32]);
225 let key = JsonStorageKey::from(b256_value);
226 assert_eq!(key, JsonStorageKey::Hash(b256_value));
227 assert_eq!(
228 key.to_string(),
229 "0x0101010101010101010101010101010101010101010101010101010101010101"
230 );
231 }
232
233 #[test]
234 fn test_json_storage_key_from_u256() {
235 let u256_value = U256::from(42);
236 let key = JsonStorageKey::from(u256_value);
237 assert_eq!(key, JsonStorageKey::Number(u256_value));
238 assert_eq!(key.to_string(), "0x2a");
239 }
240
241 #[test]
242 fn test_json_storage_key_from_u8_array() {
243 let bytes = [0u8; 32];
244 let key = JsonStorageKey::from(bytes);
245 assert_eq!(key, JsonStorageKey::Hash(B256::from(bytes)));
246 }
247
248 #[test]
249 fn test_from_str_parsing() {
250 let hex_str = "0x0101010101010101010101010101010101010101010101010101010101010101";
251 let key = JsonStorageKey::from_str(hex_str).unwrap();
252 assert_eq!(key, JsonStorageKey::Hash(B256::from_str(hex_str).unwrap()));
253 }
254
255 #[test]
256 fn test_from_str_with_too_long_hex_string() {
257 let long_hex_str = "0x".to_string() + &"1".repeat(65);
258 let result = JsonStorageKey::from_str(&long_hex_str);
259
260 assert!(matches!(result, Err(ParseError::BaseConvertError(BaseConvertError::Overflow))));
261 }
262
263 #[test]
264 fn test_deserialize_too_long_storage_key() {
265 let key = "0x".to_string() + &"f".repeat(68);
266 let result: Result<JsonStorageKey, _> = serde_json::from_str(&json!(key).to_string());
267 assert!(result.is_err(), "storage key with 68 hex chars should fail deserialization");
268 }
269
270 #[test]
271 fn test_from_str_length_boundaries() {
272 let key_63 = "0x".to_string() + &"f".repeat(63);
274 let result = JsonStorageKey::from_str(&key_63);
275 assert!(result.is_ok(), "0x + 63 hex chars should be a valid U256 storage key");
276 assert!(matches!(result.unwrap(), JsonStorageKey::Number(_)));
277
278 let key_64 = "0x".to_string() + &"f".repeat(64);
280 let result = JsonStorageKey::from_str(&key_64);
281 assert!(result.is_ok(), "0x + 64 hex chars should be a valid B256 storage key");
282 assert!(matches!(result.unwrap(), JsonStorageKey::Hash(_)));
283
284 let key_65 = "0x".to_string() + &"f".repeat(65);
286 assert!(JsonStorageKey::from_str(&key_65).is_err());
287
288 let bare_64 = "f".repeat(64);
290 let result = JsonStorageKey::from_str(&bare_64);
291 assert!(result.is_ok(), "64 bare hex chars should be a valid B256 storage key");
292 assert!(matches!(result.unwrap(), JsonStorageKey::Hash(_)));
293
294 let bare_65 = "f".repeat(65);
296 assert!(JsonStorageKey::from_str(&bare_65).is_err());
297 }
298
299 #[test]
300 fn test_deserialize_storage_map_with_valid_data() {
301 let json_data = json!({
302 "0x0000000000000000000000000000000000000000000000000000000000000001": "0x22",
303 "0x0000000000000000000000000000000000000000000000000000000000000002": "0x33"
304 });
305
306 let deserialized: Option<BTreeMap<B256, B256>> = deserialize_storage_map(
308 &serde_json::from_value::<serde_json::Value>(json_data).unwrap(),
309 )
310 .unwrap();
311
312 assert_eq!(
313 deserialized.unwrap(),
314 BTreeMap::from([
315 (B256::from(U256::from(1u128)), B256::from(U256::from(0x22u128))),
316 (B256::from(U256::from(2u128)), B256::from(U256::from(0x33u128)))
317 ])
318 );
319 }
320
321 #[test]
322 fn test_deserialize_storage_map_with_empty_data() {
323 let json_data = json!({});
324 let deserialized: Option<BTreeMap<B256, B256>> = deserialize_storage_map(
325 &serde_json::from_value::<serde_json::Value>(json_data).unwrap(),
326 )
327 .unwrap();
328 assert!(deserialized.unwrap().is_empty());
329 }
330
331 #[test]
332 fn test_deserialize_storage_map_with_none() {
333 let json_data = json!(null);
334 let deserialized: Option<BTreeMap<B256, B256>> = deserialize_storage_map(
335 &serde_json::from_value::<serde_json::Value>(json_data).unwrap(),
336 )
337 .unwrap();
338 assert!(deserialized.is_none());
339 }
340
341 #[test]
342 fn test_from_bytes_to_b256_with_valid_input() {
343 let bytes = Bytes::from(vec![0x1, 0x2, 0x3, 0x4]);
345 let result = from_bytes_to_b256::<serde_json::Value>(bytes).unwrap();
346 let expected = B256::from_slice(&[
347 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, 1,
348 2, 3, 4,
349 ]);
350 assert_eq!(result, expected);
351 }
352
353 #[test]
354 fn test_from_bytes_to_b256_with_exact_32_bytes() {
355 let bytes = Bytes::from(vec![
357 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11,
358 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
359 0x20,
360 ]);
361 let result = from_bytes_to_b256::<serde_json::Value>(bytes).unwrap();
362 let expected = B256::from_slice(&[
363 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11,
364 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
365 0x20,
366 ]);
367 assert_eq!(result, expected);
368 }
369
370 #[test]
371 fn test_from_bytes_to_b256_with_input_too_long() {
372 let bytes = Bytes::from(vec![0x1; 33]); let result = from_bytes_to_b256::<serde_json::Value>(bytes);
375 assert!(result.is_err());
376 assert_eq!(result.unwrap_err().to_string(), "input too long to be a B256");
377 }
378
379 #[test]
380 fn test_from_bytes_to_b256_with_empty_input() {
381 let bytes = Bytes::from(vec![]);
383 let result = from_bytes_to_b256::<serde_json::Value>(bytes).unwrap();
384 let expected = B256::from_slice(&[0; 32]); assert_eq!(result, expected);
386 }
387}