From 38e18463dcc13e89b224f073574ff6009dd7b935 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Fri, 10 Dec 2021 20:38:44 +0100 Subject: [PATCH] feat(solc): extend Artifact trait (#673) * feat(solc): extend Artifact trait * chore: update changelog * chore: rustfmt --- CHANGELOG.md | 1 + ethers-solc/src/artifacts.rs | 18 ++++++++++++++++-- ethers-solc/src/config.rs | 27 ++++++++++++++++++++------- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01497967..1c5cfa39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ ### Unreleased +- Add more utility functions to the `Artifact` trait [#673](https://github.com/gakonst/ethers-rs/pull/673) - Return cached artifacts from project `compile` when the cache only contains some files - Add support for library linking and make `Bytecode`'s `object` filed an `enum BytecodeObject` diff --git a/ethers-solc/src/artifacts.rs b/ethers-solc/src/artifacts.rs index fce6eb78..b55be734 100644 --- a/ethers-solc/src/artifacts.rs +++ b/ethers-solc/src/artifacts.rs @@ -565,7 +565,7 @@ pub struct Contract { } /// Minimal representation of a contract's abi with bytecode -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Default)] pub struct CompactContract { /// The Ethereum Contract ABI. If empty, it is represented as an empty /// array. See https://docs.soliditylang.org/en/develop/abi-spec.html @@ -577,7 +577,7 @@ pub struct CompactContract { } impl CompactContract { - /// Returns the contents of this type as a single + /// Returns the contents of this type as a single tuple of abi, bytecode and deployed bytecode pub fn into_parts(self) -> (Option, Option, Option) { ( self.abi, @@ -598,6 +598,20 @@ impl CompactContract { } } +impl From for CompactContract { + fn from(mut val: serde_json::Value) -> Self { + if let Some(map) = val.as_object_mut() { + let abi = map.remove("abi").and_then(|val| serde_json::from_value(val).ok()); + let bin = map.remove("bin").and_then(|val| serde_json::from_value(val).ok()); + let bin_runtime = + map.remove("bin-runtime").and_then(|val| serde_json::from_value(val).ok()); + Self { abi, bin, bin_runtime } + } else { + CompactContract::default() + } + } +} + impl From for CompactContract { fn from(c: Contract) -> Self { let (bin, bin_runtime) = if let Some(evm) = c.evm { diff --git a/ethers-solc/src/config.rs b/ethers-solc/src/config.rs index c88f4395..69feb75c 100644 --- a/ethers-solc/src/config.rs +++ b/ethers-solc/src/config.rs @@ -218,25 +218,38 @@ impl SolcConfigBuilder { pub type Artifacts = BTreeMap>; pub trait Artifact { + /// Returns the artifact's `Abi` and bytecode fn into_inner(self) -> (Option, Option); + + /// Turns the artifact into a container type for abi, bytecode and deployed bytecode + fn into_compact_contract(self) -> CompactContract; + + /// Returns the contents of this type as a single tuple of abi, bytecode and deployed bytecode + fn into_parts(self) -> (Option, Option, Option) + where + Self: Sized, + { + self.into_compact_contract().into_parts() + } } impl Artifact for CompactContract { fn into_inner(self) -> (Option, Option) { (self.abi, self.bin.and_then(|bin| bin.into_bytes())) } + + fn into_compact_contract(self) -> CompactContract { + self + } } impl Artifact for serde_json::Value { fn into_inner(self) -> (Option, Option) { - let abi = self.get("abi").map(|abi| { - serde_json::from_value::(abi.clone()).expect("could not get artifact abi") - }); - let bytecode = self.get("bin").map(|bin| { - serde_json::from_value::(bin.clone()).expect("could not get artifact bytecode") - }); + self.into_compact_contract().into_inner() + } - (abi, bytecode) + fn into_compact_contract(self) -> CompactContract { + self.into() } }