@@ -347,43 +347,68 @@ where
347
347
Ok ( result)
348
348
}
349
349
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
+ } ;
369
359
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
+ } ) ?;
372
379
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" ) ) ;
376
382
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 ! (
382
392
"{STORAGE_VALUE_INVALID_LENGTH_ERROR_MESSAGE} Received {value}, which is {length} bytes long."
383
393
) ) ) ;
394
+ }
395
+
396
+ U256 :: from_str ( & value) . map_err ( |_error| error_message ( ) )
384
397
}
385
398
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
+ }
387
412
}
388
413
389
414
/// Helper function for deserializing the payload of an `eth_signTypedData_v4`
@@ -454,4 +479,25 @@ mod tests {
454
479
"actual: {error}"
455
480
) ;
456
481
}
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
+ }
457
503
}
0 commit comments