Skip to content

Commit 375f26d

Browse files
authored
ci: add scenarios (#4952)
1 parent 8871b76 commit 375f26d

9 files changed

+77
-31
lines changed

crates/edr_provider/src/requests/methods.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ pub enum MethodInvocation {
386386
SetStorageAt(
387387
#[serde(deserialize_with = "crate::requests::serde::deserialize_address")] Address,
388388
#[serde(deserialize_with = "crate::requests::serde::deserialize_storage_key")] U256,
389-
#[serde(deserialize_with = "crate::requests::serde::deserialize_storage_value")] U256,
389+
#[serde(with = "crate::requests::serde::storage_value")] U256,
390390
),
391391
/// hardhat_stopImpersonatingAccount
392392
#[serde(

crates/edr_provider/src/requests/serde.rs

+76-30
Original file line numberDiff line numberDiff line change
@@ -347,43 +347,68 @@ where
347347
Ok(result)
348348
}
349349

350-
/// Helper function for deserializing the JSON-RPC data type, specialized
351-
/// for a storage value.
352-
pub(crate) fn deserialize_storage_value<'de, DeserializerT>(
353-
deserializer: DeserializerT,
354-
) -> Result<U256, DeserializerT::Error>
355-
where
356-
DeserializerT: Deserializer<'de>,
357-
{
358-
let value = String::deserialize(deserializer).map_err(|error| {
359-
if let Some(value) = extract_value_from_serde_json_error(error.to_string().as_str()) {
360-
serde::de::Error::custom(format!(
361-
"This method only supports strings but input was: {value}"
362-
))
363-
} else {
364-
serde::de::Error::custom(format!(
365-
"Failed to deserialize quantity argument into string with error: '{error}'"
366-
))
367-
}
368-
})?;
350+
/// Helper module for serializing/deserializing the JSON-RPC data type,
351+
/// specialized for a storage value.
352+
pub(crate) mod storage_value {
353+
use serde::Serializer;
354+
355+
use super::{
356+
extract_value_from_serde_json_error, Deserialize, Deserializer, FromStr,
357+
STORAGE_VALUE_INVALID_LENGTH_ERROR_MESSAGE, U256,
358+
};
369359

370-
let error_message =
371-
|| serde::de::Error::custom(format!("invalid value \"{value}\" supplied to : DATA"));
360+
/// Helper function for deserializing the JSON-RPC data type, specialized
361+
/// for a storage value.
362+
pub fn deserialize<'de, DeserializerT>(
363+
deserializer: DeserializerT,
364+
) -> Result<U256, DeserializerT::Error>
365+
where
366+
DeserializerT: Deserializer<'de>,
367+
{
368+
let value = String::deserialize(deserializer).map_err(|error| {
369+
if let Some(value) = extract_value_from_serde_json_error(error.to_string().as_str()) {
370+
serde::de::Error::custom(format!(
371+
"This method only supports strings but input was: {value}"
372+
))
373+
} else {
374+
serde::de::Error::custom(format!(
375+
"Failed to deserialize quantity argument into string with error: '{error}'"
376+
))
377+
}
378+
})?;
372379

373-
if !value.starts_with("0x") {
374-
return Err(error_message());
375-
}
380+
let error_message =
381+
|| serde::de::Error::custom(format!("invalid value \"{value}\" supplied to : DATA"));
376382

377-
// Remove 2 characters for the "0x" prefix and divide by 2 because each byte is
378-
// represented by 2 hex characters.
379-
let length = (value.len() - 2) / 2;
380-
if length != 32 {
381-
return Err(serde::de::Error::custom(format!(
383+
if !value.starts_with("0x") {
384+
return Err(error_message());
385+
}
386+
387+
// Remove 2 characters for the "0x" prefix and divide by 2 because each byte is
388+
// represented by 2 hex characters.
389+
let length = (value.len() - 2) / 2;
390+
if length != 32 {
391+
return Err(serde::de::Error::custom(format!(
382392
"{STORAGE_VALUE_INVALID_LENGTH_ERROR_MESSAGE} Received {value}, which is {length} bytes long."
383393
)));
394+
}
395+
396+
U256::from_str(&value).map_err(|_error| error_message())
384397
}
385398

386-
U256::from_str(&value).map_err(|_error| error_message())
399+
/// Serialize U256 with padding to make sure it's accepted by
400+
/// `deserialize_storage_value` which expects padded values (as opposed to
401+
/// the Ethereum JSON-RPC spec which expects values without padding).
402+
pub fn serialize<SerializerT>(
403+
value: &U256,
404+
serializer: SerializerT,
405+
) -> Result<SerializerT::Ok, SerializerT::Error>
406+
where
407+
SerializerT: Serializer,
408+
{
409+
let padded = format!("0x{value:0>64x}");
410+
serializer.serialize_str(&padded)
411+
}
387412
}
388413

389414
/// Helper function for deserializing the payload of an `eth_signTypedData_v4`
@@ -454,4 +479,25 @@ mod tests {
454479
"actual: {error}"
455480
);
456481
}
482+
483+
#[test]
484+
fn serialize_storage_value_round_trip() {
485+
#[derive(Serialize, Deserialize)]
486+
struct Test {
487+
#[serde(with = "storage_value")]
488+
n: U256,
489+
}
490+
491+
let u256_json = r#""0x313f922be1649cec058ec0f076664500c78bdc0b""#;
492+
let n: U256 = serde_json::from_str(u256_json).unwrap();
493+
494+
let test = Test { n };
495+
496+
let json = serde_json::to_string(&test).unwrap();
497+
assert!(json.contains("0x000000000000000000000000313f922be1649cec058ec0f076664500c78bdc0b"));
498+
499+
let parsed = serde_json::from_str::<Test>(&json).unwrap();
500+
501+
assert_eq!(parsed.n, n);
502+
}
457503
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2.32 MB
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)