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