2022-02-17 15:31:35 +00:00
|
|
|
//! A configurable artifacts handler implementation
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
artifacts::{
|
2022-03-17 14:51:43 +00:00
|
|
|
bytecode::{CompactBytecode, CompactDeployedBytecode},
|
|
|
|
contract::{CompactContract, CompactContractBytecode, Contract},
|
2022-04-23 08:48:39 +00:00
|
|
|
output_selection::{
|
|
|
|
BytecodeOutputSelection, ContractOutputSelection, EvmOutputSelection,
|
|
|
|
EwasmOutputSelection,
|
|
|
|
},
|
2022-04-23 09:20:46 +00:00
|
|
|
Ast, CompactContractBytecodeCow, DevDoc, Evm, Ewasm, FunctionDebugData, GasEstimates,
|
2022-05-05 14:47:52 +00:00
|
|
|
GeneratedSource, LosslessAbi, Metadata, Offsets, Settings, StorageLayout, UserDoc,
|
2022-02-17 15:31:35 +00:00
|
|
|
},
|
2022-03-27 16:56:33 +00:00
|
|
|
ArtifactOutput, SolcConfig, SolcError, SourceFile,
|
2022-02-17 15:31:35 +00:00
|
|
|
};
|
|
|
|
use serde::{Deserialize, Serialize};
|
2022-03-17 19:48:55 +00:00
|
|
|
use std::{borrow::Cow, collections::BTreeMap, fs, path::Path};
|
2022-02-17 15:31:35 +00:00
|
|
|
|
|
|
|
/// Represents the `Artifact` that `ConfigurableArtifacts` emits.
|
|
|
|
///
|
|
|
|
/// This is essentially a superset of [`CompactContractBytecode`].
|
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
pub struct ConfigurableContractArtifact {
|
|
|
|
/// The Ethereum Contract ABI. If empty, it is represented as an empty
|
2022-03-19 17:05:39 +00:00
|
|
|
/// array. See <https://docs.soliditylang.org/en/develop/abi-spec.html>
|
2022-02-23 10:46:52 +00:00
|
|
|
pub abi: Option<LosslessAbi>,
|
2022-02-17 15:31:35 +00:00
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub bytecode: Option<CompactBytecode>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub deployed_bytecode: Option<CompactDeployedBytecode>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub assembly: Option<String>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub method_identifiers: Option<BTreeMap<String, String>>,
|
2022-05-05 14:47:52 +00:00
|
|
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
|
|
pub generated_sources: Vec<GeneratedSource>,
|
2022-02-17 15:31:35 +00:00
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
2022-04-23 08:48:39 +00:00
|
|
|
pub function_debug_data: Option<BTreeMap<String, FunctionDebugData>>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
2022-02-17 15:31:35 +00:00
|
|
|
pub gas_estimates: Option<GasEstimates>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub metadata: Option<Metadata>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub storage_layout: Option<StorageLayout>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub userdoc: Option<UserDoc>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub devdoc: Option<DevDoc>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub ir: Option<String>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub ir_optimized: Option<String>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub ewasm: Option<Ewasm>,
|
2022-04-23 09:20:46 +00:00
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub ast: Option<Ast>,
|
2022-02-17 15:31:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ConfigurableContractArtifact {
|
|
|
|
/// Returns the inner element that contains the core bytecode related information
|
|
|
|
pub fn into_contract_bytecode(self) -> CompactContractBytecode {
|
|
|
|
self.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Looks for all link references in deployment and runtime bytecodes
|
|
|
|
pub fn all_link_references(&self) -> BTreeMap<String, BTreeMap<String, Vec<Offsets>>> {
|
|
|
|
let mut links = BTreeMap::new();
|
|
|
|
if let Some(bcode) = &self.bytecode {
|
|
|
|
links.extend(bcode.link_references.clone());
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(d_bcode) = &self.deployed_bytecode {
|
|
|
|
if let Some(bcode) = &d_bcode.bytecode {
|
|
|
|
links.extend(bcode.link_references.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
links
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ConfigurableContractArtifact> for CompactContractBytecode {
|
|
|
|
fn from(artifact: ConfigurableContractArtifact) -> Self {
|
|
|
|
CompactContractBytecode {
|
2022-02-23 10:46:52 +00:00
|
|
|
abi: artifact.abi.map(Into::into),
|
2022-02-17 15:31:35 +00:00
|
|
|
bytecode: artifact.bytecode,
|
|
|
|
deployed_bytecode: artifact.deployed_bytecode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ConfigurableContractArtifact> for CompactContract {
|
|
|
|
fn from(artifact: ConfigurableContractArtifact) -> Self {
|
|
|
|
CompactContractBytecode::from(artifact).into()
|
|
|
|
}
|
2022-03-17 19:48:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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),
|
|
|
|
}
|
|
|
|
}
|
2022-02-17 15:31:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// An `Artifact` implementation that can be configured to include additional content and emit
|
|
|
|
/// additional files
|
|
|
|
///
|
|
|
|
/// Creates a single json artifact with
|
|
|
|
/// ```json
|
|
|
|
/// {
|
|
|
|
/// "abi": [],
|
|
|
|
/// "bytecode": {...},
|
|
|
|
/// "deployedBytecode": {...}
|
|
|
|
/// // additional values
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
|
|
|
|
pub struct ConfigurableArtifacts {
|
|
|
|
/// A set of additional values to include in the contract's artifact file
|
|
|
|
pub additional_values: ExtraOutputValues,
|
|
|
|
|
|
|
|
/// A set of values that should be written to a separate file
|
|
|
|
pub additional_files: ExtraOutputFiles,
|
|
|
|
|
|
|
|
/// PRIVATE: This structure may grow, As such, constructing this structure should
|
|
|
|
/// _always_ be done using a public constructor or update syntax:
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
///
|
|
|
|
/// use ethers_solc::{ExtraOutputFiles, ConfigurableArtifacts};
|
|
|
|
/// let config = ConfigurableArtifacts {
|
|
|
|
/// additional_files: ExtraOutputFiles { metadata: true, ..Default::default() },
|
|
|
|
/// ..Default::default()
|
|
|
|
/// };
|
|
|
|
/// ```
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub __non_exhaustive: (),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ConfigurableArtifacts {
|
|
|
|
pub fn new(
|
|
|
|
extra_values: impl IntoIterator<Item = ContractOutputSelection>,
|
|
|
|
extra_files: impl IntoIterator<Item = ContractOutputSelection>,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
additional_values: ExtraOutputValues::from_output_selection(extra_values),
|
|
|
|
additional_files: ExtraOutputFiles::from_output_selection(extra_files),
|
|
|
|
..Default::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the `Settings` this configuration corresponds to
|
|
|
|
pub fn settings(&self) -> Settings {
|
|
|
|
SolcConfig::builder().additional_outputs(self.output_selection()).build().into()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the output selection corresponding to this configuration
|
|
|
|
pub fn output_selection(&self) -> Vec<ContractOutputSelection> {
|
|
|
|
let mut selection = ContractOutputSelection::basic();
|
2022-04-23 08:48:39 +00:00
|
|
|
|
2022-02-17 15:31:35 +00:00
|
|
|
if self.additional_values.ir {
|
|
|
|
selection.push(ContractOutputSelection::Ir);
|
|
|
|
}
|
|
|
|
if self.additional_values.ir_optimized || self.additional_files.ir_optimized {
|
|
|
|
selection.push(ContractOutputSelection::IrOptimized);
|
|
|
|
}
|
|
|
|
if self.additional_values.metadata || self.additional_files.metadata {
|
|
|
|
selection.push(ContractOutputSelection::Metadata);
|
|
|
|
}
|
|
|
|
if self.additional_values.storage_layout {
|
|
|
|
selection.push(ContractOutputSelection::StorageLayout);
|
|
|
|
}
|
|
|
|
if self.additional_values.devdoc {
|
|
|
|
selection.push(ContractOutputSelection::DevDoc);
|
|
|
|
}
|
|
|
|
if self.additional_values.userdoc {
|
|
|
|
selection.push(ContractOutputSelection::UserDoc);
|
|
|
|
}
|
|
|
|
if self.additional_values.gas_estimates {
|
|
|
|
selection.push(EvmOutputSelection::GasEstimates.into());
|
|
|
|
}
|
|
|
|
if self.additional_values.assembly || self.additional_files.assembly {
|
|
|
|
selection.push(EvmOutputSelection::Assembly.into());
|
|
|
|
}
|
|
|
|
if self.additional_values.ewasm || self.additional_files.ewasm {
|
|
|
|
selection.push(EwasmOutputSelection::All.into());
|
|
|
|
}
|
2022-04-23 08:48:39 +00:00
|
|
|
if self.additional_values.function_debug_data {
|
|
|
|
selection.push(BytecodeOutputSelection::FunctionDebugData.into());
|
|
|
|
}
|
|
|
|
if self.additional_values.method_identifiers {
|
|
|
|
selection.push(EvmOutputSelection::MethodIdentifiers.into());
|
|
|
|
}
|
2022-05-05 14:47:52 +00:00
|
|
|
if self.additional_values.generated_sources {
|
|
|
|
selection.push(
|
|
|
|
EvmOutputSelection::ByteCode(BytecodeOutputSelection::GeneratedSources).into(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if self.additional_values.source_map {
|
|
|
|
selection.push(EvmOutputSelection::ByteCode(BytecodeOutputSelection::SourceMap).into());
|
|
|
|
}
|
2022-02-17 15:31:35 +00:00
|
|
|
selection
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ArtifactOutput for ConfigurableArtifacts {
|
|
|
|
type Artifact = ConfigurableContractArtifact;
|
|
|
|
|
|
|
|
fn write_contract_extras(&self, contract: &Contract, file: &Path) -> Result<(), SolcError> {
|
|
|
|
self.additional_files.write_extras(contract, file)
|
|
|
|
}
|
|
|
|
|
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 {
|
2022-02-17 15:31:35 +00:00
|
|
|
let mut artifact_userdoc = None;
|
|
|
|
let mut artifact_devdoc = None;
|
|
|
|
let mut artifact_metadata = None;
|
|
|
|
let mut artifact_ir = None;
|
|
|
|
let mut artifact_ir_optimized = None;
|
|
|
|
let mut artifact_ewasm = None;
|
|
|
|
let mut artifact_bytecode = None;
|
|
|
|
let mut artifact_deployed_bytecode = None;
|
|
|
|
let mut artifact_gas_estimates = None;
|
2022-04-23 08:48:39 +00:00
|
|
|
let mut artifact_function_debug_data = None;
|
2022-02-17 15:31:35 +00:00
|
|
|
let mut artifact_method_identifiers = None;
|
|
|
|
let mut artifact_assembly = None;
|
|
|
|
let mut artifact_storage_layout = None;
|
2022-05-05 14:47:52 +00:00
|
|
|
let mut generated_sources = None;
|
2022-02-17 15:31:35 +00:00
|
|
|
|
|
|
|
let Contract {
|
|
|
|
abi,
|
|
|
|
metadata,
|
|
|
|
userdoc,
|
|
|
|
devdoc,
|
|
|
|
ir,
|
|
|
|
storage_layout,
|
|
|
|
evm,
|
|
|
|
ewasm,
|
|
|
|
ir_optimized,
|
|
|
|
} = contract;
|
|
|
|
|
|
|
|
if self.additional_values.metadata {
|
|
|
|
artifact_metadata = metadata;
|
|
|
|
}
|
|
|
|
if self.additional_values.userdoc {
|
|
|
|
artifact_userdoc = Some(userdoc);
|
|
|
|
}
|
|
|
|
if self.additional_values.devdoc {
|
|
|
|
artifact_devdoc = Some(devdoc);
|
|
|
|
}
|
|
|
|
if self.additional_values.ewasm {
|
|
|
|
artifact_ewasm = ewasm;
|
|
|
|
}
|
|
|
|
if self.additional_values.ir {
|
|
|
|
artifact_ir = ir;
|
|
|
|
}
|
|
|
|
if self.additional_values.ir_optimized {
|
|
|
|
artifact_ir_optimized = ir_optimized;
|
|
|
|
}
|
|
|
|
if self.additional_values.storage_layout {
|
|
|
|
artifact_storage_layout = Some(storage_layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(evm) = evm {
|
2022-04-23 08:48:39 +00:00
|
|
|
let Evm {
|
2022-02-17 15:31:35 +00:00
|
|
|
assembly,
|
2022-05-05 14:47:52 +00:00
|
|
|
mut bytecode,
|
2022-02-17 15:31:35 +00:00
|
|
|
deployed_bytecode,
|
|
|
|
method_identifiers,
|
|
|
|
gas_estimates,
|
|
|
|
..
|
2022-04-23 08:48:39 +00:00
|
|
|
} = evm;
|
2022-02-17 15:31:35 +00:00
|
|
|
|
2022-04-23 08:48:39 +00:00
|
|
|
if self.additional_values.function_debug_data {
|
|
|
|
artifact_function_debug_data =
|
|
|
|
bytecode.as_ref().map(|b| b.function_debug_data.clone());
|
|
|
|
}
|
2022-05-05 14:47:52 +00:00
|
|
|
if self.additional_values.generated_sources {
|
|
|
|
generated_sources =
|
|
|
|
bytecode.as_mut().map(|code| std::mem::take(&mut code.generated_sources));
|
|
|
|
}
|
2022-04-23 08:48:39 +00:00
|
|
|
|
|
|
|
artifact_bytecode = bytecode.map(Into::into);
|
|
|
|
artifact_deployed_bytecode = deployed_bytecode.map(Into::into);
|
2022-02-17 15:31:35 +00:00
|
|
|
|
|
|
|
if self.additional_values.gas_estimates {
|
|
|
|
artifact_gas_estimates = gas_estimates;
|
|
|
|
}
|
|
|
|
if self.additional_values.method_identifiers {
|
|
|
|
artifact_method_identifiers = Some(method_identifiers);
|
|
|
|
}
|
|
|
|
if self.additional_values.assembly {
|
|
|
|
artifact_assembly = assembly;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ConfigurableContractArtifact {
|
|
|
|
abi,
|
|
|
|
bytecode: artifact_bytecode,
|
|
|
|
deployed_bytecode: artifact_deployed_bytecode,
|
|
|
|
assembly: artifact_assembly,
|
2022-04-23 08:48:39 +00:00
|
|
|
function_debug_data: artifact_function_debug_data,
|
2022-02-17 15:31:35 +00:00
|
|
|
method_identifiers: artifact_method_identifiers,
|
|
|
|
gas_estimates: artifact_gas_estimates,
|
|
|
|
metadata: artifact_metadata,
|
|
|
|
storage_layout: artifact_storage_layout,
|
|
|
|
userdoc: artifact_userdoc,
|
|
|
|
devdoc: artifact_devdoc,
|
|
|
|
ir: artifact_ir,
|
|
|
|
ir_optimized: artifact_ir_optimized,
|
|
|
|
ewasm: artifact_ewasm,
|
2022-04-23 09:20:46 +00:00
|
|
|
ast: source_file.and_then(|s| s.ast.clone()),
|
2022-05-05 14:47:52 +00:00
|
|
|
generated_sources: generated_sources.unwrap_or_default(),
|
2022-02-17 15:31:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Determines the additional values to include in the contract's artifact file
|
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
|
|
|
|
pub struct ExtraOutputValues {
|
|
|
|
pub ast: bool,
|
|
|
|
pub userdoc: bool,
|
|
|
|
pub devdoc: bool,
|
|
|
|
pub method_identifiers: bool,
|
|
|
|
pub storage_layout: bool,
|
|
|
|
pub assembly: bool,
|
|
|
|
pub gas_estimates: bool,
|
|
|
|
pub compact_format: bool,
|
|
|
|
pub metadata: bool,
|
|
|
|
pub ir: bool,
|
|
|
|
pub ir_optimized: bool,
|
|
|
|
pub ewasm: bool,
|
2022-04-23 08:48:39 +00:00
|
|
|
pub function_debug_data: bool,
|
2022-05-05 14:47:52 +00:00
|
|
|
pub generated_sources: bool,
|
|
|
|
pub source_map: bool,
|
2022-02-17 15:31:35 +00:00
|
|
|
|
|
|
|
/// PRIVATE: This structure may grow, As such, constructing this structure should
|
|
|
|
/// _always_ be done using a public constructor or update syntax:
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
///
|
|
|
|
/// use ethers_solc::ExtraOutputValues;
|
|
|
|
/// let config = ExtraOutputValues {
|
|
|
|
/// ir: true,
|
|
|
|
/// ..Default::default()
|
|
|
|
/// };
|
|
|
|
/// ```
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub __non_exhaustive: (),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ExtraOutputValues {
|
|
|
|
/// Returns an instance where all values are set to `true`
|
|
|
|
pub fn all() -> Self {
|
|
|
|
Self {
|
|
|
|
ast: true,
|
|
|
|
userdoc: true,
|
|
|
|
devdoc: true,
|
|
|
|
method_identifiers: true,
|
|
|
|
storage_layout: true,
|
|
|
|
assembly: true,
|
|
|
|
gas_estimates: true,
|
|
|
|
compact_format: true,
|
|
|
|
metadata: true,
|
|
|
|
ir: true,
|
|
|
|
ir_optimized: true,
|
|
|
|
ewasm: true,
|
2022-04-23 08:48:39 +00:00
|
|
|
function_debug_data: true,
|
2022-05-05 14:47:52 +00:00
|
|
|
generated_sources: true,
|
|
|
|
source_map: true,
|
2022-02-17 15:31:35 +00:00
|
|
|
__non_exhaustive: (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the values based on a set of `ContractOutputSelection`
|
|
|
|
pub fn from_output_selection(
|
|
|
|
settings: impl IntoIterator<Item = ContractOutputSelection>,
|
|
|
|
) -> Self {
|
|
|
|
let mut config = Self::default();
|
|
|
|
for value in settings.into_iter() {
|
|
|
|
match value {
|
|
|
|
ContractOutputSelection::DevDoc => {
|
|
|
|
config.devdoc = true;
|
|
|
|
}
|
|
|
|
ContractOutputSelection::UserDoc => {
|
|
|
|
config.userdoc = true;
|
|
|
|
}
|
|
|
|
ContractOutputSelection::Metadata => {
|
|
|
|
config.metadata = true;
|
|
|
|
}
|
|
|
|
ContractOutputSelection::Ir => {
|
|
|
|
config.ir = true;
|
|
|
|
}
|
|
|
|
ContractOutputSelection::IrOptimized => {
|
|
|
|
config.ir_optimized = true;
|
|
|
|
}
|
|
|
|
ContractOutputSelection::StorageLayout => {
|
|
|
|
config.storage_layout = true;
|
|
|
|
}
|
|
|
|
ContractOutputSelection::Evm(evm) => match evm {
|
|
|
|
EvmOutputSelection::All => {
|
|
|
|
config.assembly = true;
|
|
|
|
config.gas_estimates = true;
|
|
|
|
config.method_identifiers = true;
|
2022-05-05 14:47:52 +00:00
|
|
|
config.generated_sources = true;
|
|
|
|
config.source_map = true;
|
2022-02-17 15:31:35 +00:00
|
|
|
}
|
|
|
|
EvmOutputSelection::Assembly => {
|
|
|
|
config.assembly = true;
|
|
|
|
}
|
|
|
|
EvmOutputSelection::MethodIdentifiers => {
|
|
|
|
config.method_identifiers = true;
|
|
|
|
}
|
|
|
|
EvmOutputSelection::GasEstimates => {
|
|
|
|
config.gas_estimates = true;
|
|
|
|
}
|
2022-04-23 08:48:39 +00:00
|
|
|
EvmOutputSelection::ByteCode(BytecodeOutputSelection::FunctionDebugData) => {
|
|
|
|
config.function_debug_data = true;
|
|
|
|
}
|
2022-05-05 14:47:52 +00:00
|
|
|
EvmOutputSelection::ByteCode(BytecodeOutputSelection::GeneratedSources) => {
|
|
|
|
config.generated_sources = true;
|
|
|
|
}
|
|
|
|
EvmOutputSelection::ByteCode(BytecodeOutputSelection::SourceMap) => {
|
|
|
|
config.source_map = true;
|
|
|
|
}
|
2022-02-17 15:31:35 +00:00
|
|
|
_ => {}
|
|
|
|
},
|
|
|
|
ContractOutputSelection::Ewasm(_) => {
|
|
|
|
config.ewasm = true;
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
config
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Determines what to emit as additional file
|
|
|
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
|
|
|
|
pub struct ExtraOutputFiles {
|
2022-04-23 08:40:25 +00:00
|
|
|
pub abi: bool,
|
2022-02-17 15:31:35 +00:00
|
|
|
pub metadata: bool,
|
|
|
|
pub ir_optimized: bool,
|
|
|
|
pub ewasm: bool,
|
|
|
|
pub assembly: bool,
|
2022-05-05 14:47:52 +00:00
|
|
|
pub source_map: bool,
|
|
|
|
pub generated_sources: bool,
|
2022-02-17 15:31:35 +00:00
|
|
|
|
|
|
|
/// PRIVATE: This structure may grow, As such, constructing this structure should
|
|
|
|
/// _always_ be done using a public constructor or update syntax:
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
///
|
|
|
|
/// use ethers_solc::ExtraOutputFiles;
|
|
|
|
/// let config = ExtraOutputFiles {
|
|
|
|
/// metadata: true,
|
|
|
|
/// ..Default::default()
|
|
|
|
/// };
|
|
|
|
/// ```
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub __non_exhaustive: (),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ExtraOutputFiles {
|
|
|
|
/// Returns an instance where all values are set to `true`
|
|
|
|
pub fn all() -> Self {
|
|
|
|
Self {
|
2022-04-23 08:40:25 +00:00
|
|
|
abi: true,
|
2022-02-17 15:31:35 +00:00
|
|
|
metadata: true,
|
|
|
|
ir_optimized: true,
|
|
|
|
ewasm: true,
|
|
|
|
assembly: true,
|
2022-05-05 14:47:52 +00:00
|
|
|
source_map: true,
|
|
|
|
generated_sources: true,
|
2022-02-17 15:31:35 +00:00
|
|
|
__non_exhaustive: (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the values based on a set of `ContractOutputSelection`
|
|
|
|
pub fn from_output_selection(
|
|
|
|
settings: impl IntoIterator<Item = ContractOutputSelection>,
|
|
|
|
) -> Self {
|
|
|
|
let mut config = Self::default();
|
|
|
|
for value in settings.into_iter() {
|
|
|
|
match value {
|
2022-04-23 08:40:25 +00:00
|
|
|
ContractOutputSelection::Abi => {
|
|
|
|
config.abi = true;
|
|
|
|
}
|
2022-02-17 15:31:35 +00:00
|
|
|
ContractOutputSelection::Metadata => {
|
|
|
|
config.metadata = true;
|
|
|
|
}
|
|
|
|
ContractOutputSelection::IrOptimized => {
|
|
|
|
config.ir_optimized = true;
|
|
|
|
}
|
|
|
|
ContractOutputSelection::Evm(evm) => match evm {
|
|
|
|
EvmOutputSelection::All => {
|
|
|
|
config.assembly = true;
|
2022-05-05 14:47:52 +00:00
|
|
|
config.generated_sources = true;
|
|
|
|
config.source_map = true;
|
2022-02-17 15:31:35 +00:00
|
|
|
}
|
|
|
|
EvmOutputSelection::Assembly => {
|
|
|
|
config.assembly = true;
|
|
|
|
}
|
2022-05-05 14:47:52 +00:00
|
|
|
EvmOutputSelection::ByteCode(BytecodeOutputSelection::GeneratedSources) => {
|
|
|
|
config.generated_sources = true;
|
|
|
|
}
|
|
|
|
EvmOutputSelection::ByteCode(BytecodeOutputSelection::SourceMap) => {
|
|
|
|
config.source_map = true;
|
|
|
|
}
|
2022-02-17 15:31:35 +00:00
|
|
|
_ => {}
|
|
|
|
},
|
|
|
|
ContractOutputSelection::Ewasm(_) => {
|
|
|
|
config.ewasm = true;
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
config
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Write the set values as separate files
|
|
|
|
pub fn write_extras(&self, contract: &Contract, file: &Path) -> Result<(), SolcError> {
|
2022-04-23 08:40:25 +00:00
|
|
|
if self.abi {
|
|
|
|
if let Some(ref abi) = contract.abi {
|
|
|
|
let file = file.with_extension("abi.json");
|
|
|
|
fs::write(&file, serde_json::to_string_pretty(abi)?)
|
|
|
|
.map_err(|err| SolcError::io(err, file))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 15:31:35 +00:00
|
|
|
if self.metadata {
|
|
|
|
if let Some(ref metadata) = contract.metadata {
|
|
|
|
let file = file.with_extension("metadata.json");
|
|
|
|
fs::write(&file, serde_json::to_string_pretty(metadata)?)
|
|
|
|
.map_err(|err| SolcError::io(err, file))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.ir_optimized {
|
|
|
|
if let Some(ref iropt) = contract.ir_optimized {
|
|
|
|
let file = file.with_extension("iropt");
|
|
|
|
fs::write(&file, iropt).map_err(|err| SolcError::io(err, file))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.ewasm {
|
|
|
|
if let Some(ref ir) = contract.ir {
|
|
|
|
let file = file.with_extension("ir");
|
|
|
|
fs::write(&file, ir).map_err(|err| SolcError::io(err, file))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.ewasm {
|
|
|
|
if let Some(ref ewasm) = contract.ewasm {
|
|
|
|
let file = file.with_extension("ewasm");
|
|
|
|
fs::write(&file, serde_json::to_vec_pretty(ewasm)?)
|
|
|
|
.map_err(|err| SolcError::io(err, file))?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.assembly {
|
|
|
|
if let Some(ref evm) = contract.evm {
|
|
|
|
if let Some(ref asm) = evm.assembly {
|
|
|
|
let file = file.with_extension("asm");
|
|
|
|
fs::write(&file, asm).map_err(|err| SolcError::io(err, file))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-05 14:47:52 +00:00
|
|
|
if self.generated_sources {
|
|
|
|
if let Some(ref evm) = contract.evm {
|
|
|
|
if let Some(ref bytecode) = evm.bytecode {
|
|
|
|
let file = file.with_extension("gensources");
|
|
|
|
fs::write(&file, serde_json::to_vec_pretty(&bytecode.generated_sources)?)
|
|
|
|
.map_err(|err| SolcError::io(err, file))?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.source_map {
|
|
|
|
if let Some(ref evm) = contract.evm {
|
|
|
|
if let Some(ref bytecode) = evm.bytecode {
|
|
|
|
if let Some(ref sourcemap) = bytecode.source_map {
|
|
|
|
let file = file.with_extension("sourcemap");
|
|
|
|
fs::write(&file, sourcemap).map_err(|err| SolcError::io(err, file))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 15:31:35 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|