fix(core, etherscan): RawAbi and Abi (#1757)
This commit is contained in:
parent
62beb6cf53
commit
d2c9db5ae9
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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"))]
|
||||||
|
|
|
@ -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};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
Loading…
Reference in New Issue