2021-12-11 17:39:39 +00:00
|
|
|
//! Hardhat support
|
|
|
|
|
|
|
|
use crate::{
|
2022-01-28 07:23:28 +00:00
|
|
|
artifacts::{
|
2022-03-17 14:51:43 +00:00
|
|
|
bytecode::{Bytecode, BytecodeObject, DeployedBytecode},
|
|
|
|
contract::{CompactContract, CompactContractBytecode, Contract, ContractBytecode},
|
2022-03-17 19:48:55 +00:00
|
|
|
CompactContractBytecodeCow, LosslessAbi, Offsets,
|
2022-01-28 07:23:28 +00:00
|
|
|
},
|
2022-05-22 22:19:59 +00:00
|
|
|
ArtifactOutput, SourceFile, VersionedSourceFile,
|
2021-12-11 17:39:39 +00:00
|
|
|
};
|
|
|
|
use serde::{Deserialize, Serialize};
|
2022-03-17 19:48:55 +00:00
|
|
|
use std::{borrow::Cow, collections::btree_map::BTreeMap};
|
2021-12-11 17:39:39 +00:00
|
|
|
|
|
|
|
const HH_ARTIFACT_VERSION: &str = "hh-sol-artifact-1";
|
|
|
|
|
|
|
|
/// A hardhat artifact
|
|
|
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
pub struct HardhatArtifact {
|
|
|
|
#[serde(rename = "_format")]
|
|
|
|
pub format: String,
|
|
|
|
/// A string with the contract's name.
|
|
|
|
pub contract_name: String,
|
|
|
|
/// The source name of this contract in the workspace like `contracts/Greeter.sol`
|
|
|
|
pub source_name: String,
|
|
|
|
/// The contract's ABI
|
2022-02-23 10:46:52 +00:00
|
|
|
pub abi: LosslessAbi,
|
2021-12-11 17:39:39 +00:00
|
|
|
/// A "0x"-prefixed hex string of the unlinked deployment bytecode. If the contract is not
|
|
|
|
/// deployable, this has the string "0x"
|
2021-12-25 04:45:53 +00:00
|
|
|
pub bytecode: Option<BytecodeObject>,
|
2021-12-11 17:39:39 +00:00
|
|
|
/// A "0x"-prefixed hex string of the unlinked runtime/deployed bytecode. If the contract is
|
|
|
|
/// not deployable, this has the string "0x"
|
|
|
|
pub deployed_bytecode: Option<BytecodeObject>,
|
|
|
|
/// The bytecode's link references object as returned by solc. If the contract doesn't need to
|
|
|
|
/// be linked, this value contains an empty object.
|
|
|
|
#[serde(default)]
|
|
|
|
pub link_references: BTreeMap<String, BTreeMap<String, Vec<Offsets>>>,
|
|
|
|
/// The deployed bytecode's link references object as returned by solc. If the contract doesn't
|
|
|
|
/// need to be linked, this value contains an empty object.
|
|
|
|
#[serde(default)]
|
|
|
|
pub deployed_link_references: BTreeMap<String, BTreeMap<String, Vec<Offsets>>>,
|
|
|
|
}
|
|
|
|
|
2022-03-17 19:48:55 +00:00
|
|
|
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())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-11 17:39:39 +00:00
|
|
|
impl From<HardhatArtifact> for CompactContract {
|
|
|
|
fn from(artifact: HardhatArtifact) -> Self {
|
|
|
|
CompactContract {
|
2022-02-23 10:46:52 +00:00
|
|
|
abi: Some(artifact.abi.abi),
|
2021-12-25 04:45:53 +00:00
|
|
|
bin: artifact.bytecode,
|
2021-12-11 17:39:39 +00:00
|
|
|
bin_runtime: artifact.deployed_bytecode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-28 07:23:28 +00:00
|
|
|
impl From<HardhatArtifact> for ContractBytecode {
|
|
|
|
fn from(artifact: HardhatArtifact) -> Self {
|
|
|
|
let bytecode: Option<Bytecode> = artifact.bytecode.as_ref().map(|t| {
|
|
|
|
let mut bcode: Bytecode = t.clone().into();
|
|
|
|
bcode.link_references = artifact.link_references.clone();
|
|
|
|
bcode
|
|
|
|
});
|
|
|
|
|
|
|
|
let deployed_bytecode: Option<DeployedBytecode> = artifact.bytecode.as_ref().map(|t| {
|
|
|
|
let mut bcode: Bytecode = t.clone().into();
|
|
|
|
bcode.link_references = artifact.deployed_link_references.clone();
|
|
|
|
bcode.into()
|
|
|
|
});
|
|
|
|
|
2022-02-23 10:46:52 +00:00
|
|
|
ContractBytecode { abi: Some(artifact.abi.abi), bytecode, deployed_bytecode }
|
2022-01-28 07:23:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<HardhatArtifact> for CompactContractBytecode {
|
|
|
|
fn from(artifact: HardhatArtifact) -> Self {
|
|
|
|
let c: ContractBytecode = artifact.into();
|
|
|
|
|
|
|
|
c.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-11 17:39:39 +00:00
|
|
|
/// Hardhat style artifacts handler
|
2022-02-17 15:31:35 +00:00
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
|
|
|
|
pub struct HardhatArtifacts {
|
|
|
|
_priv: (),
|
|
|
|
}
|
2021-12-11 17:39:39 +00:00
|
|
|
|
|
|
|
impl ArtifactOutput for HardhatArtifacts {
|
|
|
|
type Artifact = HardhatArtifact;
|
|
|
|
|
2022-03-27 16:56:33 +00:00
|
|
|
fn contract_to_artifact(
|
|
|
|
&self,
|
|
|
|
file: &str,
|
|
|
|
name: &str,
|
|
|
|
contract: Contract,
|
|
|
|
_source_file: Option<&SourceFile>,
|
|
|
|
) -> Self::Artifact {
|
2021-12-11 17:39:39 +00:00
|
|
|
let (bytecode, link_references, deployed_bytecode, deployed_link_references) =
|
|
|
|
if let Some(evm) = contract.evm {
|
|
|
|
let (deployed_bytecode, deployed_link_references) =
|
|
|
|
if let Some(code) = evm.deployed_bytecode.and_then(|code| code.bytecode) {
|
|
|
|
(Some(code.object), code.link_references)
|
|
|
|
} else {
|
|
|
|
(None, Default::default())
|
|
|
|
};
|
|
|
|
|
2021-12-25 04:45:53 +00:00
|
|
|
let (bytecode, link_ref) = if let Some(bc) = evm.bytecode {
|
|
|
|
(Some(bc.object), bc.link_references)
|
|
|
|
} else {
|
|
|
|
(None, Default::default())
|
|
|
|
};
|
|
|
|
|
|
|
|
(bytecode, link_ref, deployed_bytecode, deployed_link_references)
|
2021-12-11 17:39:39 +00:00
|
|
|
} else {
|
|
|
|
(Default::default(), Default::default(), None, Default::default())
|
|
|
|
};
|
|
|
|
|
|
|
|
HardhatArtifact {
|
|
|
|
format: HH_ARTIFACT_VERSION.to_string(),
|
|
|
|
contract_name: name.to_string(),
|
|
|
|
source_name: file.to_string(),
|
|
|
|
abi: contract.abi.unwrap_or_default(),
|
|
|
|
bytecode,
|
|
|
|
deployed_bytecode,
|
|
|
|
link_references,
|
|
|
|
deployed_link_references,
|
|
|
|
}
|
|
|
|
}
|
2022-05-22 22:19:59 +00:00
|
|
|
|
|
|
|
fn standalone_source_file_to_artifact(
|
|
|
|
&self,
|
|
|
|
_path: &str,
|
|
|
|
_file: &VersionedSourceFile,
|
|
|
|
) -> Option<Self::Artifact> {
|
|
|
|
None
|
|
|
|
}
|
2021-12-11 17:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use crate::Artifact;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn can_parse_hh_artifact() {
|
|
|
|
let s = include_str!("../test-data/hh-greeter-artifact.json");
|
|
|
|
let artifact = serde_json::from_str::<HardhatArtifact>(s).unwrap();
|
|
|
|
let compact = artifact.into_compact_contract();
|
|
|
|
assert!(compact.abi.is_some());
|
|
|
|
assert!(compact.bin.is_some());
|
|
|
|
assert!(compact.bin_runtime.is_some());
|
|
|
|
}
|
|
|
|
}
|