From b354102073379990f2816d24c45290a77aca37ed Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 28 Jul 2022 20:06:06 +0200 Subject: [PATCH 1/4] fix: use fully qualified path for Result (#1527) --- .../ethers-contract-abigen/src/contract/events.rs | 2 +- .../ethers-contract-abigen/src/contract/methods.rs | 4 ++-- .../ethers-contract-derive/src/abi_ty.rs | 8 ++++---- .../ethers-contract-derive/src/abigen.rs | 2 +- ethers-contract/ethers-contract-derive/src/call.rs | 2 +- ethers-contract/ethers-contract-derive/src/codec.rs | 2 +- ethers-contract/ethers-contract-derive/src/event.rs | 2 +- ethers-contract/tests/it/common/derive.rs | 13 +++++++++++++ 8 files changed, 24 insertions(+), 11 deletions(-) diff --git a/ethers-contract/ethers-contract-abigen/src/contract/events.rs b/ethers-contract/ethers-contract-abigen/src/contract/events.rs index d7fb7b5e..9c098635 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract/events.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract/events.rs @@ -77,7 +77,7 @@ impl Context { } impl #ethers_contract::EthLogDecode for #enum_name { - fn decode_log(log: &#ethers_core::abi::RawLog) -> Result + fn decode_log(log: &#ethers_core::abi::RawLog) -> ::std::result::Result where Self: Sized, { diff --git a/ethers-contract/ethers-contract-abigen/src/contract/methods.rs b/ethers-contract/ethers-contract-abigen/src/contract/methods.rs index 912444c7..3894802b 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract/methods.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract/methods.rs @@ -91,7 +91,7 @@ impl Context { /// let msg = greeter_contract.greet().call().await.unwrap(); /// # } /// ``` - pub fn deploy(client: ::std::sync::Arc, constructor_args: T) -> Result<#ethers_contract::builders::ContractDeployer, #ethers_contract::ContractError> { + pub fn deploy(client: ::std::sync::Arc, constructor_args: T) -> ::std::result::Result<#ethers_contract::builders::ContractDeployer, #ethers_contract::ContractError> { let factory = #ethers_contract::ContractFactory::new(#get_abi, #get_bytecode, client); let deployer = factory.deploy(constructor_args)?; let deployer = #ethers_contract::ContractDeployer::new(deployer); @@ -219,7 +219,7 @@ impl Context { } impl #ethers_core::abi::AbiDecode for #enum_name { - fn decode(data: impl AsRef<[u8]>) -> Result { + fn decode(data: impl AsRef<[u8]>) -> ::std::result::Result { #( if let Ok(decoded) = <#struct_names as #ethers_core::abi::AbiDecode>::decode(data.as_ref()) { return Ok(#enum_name::#variant_names(decoded)) diff --git a/ethers-contract/ethers-contract-derive/src/abi_ty.rs b/ethers-contract/ethers-contract-derive/src/abi_ty.rs index 18b43669..442d9d1d 100644 --- a/ethers-contract/ethers-contract-derive/src/abi_ty.rs +++ b/ethers-contract/ethers-contract-derive/src/abi_ty.rs @@ -152,7 +152,7 @@ pub fn derive_tokenizeable_impl(input: &DeriveInput) -> proc_macro2::TokenStream #tokenize_predicates { - fn from_token(token: #core_crate::abi::Token) -> Result where + fn from_token(token: #core_crate::abi::Token) -> ::std::result::Result where Self: Sized { #from_token_impl } @@ -174,7 +174,7 @@ fn tokenize_unit_type(name: &Ident) -> TokenStream { let ethers_core = ethers_core_crate(); quote! { impl #ethers_core::abi::Tokenizable for #name { - fn from_token(token: #ethers_core::abi::Token) -> Result where + fn from_token(token: #ethers_core::abi::Token) -> ::std::result::Result where Self: Sized { if let #ethers_core::abi::Token::Tuple(tokens) = token { if !tokens.is_empty() { @@ -210,7 +210,7 @@ fn tokenize_unit_type(name: &Ident) -> TokenStream { fn tokenize_enum<'a>( enum_name: &Ident, variants: impl Iterator + 'a, -) -> Result { +) -> ::std::result::Result { let ethers_core = ethers_core_crate(); let mut into_tokens = TokenStream::new(); @@ -252,7 +252,7 @@ fn tokenize_enum<'a>( Ok(quote! { impl #ethers_core::abi::Tokenizable for #enum_name { - fn from_token(token: #ethers_core::abi::Token) -> Result where + fn from_token(token: #ethers_core::abi::Token) -> ::std::result::Result where Self: Sized { #from_tokens Err(#ethers_core::abi::InvalidOutputType("Failed to decode all type variants".to_string())) diff --git a/ethers-contract/ethers-contract-derive/src/abigen.rs b/ethers-contract/ethers-contract-derive/src/abigen.rs index f1c47e3b..a91334ed 100644 --- a/ethers-contract/ethers-contract-derive/src/abigen.rs +++ b/ethers-contract/ethers-contract-derive/src/abigen.rs @@ -27,7 +27,7 @@ pub(crate) struct Contracts { } impl Contracts { - pub(crate) fn expand(self) -> Result { + pub(crate) fn expand(self) -> ::std::result::Result { let mut expansions = Vec::with_capacity(self.inner.len()); // expand all contracts diff --git a/ethers-contract/ethers-contract-derive/src/call.rs b/ethers-contract/ethers-contract-derive/src/call.rs index 15f901a0..f86163ed 100644 --- a/ethers-contract/ethers-contract-derive/src/call.rs +++ b/ethers-contract/ethers-contract-derive/src/call.rs @@ -95,7 +95,7 @@ pub fn derive_trait_impls( } impl #core_crate::abi::AbiDecode for #struct_name { - fn decode(bytes: impl AsRef<[u8]>) -> Result { + fn decode(bytes: impl AsRef<[u8]>) -> ::std::result::Result { #decode_impl } } diff --git a/ethers-contract/ethers-contract-derive/src/codec.rs b/ethers-contract/ethers-contract-derive/src/codec.rs index 54a577f2..15472fc2 100644 --- a/ethers-contract/ethers-contract-derive/src/codec.rs +++ b/ethers-contract/ethers-contract-derive/src/codec.rs @@ -12,7 +12,7 @@ pub fn derive_codec_impl(input: &DeriveInput) -> proc_macro2::TokenStream { quote! { impl #core_crate::abi::AbiDecode for #name { - fn decode(bytes: impl AsRef<[u8]>) -> Result { + fn decode(bytes: impl AsRef<[u8]>) -> ::std::result::Result { if let #core_crate::abi::ParamType::Tuple(params) = ::param_type() { let tokens = #core_crate::abi::decode(¶ms, bytes.as_ref())?; Ok(::from_token(#core_crate::abi::Token::Tuple(tokens))?) diff --git a/ethers-contract/ethers-contract-derive/src/event.rs b/ethers-contract/ethers-contract-derive/src/event.rs index 05d02f4f..0e56314f 100644 --- a/ethers-contract/ethers-contract-derive/src/event.rs +++ b/ethers-contract/ethers-contract-derive/src/event.rs @@ -95,7 +95,7 @@ pub(crate) fn derive_eth_event_impl(input: DeriveInput) -> TokenStream { #abi.into() } - fn decode_log(log: &#core_crate::abi::RawLog) -> Result where Self: Sized { + fn decode_log(log: &#core_crate::abi::RawLog) -> ::std::result::Result where Self: Sized { #decode_log_impl } diff --git a/ethers-contract/tests/it/common/derive.rs b/ethers-contract/tests/it/common/derive.rs index d856cbb5..3198cc9e 100644 --- a/ethers-contract/tests/it/common/derive.rs +++ b/ethers-contract/tests/it/common/derive.rs @@ -605,3 +605,16 @@ fn eth_display_works_on_ethers_bytes() { let s = format!("{}", call); assert_eq!(s, "0xaaaaaa"); } + +#[test] +fn can_use_result_name() { + abigen!( + ResultContract, + r#"[ + struct Result {uint256 result;} + result(Result result) (uint256) + ]"#, + ); + + let _call = ResultCall { result: Result { result: U256::zero() } }; +} From 2a14e5510dd56d406d8eee0a46d8572a7f732e80 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 28 Jul 2022 20:06:15 +0200 Subject: [PATCH 2/4] chore(clippy): make clippy happy (#1525) --- ethers-core/src/types/block.rs | 24 ++++++++++++-------- ethers-core/src/types/transaction/request.rs | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/ethers-core/src/types/block.rs b/ethers-core/src/types/block.rs index ce0d4e28..03a2dc33 100644 --- a/ethers-core/src/types/block.rs +++ b/ethers-core/src/types/block.rs @@ -764,11 +764,13 @@ mod tests { #[test] fn test_next_block_base_fee() { // - let mut block_14402566 = Block::::default(); - block_14402566.number = Some(U64::from(14402566u64)); - block_14402566.base_fee_per_gas = Some(U256::from(36_803_013_756u128)); - block_14402566.gas_limit = U256::from(30_087_887u128); - block_14402566.gas_used = U256::from(2_023_848u128); + let block_14402566: Block = Block { + number: Some(U64::from(14402566u64)), + base_fee_per_gas: Some(U256::from(36_803_013_756u128)), + gas_limit: U256::from(30_087_887u128), + gas_used: U256::from(2_023_848u128), + ..Default::default() + }; assert_eq!(block_14402566.base_fee_per_gas, Some(U256::from(36_803_013_756u128))); assert_eq!(block_14402566.gas_target(), U256::from(15_043_943u128)); @@ -776,11 +778,13 @@ mod tests { assert_eq!(block_14402566.next_block_base_fee(), Some(U256::from(32_821_521_542u128))); // https://etherscan.io/block/14402712 - let mut block_14402712 = Block::::default(); - block_14402712.number = Some(U64::from(14402712u64)); - block_14402712.base_fee_per_gas = Some(U256::from(24_870_031_149u128)); - block_14402712.gas_limit = U256::from(30_000_000u128); - block_14402712.gas_used = U256::from(29_999_374u128); + let block_14402712: Block = Block { + number: Some(U64::from(14402712u64)), + base_fee_per_gas: Some(U256::from(24_870_031_149u128)), + gas_limit: U256::from(30_000_000u128), + gas_used: U256::from(29_999_374u128), + ..Default::default() + }; assert_eq!(block_14402712.base_fee_per_gas, Some(U256::from(24_870_031_149u128))); assert_eq!(block_14402712.gas_target(), U256::from(15_000_000u128)); diff --git a/ethers-core/src/types/transaction/request.rs b/ethers-core/src/types/transaction/request.rs index 25270d92..34a47f86 100644 --- a/ethers-core/src/types/transaction/request.rs +++ b/ethers-core/src/types/transaction/request.rs @@ -547,7 +547,7 @@ mod tests { let addresses = raw_addresses .iter() - .map(|addr| NameOrAddress::Address(Address::from_str(*addr).unwrap())); + .map(|addr| NameOrAddress::Address(Address::from_str(addr).unwrap())); // decoding will do sender recovery and we don't expect any of these to error, so we should // check that the address matches for each decoded transaction From 81a2a5ed68b791d7f8348930a38c40a293d916db Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 28 Jul 2022 20:06:56 +0200 Subject: [PATCH 3/4] fix(etherscan): support stringified numbers in response (#1524) * fix(etherscan): support stringified numbers in response * feat: add helper function * improve string parsing * chore(clippy): make clippy happy --- ethers-core/src/types/serde_helpers.rs | 119 +++++++++++++++++++++++-- ethers-etherscan/src/account.rs | 76 ++++++++++++---- ethers-etherscan/src/gas.rs | 12 +-- ethers-etherscan/src/transaction.rs | 9 +- 4 files changed, 179 insertions(+), 37 deletions(-) diff --git a/ethers-core/src/types/serde_helpers.rs b/ethers-core/src/types/serde_helpers.rs index bd83a573..5672279a 100644 --- a/ethers-core/src/types/serde_helpers.rs +++ b/ethers-core/src/types/serde_helpers.rs @@ -1,9 +1,11 @@ //! Some convenient serde helpers use crate::types::{BlockNumber, U256}; -use ethabi::ethereum_types::FromDecStrErr; use serde::{Deserialize, Deserializer}; -use std::convert::TryFrom; +use std::{ + convert::{TryFrom, TryInto}, + str::FromStr, +}; /// Helper type to parse both `u64` and `U256` #[derive(Copy, Clone, Deserialize)] @@ -22,7 +24,21 @@ impl From for U256 { } } -/// Helper type to parse both `u64` and `U256` +impl FromStr for Numeric { + type Err = String; + + fn from_str(s: &str) -> Result { + if let Ok(val) = s.parse::() { + Ok(Numeric::U256(val.into())) + } else if s.starts_with("0x") { + U256::from_str(s).map(Numeric::U256).map_err(|err| err.to_string()) + } else { + U256::from_dec_str(s).map(Numeric::U256).map_err(|err| err.to_string()) + } + } +} + +/// Helper type to parse numeric strings, `u64` and `U256` #[derive(Deserialize, Debug, Clone)] #[serde(untagged)] pub enum StringifiedNumeric { @@ -32,7 +48,7 @@ pub enum StringifiedNumeric { } impl TryFrom for U256 { - type Error = FromDecStrErr; + type Error = String; fn try_from(value: StringifiedNumeric) -> Result { match value { @@ -41,14 +57,71 @@ impl TryFrom for U256 { StringifiedNumeric::String(s) => { if let Ok(val) = s.parse::() { Ok(val.into()) + } else if s.starts_with("0x") { + U256::from_str(&s).map_err(|err| err.to_string()) } else { - U256::from_dec_str(&s) + U256::from_dec_str(&s).map_err(|err| err.to_string()) } } } } } +/// Supports parsing numbers as strings +/// +/// See +pub fn deserialize_stringified_numeric<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let num = StringifiedNumeric::deserialize(deserializer)?; + num.try_into().map_err(serde::de::Error::custom) +} + +/// Supports parsing numbers as strings +/// +/// See +pub fn deserialize_stringified_numeric_opt<'de, D>( + deserializer: D, +) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + if let Some(num) = Option::::deserialize(deserializer)? { + num.try_into().map(Some).map_err(serde::de::Error::custom) + } else { + Ok(None) + } +} + +/// Supports parsing u64 +/// +/// See +pub fn deserialize_stringified_u64<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let num = StringifiedNumeric::deserialize(deserializer)?; + let num: U256 = num.try_into().map_err(serde::de::Error::custom)?; + num.try_into().map_err(serde::de::Error::custom) +} + +/// Supports parsing u64 +/// +/// See +pub fn deserialize_stringified_u64_opt<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + if let Some(num) = Option::::deserialize(deserializer)? { + let num: U256 = num.try_into().map_err(serde::de::Error::custom)?; + let num: u64 = num.try_into().map_err(serde::de::Error::custom)?; + Ok(Some(num)) + } else { + Ok(None) + } +} + /// Helper type to deserialize sequence of numbers #[derive(Deserialize)] #[serde(untagged)] @@ -94,6 +167,42 @@ where Ok(num) } +/// Helper type to parse numeric strings, `u64` and `U256` +#[derive(Deserialize, Debug, Clone)] +#[serde(untagged)] +pub enum StringifiedBlockNumber { + Numeric(StringifiedNumeric), + BlockNumber(BlockNumber), +} + +impl TryFrom for BlockNumber { + type Error = String; + + fn try_from(value: StringifiedBlockNumber) -> Result { + match value { + StringifiedBlockNumber::Numeric(num) => { + let num = U256::try_from(num) + .and_then(|num| u64::try_from(num).map_err(str::to_string))?; + Ok(BlockNumber::Number(num.into())) + } + StringifiedBlockNumber::BlockNumber(b) => Ok(b), + } + } +} + +/// Supports parsing block number as strings +/// +/// See +pub fn deserialize_stringified_block_number<'de, D>( + deserializer: D, +) -> Result +where + D: Deserializer<'de>, +{ + let num = StringifiedBlockNumber::deserialize(deserializer)?; + num.try_into().map_err(serde::de::Error::custom) +} + /// Various block number representations, See [`lenient_block_number()`] #[derive(Clone, Copy, Deserialize)] #[serde(untagged)] diff --git a/ethers-etherscan/src/account.rs b/ethers-etherscan/src/account.rs index 7f01c578..a33f4484 100644 --- a/ethers-etherscan/src/account.rs +++ b/ethers-etherscan/src/account.rs @@ -1,17 +1,15 @@ +use crate::{Client, EtherscanError, Query, Response, Result}; +use ethers_core::{ + abi::Address, + types::{serde_helpers::*, BlockNumber, Bytes, H256, U256}, +}; +use serde::{Deserialize, Serialize}; use std::{ borrow::Cow, collections::HashMap, fmt::{Display, Error, Formatter}, }; -use ethers_core::{ - abi::Address, - types::{BlockNumber, Bytes, H256, U256, U64}, -}; -use serde::{Deserialize, Serialize}; - -use crate::{Client, EtherscanError, Query, Response, Result}; - /// The raw response from the balance-related API endpoints #[derive(Debug, Serialize, Deserialize)] pub struct AccountBalance { @@ -100,6 +98,7 @@ impl GenesisOption { #[serde(rename_all = "camelCase")] pub struct NormalTransaction { pub is_error: String, + #[serde(deserialize_with = "deserialize_stringified_block_number")] pub block_number: BlockNumber, pub time_stamp: String, #[serde(with = "jsonstring")] @@ -108,12 +107,16 @@ pub struct NormalTransaction { pub nonce: GenesisOption, #[serde(with = "jsonstring")] pub block_hash: GenesisOption, - pub transaction_index: Option, + #[serde(deserialize_with = "deserialize_stringified_u64_opt")] + pub transaction_index: Option, #[serde(with = "jsonstring")] pub from: GenesisOption
, pub to: Option
, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub value: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric_opt")] pub gas_price: Option, #[serde(rename = "txreceipt_status")] pub tx_receipt_status: String, @@ -121,21 +124,26 @@ pub struct NormalTransaction { pub input: GenesisOption, #[serde(with = "jsonstring")] pub contract_address: GenesisOption
, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas_used: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub cumulative_gas_used: U256, - pub confirmations: U64, + #[serde(deserialize_with = "deserialize_stringified_u64")] + pub confirmations: u64, } /// The raw response from the internal transaction list API endpoint #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct InternalTransaction { + #[serde(deserialize_with = "deserialize_stringified_block_number")] pub block_number: BlockNumber, pub time_stamp: String, pub hash: H256, pub from: Address, #[serde(with = "jsonstring")] pub to: GenesisOption
, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub value: U256, #[serde(with = "jsonstring")] pub contract_address: GenesisOption
, @@ -143,7 +151,9 @@ pub struct InternalTransaction { pub input: GenesisOption, #[serde(rename = "type")] pub result_type: String, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas_used: U256, pub trace_id: String, pub is_error: String, @@ -154,35 +164,46 @@ pub struct InternalTransaction { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ERC20TokenTransferEvent { + #[serde(deserialize_with = "deserialize_stringified_block_number")] pub block_number: BlockNumber, pub time_stamp: String, pub hash: H256, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub nonce: U256, pub block_hash: H256, pub from: Address, pub contract_address: Address, pub to: Option
, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub value: U256, pub token_name: String, pub token_symbol: String, pub token_decimal: String, - pub transaction_index: U64, + #[serde(deserialize_with = "deserialize_stringified_u64")] + pub transaction_index: u64, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric_opt")] pub gas_price: Option, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas_used: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub cumulative_gas_used: U256, /// deprecated pub input: String, - pub confirmations: U64, + #[serde(deserialize_with = "deserialize_stringified_u64")] + pub confirmations: u64, } /// The raw response from the ERC721 transfer list API endpoint #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ERC721TokenTransferEvent { + #[serde(deserialize_with = "deserialize_stringified_block_number")] pub block_number: BlockNumber, pub time_stamp: String, pub hash: H256, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub nonce: U256, pub block_hash: H256, pub from: Address, @@ -193,23 +214,31 @@ pub struct ERC721TokenTransferEvent { pub token_name: String, pub token_symbol: String, pub token_decimal: String, - pub transaction_index: U64, + #[serde(deserialize_with = "deserialize_stringified_u64")] + pub transaction_index: u64, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric_opt")] pub gas_price: Option, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas_used: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub cumulative_gas_used: U256, /// deprecated pub input: String, - pub confirmations: U64, + #[serde(deserialize_with = "deserialize_stringified_u64")] + pub confirmations: u64, } /// The raw response from the ERC1155 transfer list API endpoint #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ERC1155TokenTransferEvent { + #[serde(deserialize_with = "deserialize_stringified_block_number")] pub block_number: BlockNumber, pub time_stamp: String, pub hash: H256, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub nonce: U256, pub block_hash: H256, pub from: Address, @@ -220,20 +249,27 @@ pub struct ERC1155TokenTransferEvent { pub token_value: String, pub token_name: String, pub token_symbol: String, - pub transaction_index: U64, + #[serde(deserialize_with = "deserialize_stringified_u64")] + pub transaction_index: u64, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric_opt")] pub gas_price: Option, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub gas_used: U256, + #[serde(deserialize_with = "deserialize_stringified_numeric")] pub cumulative_gas_used: U256, /// deprecated pub input: String, - pub confirmations: U64, + #[serde(deserialize_with = "deserialize_stringified_u64")] + pub confirmations: u64, } /// The raw response from the mined blocks API endpoint #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct MinedBlock { + #[serde(deserialize_with = "deserialize_stringified_block_number")] pub block_number: BlockNumber, pub time_stamp: String, pub block_reward: String, @@ -739,8 +775,12 @@ mod tests { ), None, ) - .await; - assert!(txs.is_ok()); + .await + .unwrap(); + let tx = txs.get(0).unwrap(); + assert_eq!(tx.gas_used, 93657u64.into()); + assert_eq!(tx.nonce, 10u64.into()); + assert_eq!(tx.block_number, 2228258u64.into()); }) .await } diff --git a/ethers-etherscan/src/gas.rs b/ethers-etherscan/src/gas.rs index e9c7e1de..94e93b1e 100644 --- a/ethers-etherscan/src/gas.rs +++ b/ethers-etherscan/src/gas.rs @@ -70,15 +70,11 @@ impl Client { #[cfg(test)] mod tests { - use std::time::Duration; - - use serial_test::serial; - - use ethers_core::types::Chain; - - use crate::tests::run_at_least_duration; - use super::*; + use crate::tests::run_at_least_duration; + use ethers_core::types::Chain; + use serial_test::serial; + use std::time::Duration; #[tokio::test] #[serial] diff --git a/ethers-etherscan/src/transaction.rs b/ethers-etherscan/src/transaction.rs index e916d55a..9259b097 100644 --- a/ethers-etherscan/src/transaction.rs +++ b/ethers-etherscan/src/transaction.rs @@ -52,13 +52,10 @@ impl Client { #[cfg(test)] mod tests { - use std::time::Duration; - - use serial_test::serial; - - use crate::{tests::run_at_least_duration, Chain}; - use super::*; + use crate::{tests::run_at_least_duration, Chain}; + use serial_test::serial; + use std::time::Duration; #[tokio::test] #[serial] From 16f686df265c6cfad4ce0ebba55d803be77a3e24 Mon Sep 17 00:00:00 2001 From: Mark Tyneway Date: Thu, 28 Jul 2022 11:07:24 -0700 Subject: [PATCH 4/4] ethers-solc: add immutableReferences output selector (#1523) * ethers-solc: add immutableReferences output selector It is a property on the deployed bytecode object on the compiler output. This is the precursor for `forge inspect immutableReferences`. * chore: update changelog --- CHANGELOG.md | 1 + ethers-solc/src/artifacts/output_selection.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fefd4112..86013cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Unreleased +- Add `evm.deployedBytecode.immutableReferences` output selector [#1523](https://github.com/gakonst/ethers-rs/pull/1523) - Added `get_erc1155_token_transfer_events` function for etherscan client [#1503](https://github.com/gakonst/ethers-rs/pull/1503) - Add support for Geth `debug_traceTransaction` [#1469](https://github.com/gakonst/ethers-rs/pull/1469) - Use correct, new transaction type for `typool_content` RPC endpoint [#1501](https://github.com/gakonst/ethers-rs/pull/1501) diff --git a/ethers-solc/src/artifacts/output_selection.rs b/ethers-solc/src/artifacts/output_selection.rs index b5546350..a016b6ef 100644 --- a/ethers-solc/src/artifacts/output_selection.rs +++ b/ethers-solc/src/artifacts/output_selection.rs @@ -427,6 +427,7 @@ pub enum DeployedBytecodeOutputSelection { SourceMap, LinkReferences, GeneratedSources, + ImmutableReferences, } impl Serialize for DeployedBytecodeOutputSelection { @@ -465,6 +466,9 @@ impl fmt::Display for DeployedBytecodeOutputSelection { DeployedBytecodeOutputSelection::GeneratedSources => { f.write_str("evm.deployedBytecode.generatedSources") } + DeployedBytecodeOutputSelection::ImmutableReferences => { + f.write_str("evm.deployedBytecode.immutableReferences") + } } } } @@ -487,6 +491,9 @@ impl FromStr for DeployedBytecodeOutputSelection { "evm.deployedBytecode.generatedSources" => { Ok(DeployedBytecodeOutputSelection::GeneratedSources) } + "evm.deployedBytecode.immutableReferences" => { + Ok(DeployedBytecodeOutputSelection::ImmutableReferences) + } s => Err(format!("Invalid deployedBytecode selection: {}", s)), } } @@ -573,4 +580,13 @@ mod tests { let s = serde_json::to_string(&empty).unwrap(); assert_eq!(s, r#"{"contract.sol":{"*":[]}}"#); } + + #[test] + fn deployed_bytecode_from_str() { + assert_eq!( + DeployedBytecodeOutputSelection::from_str("evm.deployedBytecode.immutableReferences") + .unwrap(), + DeployedBytecodeOutputSelection::ImmutableReferences + ) + } }