feat(solc): more artifact trait functions (#1057)
* style: split artifacts mod and create contract and bytecode mods * chore: rustfmt * feat(solc): more artifact trait functions * feat: add missing impl
This commit is contained in:
parent
65b1751cf8
commit
d1f46f4c2c
|
@ -5,13 +5,13 @@ use crate::{
|
||||||
bytecode::{CompactBytecode, CompactDeployedBytecode},
|
bytecode::{CompactBytecode, CompactDeployedBytecode},
|
||||||
contract::{CompactContract, CompactContractBytecode, Contract},
|
contract::{CompactContract, CompactContractBytecode, Contract},
|
||||||
output_selection::{ContractOutputSelection, EvmOutputSelection, EwasmOutputSelection},
|
output_selection::{ContractOutputSelection, EvmOutputSelection, EwasmOutputSelection},
|
||||||
CompactEvm, DevDoc, Ewasm, GasEstimates, LosslessAbi, Metadata, Offsets, Settings,
|
CompactContractBytecodeCow, CompactEvm, DevDoc, Ewasm, GasEstimates, LosslessAbi, Metadata,
|
||||||
StorageLayout, UserDoc,
|
Offsets, Settings, StorageLayout, UserDoc,
|
||||||
},
|
},
|
||||||
ArtifactOutput, SolcConfig, SolcError,
|
ArtifactOutput, SolcConfig, SolcError,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{collections::BTreeMap, fs, path::Path};
|
use std::{borrow::Cow, collections::BTreeMap, fs, path::Path};
|
||||||
|
|
||||||
/// Represents the `Artifact` that `ConfigurableArtifacts` emits.
|
/// Represents the `Artifact` that `ConfigurableArtifacts` emits.
|
||||||
///
|
///
|
||||||
|
@ -87,6 +87,16 @@ impl From<ConfigurableContractArtifact> for CompactContract {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a ConfigurableContractArtifact> for CompactContractBytecodeCow<'a> {
|
||||||
|
fn from(artifact: &'a ConfigurableContractArtifact) -> Self {
|
||||||
|
CompactContractBytecodeCow {
|
||||||
|
abi: artifact.abi.as_ref().map(|abi| Cow::Borrowed(&abi.abi)),
|
||||||
|
bytecode: artifact.bytecode.as_ref().map(Cow::Borrowed),
|
||||||
|
deployed_bytecode: artifact.deployed_bytecode.as_ref().map(Cow::Borrowed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An `Artifact` implementation that can be configured to include additional content and emit
|
/// An `Artifact` implementation that can be configured to include additional content and emit
|
||||||
/// additional files
|
/// additional files
|
||||||
///
|
///
|
||||||
|
|
|
@ -8,13 +8,17 @@ use ethers_core::{abi::Abi, types::Bytes};
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
collections::btree_map::BTreeMap,
|
collections::btree_map::BTreeMap,
|
||||||
fmt, fs, io,
|
fmt, fs, io,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod configurable;
|
mod configurable;
|
||||||
use crate::artifacts::contract::{CompactContract, CompactContractBytecode, Contract};
|
use crate::artifacts::{
|
||||||
|
contract::{CompactContract, CompactContractBytecode, Contract},
|
||||||
|
BytecodeObject, CompactBytecode, CompactContractBytecodeCow, CompactDeployedBytecode,
|
||||||
|
};
|
||||||
pub use configurable::*;
|
pub use configurable::*;
|
||||||
|
|
||||||
/// Represents unique artifact metadata for identifying artifacts on output
|
/// Represents unique artifact metadata for identifying artifacts on output
|
||||||
|
@ -290,6 +294,29 @@ pub trait Artifact {
|
||||||
/// Returns the contents of this type as a single tuple of abi, bytecode and deployed bytecode
|
/// Returns the contents of this type as a single tuple of abi, bytecode and deployed bytecode
|
||||||
fn into_parts(self) -> (Option<Abi>, Option<Bytes>, Option<Bytes>);
|
fn into_parts(self) -> (Option<Abi>, Option<Bytes>, Option<Bytes>);
|
||||||
|
|
||||||
|
/// Consumes the type and returns the [Abi]
|
||||||
|
fn into_abi(self) -> Option<Abi>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.into_parts().0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes the type and returns the `bytecode`
|
||||||
|
fn into_bytecode_bytes(self) -> Option<Bytes>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.into_parts().1
|
||||||
|
}
|
||||||
|
/// Consumes the type and returns the `deployed bytecode`
|
||||||
|
fn into_deployed_bytecode_bytes(self) -> Option<Bytes>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.into_parts().2
|
||||||
|
}
|
||||||
|
|
||||||
/// Same as [`Self::into_parts()`] but returns `Err` if an element is `None`
|
/// Same as [`Self::into_parts()`] but returns `Err` if an element is `None`
|
||||||
fn try_into_parts(self) -> Result<(Abi, Bytes, Bytes)>
|
fn try_into_parts(self) -> Result<(Abi, Bytes, Bytes)>
|
||||||
where
|
where
|
||||||
|
@ -303,11 +330,67 @@ pub trait Artifact {
|
||||||
deployed_bytecode.ok_or_else(|| SolcError::msg("deployed bytecode missing"))?,
|
deployed_bytecode.ok_or_else(|| SolcError::msg("deployed bytecode missing"))?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the reference of container type for abi, compact bytecode and deployed bytecode if
|
||||||
|
/// available
|
||||||
|
fn get_contract_bytecode(&self) -> CompactContractBytecodeCow;
|
||||||
|
|
||||||
|
/// Returns the reference to the `bytecode`
|
||||||
|
fn get_bytecode(&self) -> Option<Cow<CompactBytecode>> {
|
||||||
|
self.get_contract_bytecode().bytecode
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the reference to the `bytecode` object
|
||||||
|
fn get_bytecode_object(&self) -> Option<Cow<BytecodeObject>> {
|
||||||
|
let val = match self.get_bytecode()? {
|
||||||
|
Cow::Borrowed(b) => Cow::Borrowed(&b.object),
|
||||||
|
Cow::Owned(b) => Cow::Owned(b.object),
|
||||||
|
};
|
||||||
|
Some(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the bytes of the `bytecode` object
|
||||||
|
fn get_bytecode_bytes(&self) -> Option<Cow<Bytes>> {
|
||||||
|
let val = match self.get_bytecode_object()? {
|
||||||
|
Cow::Borrowed(b) => Cow::Borrowed(b.as_bytes()?),
|
||||||
|
Cow::Owned(b) => Cow::Owned(b.into_bytes()?),
|
||||||
|
};
|
||||||
|
Some(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the reference to the `deployedBytecode`
|
||||||
|
fn get_deployed_bytecode(&self) -> Option<Cow<CompactDeployedBytecode>> {
|
||||||
|
self.get_contract_bytecode().deployed_bytecode
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the reference to the `bytecode` object
|
||||||
|
fn get_deployed_bytecode_object(&self) -> Option<Cow<BytecodeObject>> {
|
||||||
|
let val = match self.get_deployed_bytecode()? {
|
||||||
|
Cow::Borrowed(b) => Cow::Borrowed(&b.bytecode.as_ref()?.object),
|
||||||
|
Cow::Owned(b) => Cow::Owned(b.bytecode?.object),
|
||||||
|
};
|
||||||
|
Some(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the bytes of the `deployed bytecode` object
|
||||||
|
fn get_deployed_bytecode_bytes(&self) -> Option<Cow<Bytes>> {
|
||||||
|
let val = match self.get_deployed_bytecode_object()? {
|
||||||
|
Cow::Borrowed(b) => Cow::Borrowed(b.as_bytes()?),
|
||||||
|
Cow::Owned(b) => Cow::Owned(b.into_bytes()?),
|
||||||
|
};
|
||||||
|
Some(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the reference to the [Abi] if available
|
||||||
|
fn get_abi(&self) -> Option<Cow<Abi>> {
|
||||||
|
self.get_contract_bytecode().abi
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Artifact for T
|
impl<T> Artifact for T
|
||||||
where
|
where
|
||||||
T: Into<CompactContractBytecode> + Into<CompactContract>,
|
T: Into<CompactContractBytecode> + Into<CompactContract>,
|
||||||
|
for<'a> &'a T: Into<CompactContractBytecodeCow<'a>>,
|
||||||
{
|
{
|
||||||
fn into_inner(self) -> (Option<Abi>, Option<Bytes>) {
|
fn into_inner(self) -> (Option<Abi>, Option<Bytes>) {
|
||||||
let artifact = self.into_compact_contract();
|
let artifact = self.into_compact_contract();
|
||||||
|
@ -325,6 +408,10 @@ where
|
||||||
fn into_parts(self) -> (Option<Abi>, Option<Bytes>, Option<Bytes>) {
|
fn into_parts(self) -> (Option<Abi>, Option<Bytes>, Option<Bytes>) {
|
||||||
self.into_compact_contract().into_parts()
|
self.into_compact_contract().into_parts()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_contract_bytecode(&self) -> CompactContractBytecodeCow {
|
||||||
|
self.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handler invoked with the output of `solc`
|
/// Handler invoked with the output of `solc`
|
||||||
|
|
|
@ -221,6 +221,14 @@ impl BytecodeObject {
|
||||||
BytecodeObject::Unlinked(_) => None,
|
BytecodeObject::Unlinked(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the number of bytes of the fully linked bytecode
|
||||||
|
///
|
||||||
|
/// Returns `0` if this object is unlinked.
|
||||||
|
pub fn bytes_len(&self) -> usize {
|
||||||
|
self.as_bytes().map(|b| b.as_ref().len()).unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a reference to the underlying `String` if the object is unlinked
|
/// Returns a reference to the underlying `String` if the object is unlinked
|
||||||
pub fn as_str(&self) -> Option<&str> {
|
pub fn as_str(&self) -> Option<&str> {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::artifacts::{
|
||||||
};
|
};
|
||||||
use ethers_core::{abi::Contract as Abi, types::Bytes};
|
use ethers_core::{abi::Contract as Abi, types::Bytes};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{collections::BTreeMap, convert::TryFrom};
|
use std::{borrow::Cow, collections::BTreeMap, convert::TryFrom};
|
||||||
|
|
||||||
/// Represents a compiled solidity contract
|
/// Represents a compiled solidity contract
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
|
@ -41,6 +41,24 @@ pub struct Contract {
|
||||||
pub ir_optimized: Option<String>,
|
pub ir_optimized: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a Contract> for CompactContractBytecodeCow<'a> {
|
||||||
|
fn from(artifact: &'a Contract) -> Self {
|
||||||
|
let (bytecode, deployed_bytecode) = if let Some(ref evm) = artifact.evm {
|
||||||
|
(
|
||||||
|
evm.bytecode.clone().map(Into::into).map(Cow::Owned),
|
||||||
|
evm.deployed_bytecode.clone().map(Into::into).map(Cow::Owned),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
};
|
||||||
|
CompactContractBytecodeCow {
|
||||||
|
abi: artifact.abi.as_ref().map(|abi| Cow::Borrowed(&abi.abi)),
|
||||||
|
bytecode,
|
||||||
|
deployed_bytecode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Minimal representation of a contract with a present abi and bytecode.
|
/// Minimal representation of a contract with a present abi and bytecode.
|
||||||
///
|
///
|
||||||
/// Unlike `CompactContractSome` which contains the `BytecodeObject`, this holds the whole
|
/// Unlike `CompactContractSome` which contains the `BytecodeObject`, this holds the whole
|
||||||
|
@ -143,6 +161,16 @@ impl CompactContractBytecode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a CompactContractBytecode> for CompactContractBytecodeCow<'a> {
|
||||||
|
fn from(artifact: &'a CompactContractBytecode) -> Self {
|
||||||
|
CompactContractBytecodeCow {
|
||||||
|
abi: artifact.abi.as_ref().map(Cow::Borrowed),
|
||||||
|
bytecode: artifact.bytecode.as_ref().map(Cow::Borrowed),
|
||||||
|
deployed_bytecode: artifact.deployed_bytecode.as_ref().map(Cow::Borrowed),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Contract> for CompactContractBytecode {
|
impl From<Contract> for CompactContractBytecode {
|
||||||
fn from(c: Contract) -> Self {
|
fn from(c: Contract) -> Self {
|
||||||
let (bytecode, deployed_bytecode) = if let Some(evm) = c.evm {
|
let (bytecode, deployed_bytecode) = if let Some(evm) = c.evm {
|
||||||
|
@ -180,6 +208,17 @@ impl From<CompactContractBytecode> for ContractBytecode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A [CompactContractBytecode] that is either owns or borrows its content
|
||||||
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct CompactContractBytecodeCow<'a> {
|
||||||
|
pub abi: Option<Cow<'a, Abi>>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub bytecode: Option<Cow<'a, CompactBytecode>>,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deployed_bytecode: Option<Cow<'a, CompactDeployedBytecode>>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Minimal representation of a contract with a present abi and bytecode.
|
/// Minimal representation of a contract with a present abi and bytecode.
|
||||||
///
|
///
|
||||||
/// Unlike `CompactContractSome` which contains the `BytecodeObject`, this holds the whole
|
/// Unlike `CompactContractSome` which contains the `BytecodeObject`, this holds the whole
|
||||||
|
@ -311,6 +350,17 @@ impl From<serde_json::Value> for CompactContract {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a serde_json::Value> for CompactContractBytecodeCow<'a> {
|
||||||
|
fn from(artifact: &'a serde_json::Value) -> Self {
|
||||||
|
let c = CompactContractBytecode::from(artifact.clone());
|
||||||
|
CompactContractBytecodeCow {
|
||||||
|
abi: c.abi.map(Cow::Owned),
|
||||||
|
bytecode: c.bytecode.map(Cow::Owned),
|
||||||
|
deployed_bytecode: c.deployed_bytecode.map(Cow::Owned),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<serde_json::Value> for CompactContractBytecode {
|
impl From<serde_json::Value> for CompactContractBytecode {
|
||||||
fn from(val: serde_json::Value) -> Self {
|
fn from(val: serde_json::Value) -> Self {
|
||||||
serde_json::from_value(val).unwrap_or_default()
|
serde_json::from_value(val).unwrap_or_default()
|
||||||
|
|
|
@ -4,12 +4,12 @@ use crate::{
|
||||||
artifacts::{
|
artifacts::{
|
||||||
bytecode::{Bytecode, BytecodeObject, DeployedBytecode},
|
bytecode::{Bytecode, BytecodeObject, DeployedBytecode},
|
||||||
contract::{CompactContract, CompactContractBytecode, Contract, ContractBytecode},
|
contract::{CompactContract, CompactContractBytecode, Contract, ContractBytecode},
|
||||||
LosslessAbi, Offsets,
|
CompactContractBytecodeCow, LosslessAbi, Offsets,
|
||||||
},
|
},
|
||||||
ArtifactOutput,
|
ArtifactOutput,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::btree_map::BTreeMap;
|
use std::{borrow::Cow, collections::btree_map::BTreeMap};
|
||||||
|
|
||||||
const HH_ARTIFACT_VERSION: &str = "hh-sol-artifact-1";
|
const HH_ARTIFACT_VERSION: &str = "hh-sol-artifact-1";
|
||||||
|
|
||||||
|
@ -41,6 +41,17 @@ pub struct HardhatArtifact {
|
||||||
pub deployed_link_references: BTreeMap<String, BTreeMap<String, Vec<Offsets>>>,
|
pub deployed_link_references: BTreeMap<String, BTreeMap<String, Vec<Offsets>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a HardhatArtifact> for CompactContractBytecodeCow<'a> {
|
||||||
|
fn from(artifact: &'a HardhatArtifact) -> Self {
|
||||||
|
let c: ContractBytecode = artifact.clone().into();
|
||||||
|
CompactContractBytecodeCow {
|
||||||
|
abi: Some(Cow::Borrowed(&artifact.abi.abi)),
|
||||||
|
bytecode: c.bytecode.map(|b| Cow::Owned(b.into())),
|
||||||
|
deployed_bytecode: c.deployed_bytecode.map(|b| Cow::Owned(b.into())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<HardhatArtifact> for CompactContract {
|
impl From<HardhatArtifact> for CompactContract {
|
||||||
fn from(artifact: HardhatArtifact) -> Self {
|
fn from(artifact: HardhatArtifact) -> Self {
|
||||||
CompactContract {
|
CompactContract {
|
||||||
|
|
Loading…
Reference in New Issue