Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

Commit

Permalink
fix(core): add from_x_or_hex to remaining genesis fields (#2360)
Browse files Browse the repository at this point in the history
* refactor from_u64_or_hex enum

* fix(core): add from_x_or_hex to remaining genesis fields

* convert to stringified numeric deserializers

* make StringifiedNumeric support arbitrary precision

* fix docs
  • Loading branch information
Rjected authored Apr 18, 2023
1 parent 80eac38 commit 6ebb1b2
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 127 deletions.
4 changes: 2 additions & 2 deletions ethers-core/src/types/fee.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::{types::U256, utils::from_int_or_hex};
use crate::types::{serde_helpers::deserialize_stringified_numeric, U256};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct FeeHistory {
pub base_fee_per_gas: Vec<U256>,
pub gas_used_ratio: Vec<f64>,
#[serde(deserialize_with = "from_int_or_hex")]
#[serde(deserialize_with = "deserialize_stringified_numeric")]
/// oldestBlock is returned as an unsigned integer up to geth v1.10.6. From
/// geth v1.10.7, this has been updated to return in the hex encoded form.
/// The custom deserializer allows backward compatibility for those clients
Expand Down
46 changes: 43 additions & 3 deletions ethers-core/src/types/serde_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Some convenient serde helpers

use crate::types::{BlockNumber, U256};
use crate::types::{BlockNumber, U256, U64};
use serde::{Deserialize, Deserializer};
use std::{
convert::{TryFrom, TryInto},
Expand Down Expand Up @@ -44,7 +44,7 @@ impl FromStr for Numeric {
pub enum StringifiedNumeric {
String(String),
U256(U256),
Num(u64),
Num(serde_json::Number),
}

impl TryFrom<StringifiedNumeric> for U256 {
Expand All @@ -53,7 +53,9 @@ impl TryFrom<StringifiedNumeric> for U256 {
fn try_from(value: StringifiedNumeric) -> Result<Self, Self::Error> {
match value {
StringifiedNumeric::U256(n) => Ok(n),
StringifiedNumeric::Num(n) => Ok(U256::from(n)),
StringifiedNumeric::Num(n) => {
Ok(U256::from_dec_str(&n.to_string()).map_err(|err| err.to_string())?)
}
StringifiedNumeric::String(s) => {
if let Ok(val) = s.parse::<u128>() {
Ok(val.into())
Expand All @@ -67,6 +69,18 @@ impl TryFrom<StringifiedNumeric> for U256 {
}
}

impl TryFrom<StringifiedNumeric> for U64 {
type Error = String;

fn try_from(value: StringifiedNumeric) -> Result<Self, Self::Error> {
let value = U256::try_from(value)?;
let mut be_bytes = [0u8; 32];
value.to_big_endian(&mut be_bytes);
U64::try_from(&be_bytes[value.leading_zeros() as usize / 8..])
.map_err(|err| err.to_string())
}
}

/// Supports parsing numbers as strings
///
/// See <https://github.com/gakonst/ethers-rs/issues/1507>
Expand Down Expand Up @@ -94,6 +108,32 @@ where
}
}

/// Supports parsing ethereum-types U64
///
/// See <https://github.com/gakonst/ethers-rs/issues/1507>
pub fn deserialize_stringified_eth_u64<'de, D>(deserializer: D) -> Result<U64, D::Error>
where
D: Deserializer<'de>,
{
let num = StringifiedNumeric::deserialize(deserializer)?;
num.try_into().map_err(serde::de::Error::custom)
}

/// Supports parsing ethereum-types `Option<U64>`
///
/// See <https://github.com/gakonst/ethers-rs/issues/1507>
pub fn deserialize_stringified_eth_u64_opt<'de, D>(deserializer: D) -> Result<Option<U64>, D::Error>
where
D: Deserializer<'de>,
{
if let Some(num) = Option::<StringifiedNumeric>::deserialize(deserializer)? {
let num: U64 = num.try_into().map_err(serde::de::Error::custom)?;
Ok(Some(num))
} else {
Ok(None)
}
}

/// Supports parsing u64
///
/// See <https://github.com/gakonst/ethers-rs/issues/1507>
Expand Down
7 changes: 2 additions & 5 deletions ethers-core/src/types/trace/geth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ pub use self::{
noop::NoopFrame,
pre_state::{PreStateConfig, PreStateFrame},
};
use crate::{
types::{Bytes, H256, U256},
utils::from_int_or_hex,
};
use crate::types::{serde_helpers::deserialize_stringified_numeric, Bytes, H256, U256};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::BTreeMap;
Expand All @@ -21,7 +18,7 @@ use std::collections::BTreeMap;
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct DefaultFrame {
pub failed: bool,
#[serde(deserialize_with = "from_int_or_hex")]
#[serde(deserialize_with = "deserialize_stringified_numeric")]
pub gas: U256,
#[serde(rename = "returnValue")]
pub return_value: Bytes,
Expand Down
16 changes: 10 additions & 6 deletions ethers-core/src/types/trace/geth/call.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
types::{Address, Bytes, NameOrAddress, H256, U256},
utils::from_int_or_hex,
use crate::types::{
serde_helpers::{deserialize_stringified_numeric, deserialize_stringified_numeric_opt},
Address, Bytes, NameOrAddress, H256, U256,
};
use serde::{Deserialize, Serialize};

Expand All @@ -12,11 +12,15 @@ pub struct CallFrame {
pub from: Address,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub to: Option<NameOrAddress>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[serde(
default,
deserialize_with = "deserialize_stringified_numeric_opt",
skip_serializing_if = "Option::is_none"
)]
pub value: Option<U256>,
#[serde(default, deserialize_with = "from_int_or_hex")]
#[serde(default, deserialize_with = "deserialize_stringified_numeric")]
pub gas: U256,
#[serde(default, deserialize_with = "from_int_or_hex", rename = "gasUsed")]
#[serde(default, deserialize_with = "deserialize_stringified_numeric", rename = "gasUsed")]
pub gas_used: U256,
pub input: Bytes,
#[serde(default, skip_serializing_if = "Option::is_none")]
Expand Down
9 changes: 3 additions & 6 deletions ethers-core/src/types/trace/geth/pre_state.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::{
types::{Address, H256, U256},
utils::from_int_or_hex_opt,
};
use crate::types::{serde_helpers::deserialize_stringified_numeric_opt, Address, H256, U256};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

Expand All @@ -26,15 +23,15 @@ pub struct DiffMode {
pub struct AccountState {
#[serde(
default,
deserialize_with = "from_int_or_hex_opt",
deserialize_with = "deserialize_stringified_numeric_opt",
skip_serializing_if = "Option::is_none"
)]
pub balance: Option<U256>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(
default,
deserialize_with = "from_int_or_hex_opt",
deserialize_with = "deserialize_stringified_numeric_opt",
skip_serializing_if = "Option::is_none"
)]
pub nonce: Option<U256>,
Expand Down
Loading

0 comments on commit 6ebb1b2

Please sign in to comment.