2022-02-17 15:31:35 +00:00
|
|
|
//! A configurable artifacts handler implementation
|
2022-06-30 16:16:47 +00:00
|
|
|
//!
|
|
|
|
//! Configuring artifacts requires two pieces: the `ConfigurableArtifacts` handler, which contains
|
|
|
|
//! the configuration of how to construct the `ConfigurableArtifact` type based on a `Contract`. The
|
|
|
|
//! `ConfigurableArtifacts` populates a single `Artifact`, the `ConfigurableArtifact`, by default
|
|
|
|
//! with essential entries only, such as `abi`, `bytecode`,..., but may include additional values
|
|
|
|
//! based on its `ExtraOutputValues` that maps to various objects in the solc contract output, see
|
2022-07-24 01:16:55 +00:00
|
|
|
//! also: [`OutputSelection`](crate::artifacts::output_selection::OutputSelection). In addition to
|
|
|
|
//! that some output values can also be emitted as standalone files.
|
2022-02-17 15:31:35 +00:00
|
|
|
|
|
|
|
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::{
|
2023-01-27 18:15:03 +00:00
|
|
|
BytecodeOutputSelection, ContractOutputSelection, DeployedBytecodeOutputSelection,
|
|
|
|
EvmOutputSelection, EwasmOutputSelection,
|
2022-04-23 08:48:39 +00:00
|
|
|
},
|
2022-12-22 16:22:11 +00:00
|
|
|
Ast, CompactContractBytecodeCow, DevDoc, Evm, Ewasm, FunctionDebugData, GasEstimates,
|
|
|
|
GeneratedSource, LosslessAbi, LosslessMetadata, Metadata, Offsets, Settings, StorageLayout,
|
|
|
|
UserDoc,
|
2022-02-17 15:31:35 +00:00
|
|
|
},
|
2022-05-22 22:19:59 +00:00
|
|
|
sources::VersionedSourceFile,
|
2023-01-27 18:15:03 +00:00
|
|
|
Artifact, 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")]
|
2022-06-30 16:16:47 +00:00
|
|
|
pub opcodes: Option<String>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
2022-02-17 15:31:35 +00:00
|
|
|
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")]
|
2022-06-10 13:49:19 +00:00
|
|
|
pub raw_metadata: Option<String>,
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
2022-02-17 15:31:35 +00:00
|
|
|
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")]
|
2022-12-22 16:22:11 +00:00
|
|
|
pub ast: Option<Ast>,
|
2022-05-19 18:02:31 +00:00
|
|
|
/// The identifier of the source file
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
pub id: Option<u32>,
|
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
|
|
|
|
}
|
2022-05-19 18:02:31 +00:00
|
|
|
|
|
|
|
/// Returns the source file of this artifact's contract
|
|
|
|
pub fn source_file(&self) -> Option<SourceFile> {
|
|
|
|
self.id.map(|id| SourceFile { id, ast: self.ast.clone() })
|
|
|
|
}
|
2022-02-17 15:31:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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": {...},
|
2022-05-16 17:28:53 +00:00
|
|
|
/// "deployedBytecode": {...},
|
|
|
|
/// "methodIdentifiers": {...},
|
2022-02-17 15:31:35 +00:00
|
|
|
/// // 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;
|
2022-06-10 13:49:19 +00:00
|
|
|
let mut artifact_raw_metadata = None;
|
2022-02-17 15:31:35 +00:00
|
|
|
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-06-30 16:16:47 +00:00
|
|
|
let mut opcodes = 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 {
|
2022-06-10 13:49:19 +00:00
|
|
|
if let Some(LosslessMetadata { raw_metadata, metadata }) = metadata {
|
|
|
|
artifact_raw_metadata = Some(raw_metadata);
|
|
|
|
artifact_metadata = Some(metadata);
|
|
|
|
}
|
2022-02-17 15:31:35 +00:00
|
|
|
}
|
|
|
|
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 =
|
2022-06-30 16:16:47 +00:00
|
|
|
bytecode.as_mut().map(|code| std::mem::take(&mut code.function_debug_data));
|
2022-04-23 08:48:39 +00:00
|
|
|
}
|
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
|
|
|
|
2022-06-30 16:16:47 +00:00
|
|
|
if self.additional_values.opcodes {
|
|
|
|
opcodes = bytecode.as_mut().and_then(|code| code.opcodes.take())
|
|
|
|
}
|
|
|
|
|
2022-04-23 08:48:39 +00:00
|
|
|
artifact_bytecode = bytecode.map(Into::into);
|
|
|
|
artifact_deployed_bytecode = deployed_bytecode.map(Into::into);
|
2022-05-16 17:28:53 +00:00
|
|
|
artifact_method_identifiers = Some(method_identifiers);
|
2022-02-17 15:31:35 +00:00
|
|
|
|
|
|
|
if self.additional_values.gas_estimates {
|
|
|
|
artifact_gas_estimates = gas_estimates;
|
|
|
|
}
|
|
|
|
if self.additional_values.assembly {
|
|
|
|
artifact_assembly = assembly;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ConfigurableContractArtifact {
|
|
|
|
abi,
|
|
|
|
bytecode: artifact_bytecode,
|
|
|
|
deployed_bytecode: artifact_deployed_bytecode,
|
|
|
|
assembly: artifact_assembly,
|
2022-06-30 16:16:47 +00:00
|
|
|
opcodes,
|
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,
|
2022-06-10 13:49:19 +00:00
|
|
|
raw_metadata: artifact_raw_metadata,
|
2022-02-17 15:31:35 +00:00
|
|
|
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-05-19 18:02:31 +00:00
|
|
|
id: source_file.as_ref().map(|s| s.id),
|
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
|
|
|
}
|
|
|
|
}
|
2022-05-22 22:19:59 +00:00
|
|
|
|
|
|
|
fn standalone_source_file_to_artifact(
|
|
|
|
&self,
|
|
|
|
_path: &str,
|
|
|
|
file: &VersionedSourceFile,
|
|
|
|
) -> Option<Self::Artifact> {
|
|
|
|
file.source_file.ast.clone().map(|ast| ConfigurableContractArtifact {
|
2022-06-04 18:38:21 +00:00
|
|
|
abi: Some(LosslessAbi::default()),
|
2022-05-22 22:19:59 +00:00
|
|
|
id: Some(file.source_file.id),
|
|
|
|
ast: Some(ast),
|
2022-05-31 16:29:25 +00:00
|
|
|
bytecode: Some(CompactBytecode::empty()),
|
|
|
|
deployed_bytecode: Some(CompactDeployedBytecode::empty()),
|
2022-05-22 22:19:59 +00:00
|
|
|
..Default::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-06-30 16:16:47 +00:00
|
|
|
pub opcodes: 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-06-30 16:16:47 +00:00
|
|
|
opcodes: 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-06-30 16:16:47 +00:00
|
|
|
config.opcodes = 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-06-30 16:16:47 +00:00
|
|
|
EvmOutputSelection::ByteCode(BytecodeOutputSelection::Opcodes) => {
|
|
|
|
config.opcodes = 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,
|
2023-01-17 00:35:47 +00:00
|
|
|
pub ir: bool,
|
2022-02-17 15:31:35 +00:00
|
|
|
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,
|
2023-01-27 18:15:03 +00:00
|
|
|
pub bytecode: bool,
|
|
|
|
pub deployed_bytecode: 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,
|
2023-01-17 00:35:47 +00:00
|
|
|
ir: true,
|
2022-02-17 15:31:35 +00:00
|
|
|
ir_optimized: true,
|
|
|
|
ewasm: true,
|
|
|
|
assembly: true,
|
2022-05-05 14:47:52 +00:00
|
|
|
source_map: true,
|
|
|
|
generated_sources: true,
|
2023-01-27 18:15:03 +00:00
|
|
|
bytecode: true,
|
|
|
|
deployed_bytecode: 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;
|
|
|
|
}
|
2023-01-17 00:35:47 +00:00
|
|
|
ContractOutputSelection::Ir => {
|
|
|
|
config.ir = true;
|
|
|
|
}
|
2022-02-17 15:31:35 +00:00
|
|
|
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;
|
2023-01-27 18:15:03 +00:00
|
|
|
config.bytecode = true;
|
|
|
|
config.deployed_bytecode = 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;
|
|
|
|
}
|
2023-01-27 18:15:03 +00:00
|
|
|
EvmOutputSelection::ByteCode(BytecodeOutputSelection::Object) => {
|
|
|
|
config.bytecode = true;
|
|
|
|
}
|
2022-05-05 14:47:52 +00:00
|
|
|
EvmOutputSelection::ByteCode(BytecodeOutputSelection::SourceMap) => {
|
|
|
|
config.source_map = true;
|
|
|
|
}
|
2023-01-27 18:15:03 +00:00
|
|
|
EvmOutputSelection::DeployedByteCode(DeployedBytecodeOutputSelection::All) |
|
|
|
|
EvmOutputSelection::DeployedByteCode(
|
|
|
|
DeployedBytecodeOutputSelection::Object,
|
|
|
|
) => {
|
|
|
|
config.deployed_bytecode = 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");
|
2022-06-10 13:49:19 +00:00
|
|
|
fs::write(&file, serde_json::to_string_pretty(&metadata.raw_json()?)?)
|
2022-02-17 15:31:35 +00:00
|
|
|
.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))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-17 00:35:47 +00:00
|
|
|
if self.ir {
|
2022-02-17 15:31:35 +00:00
|
|
|
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))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-27 18:15:03 +00:00
|
|
|
if self.bytecode {
|
|
|
|
if let Some(ref code) = contract.get_bytecode_bytes() {
|
|
|
|
let code = hex::encode(code.as_ref());
|
|
|
|
let file = file.with_extension("bin");
|
|
|
|
fs::write(&file, code).map_err(|err| SolcError::io(err, file))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if self.deployed_bytecode {
|
|
|
|
if let Some(ref code) = contract.get_deployed_bytecode_bytes() {
|
|
|
|
let code = hex::encode(code.as_ref());
|
|
|
|
let file = file.with_extension("deployed-bin");
|
|
|
|
fs::write(&file, code).map_err(|err| SolcError::io(err, file))?
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 15:31:35 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|