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() > 64 && !(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", ];
190
191 for input in test_cases {
192 let key: JsonStorageKey = serde_json::from_str(&json!(input).to_string()).unwrap();
193 let output = key.to_string();
194
195 assert_eq!(
196 input, output,
197 "Storage key roundtrip failed to preserve the exact hex representation for {input}"
198 );
199 }
200 }
201
202 #[test]
203 fn test_as_b256() {
204 let cases = [
205 "0x0abc", "0x0000000000000000000000000000000000000000000000000000000000000abc", ];
208
209 let num_key: JsonStorageKey = serde_json::from_str(&json!(cases[0]).to_string()).unwrap();
210 let hash_key: JsonStorageKey = serde_json::from_str(&json!(cases[1]).to_string()).unwrap();
211
212 assert_eq!(num_key, JsonStorageKey::Number(U256::from_str(cases[0]).unwrap()));
213 assert_eq!(hash_key, JsonStorageKey::Hash(B256::from_str(cases[1]).unwrap()));
214
215 assert_eq!(num_key.as_b256(), hash_key.as_b256());
216 }
217
218 #[test]
219 fn test_json_storage_key_from_b256() {
220 let b256_value = B256::from([1u8; 32]);
221 let key = JsonStorageKey::from(b256_value);
222 assert_eq!(key, JsonStorageKey::Hash(b256_value));
223 assert_eq!(
224 key.to_string(),
225 "0x0101010101010101010101010101010101010101010101010101010101010101"
226 );
227 }
228
229 #[test]
230 fn test_json_storage_key_from_u256() {
231 let u256_value = U256::from(42);
232 let key = JsonStorageKey::from(u256_value);
233 assert_eq!(key, JsonStorageKey::Number(u256_value));
234 assert_eq!(key.to_string(), "0x2a");
235 }
236
237 #[test]
238 fn test_json_storage_key_from_u8_array() {
239 let bytes = [0u8; 32];
240 let key = JsonStorageKey::from(bytes);
241 assert_eq!(key, JsonStorageKey::Hash(B256::from(bytes)));
242 }
243
244 #[test]
245 fn test_from_str_parsing() {
246 let hex_str = "0x0101010101010101010101010101010101010101010101010101010101010101";
247 let key = JsonStorageKey::from_str(hex_str).unwrap();
248 assert_eq!(key, JsonStorageKey::Hash(B256::from_str(hex_str).unwrap()));
249 }
250
251 #[test]
252 fn test_from_str_with_too_long_hex_string() {
253 let long_hex_str = "0x".to_string() + &"1".repeat(65);
254 let result = JsonStorageKey::from_str(&long_hex_str);
255
256 assert!(matches!(result, Err(ParseError::BaseConvertError(BaseConvertError::Overflow))));
257 }
258
259 #[test]
260 fn test_deserialize_storage_map_with_valid_data() {
261 let json_data = json!({
262 "0x0000000000000000000000000000000000000000000000000000000000000001": "0x22",
263 "0x0000000000000000000000000000000000000000000000000000000000000002": "0x33"
264 });
265
266 let deserialized: Option<BTreeMap<B256, B256>> = deserialize_storage_map(
268 &serde_json::from_value::<serde_json::Value>(json_data).unwrap(),
269 )
270 .unwrap();
271
272 assert_eq!(
273 deserialized.unwrap(),
274 BTreeMap::from([
275 (B256::from(U256::from(1u128)), B256::from(U256::from(0x22u128))),
276 (B256::from(U256::from(2u128)), B256::from(U256::from(0x33u128)))
277 ])
278 );
279 }
280
281 #[test]
282 fn test_deserialize_storage_map_with_empty_data() {
283 let json_data = json!({});
284 let deserialized: Option<BTreeMap<B256, B256>> = deserialize_storage_map(
285 &serde_json::from_value::<serde_json::Value>(json_data).unwrap(),
286 )
287 .unwrap();
288 assert!(deserialized.unwrap().is_empty());
289 }
290
291 #[test]
292 fn test_deserialize_storage_map_with_none() {
293 let json_data = json!(null);
294 let deserialized: Option<BTreeMap<B256, B256>> = deserialize_storage_map(
295 &serde_json::from_value::<serde_json::Value>(json_data).unwrap(),
296 )
297 .unwrap();
298 assert!(deserialized.is_none());
299 }
300
301 #[test]
302 fn test_from_bytes_to_b256_with_valid_input() {
303 let bytes = Bytes::from(vec![0x1, 0x2, 0x3, 0x4]);
305 let result = from_bytes_to_b256::<serde_json::Value>(bytes).unwrap();
306 let expected = B256::from_slice(&[
307 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,
308 2, 3, 4,
309 ]);
310 assert_eq!(result, expected);
311 }
312
313 #[test]
314 fn test_from_bytes_to_b256_with_exact_32_bytes() {
315 let bytes = Bytes::from(vec![
317 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11,
318 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
319 0x20,
320 ]);
321 let result = from_bytes_to_b256::<serde_json::Value>(bytes).unwrap();
322 let expected = B256::from_slice(&[
323 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11,
324 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
325 0x20,
326 ]);
327 assert_eq!(result, expected);
328 }
329
330 #[test]
331 fn test_from_bytes_to_b256_with_input_too_long() {
332 let bytes = Bytes::from(vec![0x1; 33]); let result = from_bytes_to_b256::<serde_json::Value>(bytes);
335 assert!(result.is_err());
336 assert_eq!(result.unwrap_err().to_string(), "input too long to be a B256");
337 }
338
339 #[test]
340 fn test_from_bytes_to_b256_with_empty_input() {
341 let bytes = Bytes::from(vec![]);
343 let result = from_bytes_to_b256::<serde_json::Value>(bytes).unwrap();
344 let expected = B256::from_slice(&[0; 32]); assert_eq!(result, expected);
346 }
347}