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 let map = Option::<BTreeMap<Bytes, Bytes>>::deserialize(deserializer)?;
129 match map {
130 Some(map) => {
131 let mut res_map = BTreeMap::new();
132 for (k, v) in map {
133 let k_deserialized = from_bytes_to_b256::<'de, D>(k)?;
134 let v_deserialized = from_bytes_to_b256::<'de, D>(v)?;
135 res_map.insert(k_deserialized, v_deserialized);
136 }
137 Ok(Some(res_map))
138 }
139 None => Ok(None),
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146 use alloc::string::{String, ToString};
147 use serde_json::json;
148
149 #[test]
150 fn default_number_storage_key() {
151 let key = JsonStorageKey::Number(Default::default());
152 assert_eq!(key.to_string(), String::from("0x0"));
153 }
154
155 #[test]
156 fn default_hash_storage_key() {
157 let key = JsonStorageKey::default();
158 assert_eq!(
159 key.to_string(),
160 String::from("0x0000000000000000000000000000000000000000000000000000000000000000")
161 );
162 }
163
164 #[test]
165 fn test_storage_key() {
166 let cases = [
167 "0x0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", ];
170
171 let key: JsonStorageKey = serde_json::from_str(&json!(cases[0]).to_string()).unwrap();
172 let key2: JsonStorageKey = serde_json::from_str(&json!(cases[1]).to_string()).unwrap();
173
174 assert_eq!(key.as_b256(), key2.as_b256());
175 }
176
177 #[test]
178 fn test_storage_key_serde_roundtrips() {
179 let test_cases = [
180 "0x0000000000000000000000000000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000000000000000000000000000abc", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xabc", "0xabcd", ];
186
187 for input in test_cases {
188 let key: JsonStorageKey = serde_json::from_str(&json!(input).to_string()).unwrap();
189 let output = key.to_string();
190
191 assert_eq!(
192 input, output,
193 "Storage key roundtrip failed to preserve the exact hex representation for {input}"
194 );
195 }
196 }
197
198 #[test]
199 fn test_as_b256() {
200 let cases = [
201 "0x0abc", "0x0000000000000000000000000000000000000000000000000000000000000abc", ];
204
205 let num_key: JsonStorageKey = serde_json::from_str(&json!(cases[0]).to_string()).unwrap();
206 let hash_key: JsonStorageKey = serde_json::from_str(&json!(cases[1]).to_string()).unwrap();
207
208 assert_eq!(num_key, JsonStorageKey::Number(U256::from_str(cases[0]).unwrap()));
209 assert_eq!(hash_key, JsonStorageKey::Hash(B256::from_str(cases[1]).unwrap()));
210
211 assert_eq!(num_key.as_b256(), hash_key.as_b256());
212 }
213
214 #[test]
215 fn test_json_storage_key_from_b256() {
216 let b256_value = B256::from([1u8; 32]);
217 let key = JsonStorageKey::from(b256_value);
218 assert_eq!(key, JsonStorageKey::Hash(b256_value));
219 assert_eq!(
220 key.to_string(),
221 "0x0101010101010101010101010101010101010101010101010101010101010101"
222 );
223 }
224
225 #[test]
226 fn test_json_storage_key_from_u256() {
227 let u256_value = U256::from(42);
228 let key = JsonStorageKey::from(u256_value);
229 assert_eq!(key, JsonStorageKey::Number(u256_value));
230 assert_eq!(key.to_string(), "0x2a");
231 }
232
233 #[test]
234 fn test_json_storage_key_from_u8_array() {
235 let bytes = [0u8; 32];
236 let key = JsonStorageKey::from(bytes);
237 assert_eq!(key, JsonStorageKey::Hash(B256::from(bytes)));
238 }
239
240 #[test]
241 fn test_from_str_parsing() {
242 let hex_str = "0x0101010101010101010101010101010101010101010101010101010101010101";
243 let key = JsonStorageKey::from_str(hex_str).unwrap();
244 assert_eq!(key, JsonStorageKey::Hash(B256::from_str(hex_str).unwrap()));
245 }
246
247 #[test]
248 fn test_from_str_with_too_long_hex_string() {
249 let long_hex_str = "0x".to_string() + &"1".repeat(65);
250 let result = JsonStorageKey::from_str(&long_hex_str);
251
252 assert!(matches!(result, Err(ParseError::BaseConvertError(BaseConvertError::Overflow))));
253 }
254
255 #[test]
256 fn test_deserialize_storage_map_with_valid_data() {
257 let json_data = json!({
258 "0x0000000000000000000000000000000000000000000000000000000000000001": "0x22",
259 "0x0000000000000000000000000000000000000000000000000000000000000002": "0x33"
260 });
261
262 let deserialized: Option<BTreeMap<B256, B256>> = deserialize_storage_map(
264 &serde_json::from_value::<serde_json::Value>(json_data).unwrap(),
265 )
266 .unwrap();
267
268 assert_eq!(
269 deserialized.unwrap(),
270 BTreeMap::from([
271 (B256::from(U256::from(1u128)), B256::from(U256::from(0x22u128))),
272 (B256::from(U256::from(2u128)), B256::from(U256::from(0x33u128)))
273 ])
274 );
275 }
276
277 #[test]
278 fn test_deserialize_storage_map_with_empty_data() {
279 let json_data = json!({});
280 let deserialized: Option<BTreeMap<B256, B256>> = deserialize_storage_map(
281 &serde_json::from_value::<serde_json::Value>(json_data).unwrap(),
282 )
283 .unwrap();
284 assert!(deserialized.unwrap().is_empty());
285 }
286
287 #[test]
288 fn test_deserialize_storage_map_with_none() {
289 let json_data = json!(null);
290 let deserialized: Option<BTreeMap<B256, B256>> = deserialize_storage_map(
291 &serde_json::from_value::<serde_json::Value>(json_data).unwrap(),
292 )
293 .unwrap();
294 assert!(deserialized.is_none());
295 }
296
297 #[test]
298 fn test_from_bytes_to_b256_with_valid_input() {
299 let bytes = Bytes::from(vec![0x1, 0x2, 0x3, 0x4]);
301 let result = from_bytes_to_b256::<serde_json::Value>(bytes).unwrap();
302 let expected = B256::from_slice(&[
303 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,
304 2, 3, 4,
305 ]);
306 assert_eq!(result, expected);
307 }
308
309 #[test]
310 fn test_from_bytes_to_b256_with_exact_32_bytes() {
311 let bytes = Bytes::from(vec![
313 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11,
314 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
315 0x20,
316 ]);
317 let result = from_bytes_to_b256::<serde_json::Value>(bytes).unwrap();
318 let expected = B256::from_slice(&[
319 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11,
320 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
321 0x20,
322 ]);
323 assert_eq!(result, expected);
324 }
325
326 #[test]
327 fn test_from_bytes_to_b256_with_input_too_long() {
328 let bytes = Bytes::from(vec![0x1; 33]); let result = from_bytes_to_b256::<serde_json::Value>(bytes);
331 assert!(result.is_err());
332 assert_eq!(result.unwrap_err().to_string(), "input too long to be a B256");
333 }
334
335 #[test]
336 fn test_from_bytes_to_b256_with_empty_input() {
337 let bytes = Bytes::from(vec![]);
339 let result = from_bytes_to_b256::<serde_json::Value>(bytes).unwrap();
340 let expected = B256::from_slice(&[0; 32]); assert_eq!(result, expected);
342 }
343}