Skip to content

Commit

Permalink
Fix deserialization failure of blockscout contract_source response
Browse files Browse the repository at this point in the history
  • Loading branch information
ckoopmann committed Dec 21, 2023
1 parent ec44deb commit 791c05b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
serde_helpers::deserialize_stringified_u64,
serde_helpers::{deserialize_stringified_u64, deserialize_stringified_bool_or_u64},
source_tree::{SourceTree, SourceTreeEntry},
utils::{deserialize_address_opt, deserialize_source_code},
Client, EtherscanError, Response, Result,
Expand Down Expand Up @@ -128,14 +128,15 @@ pub struct Metadata {
pub compiler_version: String,

/// Whether the optimizer was used. This value should only be 0 or 1.
#[serde(deserialize_with = "deserialize_stringified_u64")]
#[serde(deserialize_with = "deserialize_stringified_bool_or_u64")]
pub optimization_used: u64,

/// The number of optimizations performed.
#[serde(deserialize_with = "deserialize_stringified_u64")]
#[serde(deserialize_with = "deserialize_stringified_u64", alias="OptimizationRuns")]
pub runs: u64,

/// The constructor arguments the contract was deployed with.
#[serde(default)]
pub constructor_arguments: Bytes,

/// The version of the EVM the contract was deployed in. Can be either a variant of EvmVersion
Expand All @@ -144,13 +145,15 @@ pub struct Metadata {
pub evm_version: String,

// ?
#[serde(default)]
pub library: String,

/// The license of the contract.
#[serde(default)]
pub license_type: String,

/// Whether this contract is a proxy. This value should only be 0 or 1.
#[serde(deserialize_with = "deserialize_stringified_u64")]
#[serde(deserialize_with = "deserialize_stringified_bool_or_u64", alias="IsProxy")]
pub proxy: u64,

/// If this contract is a proxy, the address of its implementation.
Expand All @@ -162,6 +165,7 @@ pub struct Metadata {
pub implementation: Option<Address>,

/// The swarm source of the contract.
#[serde(default)]
pub swarm_source: String,
}

Expand Down
28 changes: 28 additions & 0 deletions src/serde_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,34 @@ impl TryFrom<StringifiedNumeric> for U64 {
}
}


#[derive(Deserialize)]
#[serde(untagged)]
enum BoolOrU64 {
#[serde(deserialize_with = "deserialize_stringified_u64")]
U64(u64),
Bool(String),
}


/// Supports parsing either a u64 or a boolean (which will then be converted to u64)
/// Implemented to binary fields such as "OptimizationUsed" which are formatted either as 0/1 or
/// "true/"false" by different block explorers (e.g. etherscan vs blockscout)
pub fn deserialize_stringified_bool_or_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
where
D: Deserializer<'de>,
{
let num = BoolOrU64::deserialize(deserializer)?;
match num {
BoolOrU64::Bool(b) => {
let b = b.parse::<bool>().map_err(serde::de::Error::custom)?;
let u = if b { 1 } else { 0 };
Ok(u)
}
BoolOrU64::U64(u) => Ok(u),
}
}

/// Supports parsing u64
///
/// See <https://github.com/gakonst/ethers-rs/issues/1507>
Expand Down

0 comments on commit 791c05b

Please sign in to comment.