fix(core, etherscan): RawAbi and Abi (#1757)

This commit is contained in:
DaniPopes 2022-09-29 20:15:04 +02:00 committed by GitHub
parent 62beb6cf53
commit d2c9db5ae9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 47 additions and 53 deletions

View File

@ -7,12 +7,9 @@ pub(crate) mod structs;
mod types; mod types;
use super::{util, Abigen}; use super::{util, Abigen};
use crate::{ use crate::contract::{methods::MethodAlias, structs::InternalStructs};
contract::{methods::MethodAlias, structs::InternalStructs},
rawabi::JsonAbi,
};
use ethers_core::{ use ethers_core::{
abi::{Abi, AbiParser, ErrorExt, EventExt}, abi::{Abi, AbiParser, ErrorExt, EventExt, JsonAbi},
macros::{ethers_contract_crate, ethers_core_crate, ethers_providers_crate}, macros::{ethers_contract_crate, ethers_core_crate, ethers_providers_crate},
types::Bytes, types::Bytes,
}; };

View File

@ -1,13 +1,12 @@
//! Methods for expanding structs //! Methods for expanding structs
use crate::{ use crate::{
contract::{types, Context}, contract::{types, Context},
rawabi::{Component, RawAbi},
util, util,
}; };
use ethers_core::{ use ethers_core::{
abi::{ abi::{
struct_def::{FieldDeclaration, FieldType, StructFieldType, StructType}, struct_def::{FieldDeclaration, FieldType, StructFieldType, StructType},
HumanReadableParser, ParamType, SolStruct, Component, HumanReadableParser, ParamType, RawAbi, SolStruct,
}, },
macros::ethers_contract_crate, macros::ethers_contract_crate,
}; };

View File

@ -16,9 +16,6 @@ pub mod contract;
pub use contract::structs::InternalStructs; pub use contract::structs::InternalStructs;
use contract::Context; use contract::Context;
pub mod rawabi;
pub use rawabi::RawAbi;
mod rustfmt; mod rustfmt;
mod source; mod source;
mod util; mod util;

View File

@ -49,7 +49,7 @@ pub mod builders {
#[cfg(any(test, feature = "abigen"))] #[cfg(any(test, feature = "abigen"))]
#[cfg_attr(docsrs, doc(cfg(feature = "abigen")))] #[cfg_attr(docsrs, doc(cfg(feature = "abigen")))]
pub use ethers_contract_abigen::{ pub use ethers_contract_abigen::{
Abigen, ContractFilter, ExcludeContracts, InternalStructs, MultiAbigen, RawAbi, SelectContracts, Abigen, ContractFilter, ExcludeContracts, InternalStructs, MultiAbigen, SelectContracts,
}; };
#[cfg(any(test, feature = "abigen"))] #[cfg(any(test, feature = "abigen"))]

View File

@ -22,6 +22,10 @@ mod human_readable;
pub use human_readable::{ pub use human_readable::{
lexer::HumanReadableParser, parse as parse_abi, parse_str as parse_abi_str, AbiParser, lexer::HumanReadableParser, parse as parse_abi, parse_str as parse_abi_str, AbiParser,
}; };
mod raw;
pub use raw::{AbiObject, Component, Item, JsonAbi, RawAbi};
mod sealed { mod sealed {
use ethabi::{Event, Function}; use ethabi::{Event, Function};

View File

@ -2,7 +2,7 @@
//! raw content of the ABI. //! raw content of the ABI.
#![allow(missing_docs)] #![allow(missing_docs)]
use ethers_core::types::Bytes; use crate::types::Bytes;
use serde::{ use serde::{
de::{MapAccess, SeqAccess, Visitor}, de::{MapAccess, SeqAccess, Visitor},
Deserialize, Deserializer, Serialize, Deserialize, Deserializer, Serialize,
@ -109,7 +109,7 @@ pub struct Component {
/// Represents contract ABI input variants /// Represents contract ABI input variants
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(untagged)] #[serde(untagged)]
pub(crate) enum JsonAbi { pub enum JsonAbi {
/// json object input as `{"abi": [..], "bin": "..."}` /// json object input as `{"abi": [..], "bin": "..."}`
Object(AbiObject), Object(AbiObject),
/// json array input as `[]` /// json array input as `[]`
@ -125,7 +125,7 @@ where
} }
/// Contract ABI and optional bytecode as JSON object /// Contract ABI and optional bytecode as JSON object
pub(crate) struct AbiObject { pub struct AbiObject {
pub abi: RawAbi, pub abi: RawAbi,
pub bytecode: Option<Bytes>, pub bytecode: Option<Bytes>,
} }
@ -158,7 +158,7 @@ impl<'de> Visitor<'de> for AbiObjectVisitor {
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
Ok(DeserializeBytes(ethers_core::types::deserialize_bytes(deserializer)?.into())) Ok(DeserializeBytes(crate::types::deserialize_bytes(deserializer)?.into()))
} }
} }
@ -204,7 +204,7 @@ impl<'de> Deserialize<'de> for AbiObject {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use ethers_core::abi::Abi; use crate::abi::Abi;
fn assert_has_bytecode(s: &str) { fn assert_has_bytecode(s: &str) {
match serde_json::from_str::<JsonAbi>(s).unwrap() { match serde_json::from_str::<JsonAbi>(s).unwrap() {
@ -219,14 +219,16 @@ mod tests {
#[test] #[test]
fn can_parse_raw_abi() { fn can_parse_raw_abi() {
const VERIFIER_ABI: &str = include_str!("../../tests/solidity-contracts/verifier_abi.json"); const VERIFIER_ABI: &str =
include_str!("../../../ethers-contract/tests/solidity-contracts/verifier_abi.json");
let _ = serde_json::from_str::<RawAbi>(VERIFIER_ABI).unwrap(); let _ = serde_json::from_str::<RawAbi>(VERIFIER_ABI).unwrap();
} }
#[test] #[test]
fn can_parse_hardhat_raw_abi() { fn can_parse_hardhat_raw_abi() {
const VERIFIER_ABI: &str = const VERIFIER_ABI: &str = include_str!(
include_str!("../../tests/solidity-contracts/verifier_abi_hardhat.json"); "../../../ethers-contract/tests/solidity-contracts/verifier_abi_hardhat.json"
);
let _ = serde_json::from_str::<RawAbi>(VERIFIER_ABI).unwrap(); let _ = serde_json::from_str::<RawAbi>(VERIFIER_ABI).unwrap();
} }
@ -261,7 +263,9 @@ mod tests {
let s = format!(r#"{{"abi": {}, "bytecode" : {{ "object": "{}" }} }}"#, abi_str, code); let s = format!(r#"{{"abi": {}, "bytecode" : {{ "object": "{}" }} }}"#, abi_str, code);
assert_has_bytecode(&s); assert_has_bytecode(&s);
let hh_artifact = include_str!("../../tests/solidity-contracts/verifier_abi_hardhat.json"); let hh_artifact = include_str!(
"../../../ethers-contract/tests/solidity-contracts/verifier_abi_hardhat.json"
);
match serde_json::from_str::<JsonAbi>(hh_artifact).unwrap() { match serde_json::from_str::<JsonAbi>(hh_artifact).unwrap() {
JsonAbi::Object(abi) => { JsonAbi::Object(abi) => {
assert!(abi.bytecode.is_none()); assert!(abi.bytecode.is_none());
@ -274,7 +278,8 @@ mod tests {
#[test] #[test]
fn can_parse_greeter_bytecode() { fn can_parse_greeter_bytecode() {
let artifact = include_str!("../../tests/solidity-contracts/greeter.json"); let artifact =
include_str!("../../../ethers-contract/tests/solidity-contracts/greeter.json");
assert_has_bytecode(artifact); assert_has_bytecode(artifact);
} }

View File

@ -1,12 +1,10 @@
use crate::{ use crate::{
source_tree::{SourceTree, SourceTreeEntry}, source_tree::{SourceTree, SourceTreeEntry},
utils::{ utils::{deserialize_address_opt, deserialize_stringified_source_code},
deserialize_address_opt, deserialize_stringified_abi, deserialize_stringified_source_code,
},
Client, EtherscanError, Response, Result, Client, EtherscanError, Response, Result,
}; };
use ethers_core::{ use ethers_core::{
abi::{Abi, Address}, abi::{Abi, Address, RawAbi},
types::{serde_helpers::deserialize_stringified_u64, Bytes}, types::{serde_helpers::deserialize_stringified_u64, Bytes},
}; };
use semver::Version; use semver::Version;
@ -113,8 +111,8 @@ pub struct Metadata {
pub source_code: SourceCodeMetadata, pub source_code: SourceCodeMetadata,
/// The ABI of the contract. /// The ABI of the contract.
#[serde(rename = "ABI", deserialize_with = "deserialize_stringified_abi")] #[serde(rename = "ABI")]
pub abi: Abi, pub abi: String,
/// The name of the contract. /// The name of the contract.
pub contract_name: String, pub contract_name: String,
@ -179,6 +177,16 @@ impl Metadata {
self.source_code.sources() self.source_code.sources()
} }
/// Parses the Abi String as an [RawAbi] struct.
pub fn raw_abi(&self) -> Result<RawAbi> {
Ok(serde_json::from_str(&self.abi)?)
}
/// Parses the Abi String as an [Abi] struct.
pub fn abi(&self) -> Result<Abi> {
Ok(serde_json::from_str(&self.abi)?)
}
/// Parses the compiler version. /// Parses the compiler version.
pub fn compiler_version(&self) -> Result<Version> { pub fn compiler_version(&self) -> Result<Version> {
let v = &self.compiler_version; let v = &self.compiler_version;
@ -274,8 +282,13 @@ impl IntoIterator for ContractMetadata {
impl ContractMetadata { impl ContractMetadata {
/// Returns the ABI of all contracts. /// Returns the ABI of all contracts.
pub fn abis(&self) -> Vec<&Abi> { pub fn abis(&self) -> Result<Vec<Abi>> {
self.items.iter().map(|c| &c.abi).collect() self.items.iter().map(|c| c.abi()).collect()
}
/// Returns the raw ABI of all contracts.
pub fn raw_abis(&self) -> Result<Vec<RawAbi>> {
self.items.iter().map(|c| c.raw_abi()).collect()
} }
/// Returns the combined source code of all contracts. /// Returns the combined source code of all contracts.
@ -460,7 +473,7 @@ mod tests {
let item = &meta.items[0]; let item = &meta.items[0];
assert!(matches!(item.source_code, SourceCodeMetadata::SourceCode(_))); assert!(matches!(item.source_code, SourceCodeMetadata::SourceCode(_)));
assert_eq!(item.source_code.sources().len(), 1); assert_eq!(item.source_code.sources().len(), 1);
assert_eq!(item.abi, serde_json::from_str(DAO_ABI).unwrap()); assert_eq!(item.abi().unwrap(), serde_json::from_str(DAO_ABI).unwrap());
}) })
.await .await
} }
@ -497,7 +510,7 @@ mod tests {
let item = &meta.items[0]; let item = &meta.items[0];
assert!(matches!(item.source_code, SourceCodeMetadata::SourceCode(_))); assert!(matches!(item.source_code, SourceCodeMetadata::SourceCode(_)));
assert_eq!(item.source_code.sources().len(), 1); assert_eq!(item.source_code.sources().len(), 1);
assert_eq!(item.abi, serde_json::from_str(DAO_ABI).unwrap()); assert_eq!(item.abi().unwrap(), serde_json::from_str(DAO_ABI).unwrap());
}) })
.await .await
} }

View File

@ -1,5 +1,5 @@
use crate::{contract::SourceCodeMetadata, EtherscanError, Result}; use crate::{contract::SourceCodeMetadata, EtherscanError, Result};
use ethers_core::{abi::Abi, types::Address}; use ethers_core::types::Address;
use semver::Version; use semver::Version;
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
@ -53,14 +53,6 @@ pub fn deserialize_stringified_source_code<'de, D: Deserializer<'de>>(
} }
} }
/// Deserializes as JSON: "\[...\]"
pub fn deserialize_stringified_abi<'de, D: Deserializer<'de>>(
deserializer: D,
) -> std::result::Result<Abi, D::Error> {
let s = String::deserialize(deserializer)?;
serde_json::from_str(&s).map_err(serde::de::Error::custom)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -115,19 +107,6 @@ mod tests {
assert_eq!(de.address, Some(expected)); assert_eq!(de.address, Some(expected));
} }
#[test]
fn can_deserialize_stringified_abi() {
#[derive(Deserialize)]
struct Test {
#[serde(deserialize_with = "deserialize_stringified_abi")]
abi: Abi,
}
let json = r#"{"abi": "[]"}"#;
let de: Test = serde_json::from_str(json).unwrap();
assert_eq!(de.abi, Abi::default());
}
#[test] #[test]
fn can_deserialize_stringified_source_code() { fn can_deserialize_stringified_source_code() {
#[derive(Deserialize)] #[derive(Deserialize)]