feat(solc): include opcodes in output (#1435)

This commit is contained in:
Matthias Seitz 2022-06-30 18:16:47 +02:00 committed by GitHub
parent 73d3d3f494
commit 9892756ee4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 14 deletions

View File

@ -1,4 +1,12 @@
//! A configurable artifacts handler implementation //! A configurable artifacts handler implementation
//!
//! 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
//! also: [`OutputSelection`](crate::artifacts::OutputSelection). In addition to that some output
//! values can also be emitted as standalone files.
use crate::{ use crate::{
artifacts::{ artifacts::{
@ -34,6 +42,8 @@ pub struct ConfigurableContractArtifact {
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
pub assembly: Option<String>, pub assembly: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
pub opcodes: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub method_identifiers: Option<BTreeMap<String, String>>, pub method_identifiers: Option<BTreeMap<String, String>>,
#[serde(default, skip_serializing_if = "Vec::is_empty")] #[serde(default, skip_serializing_if = "Vec::is_empty")]
pub generated_sources: Vec<GeneratedSource>, pub generated_sources: Vec<GeneratedSource>,
@ -248,6 +258,7 @@ impl ArtifactOutput for ConfigurableArtifacts {
let mut artifact_assembly = None; let mut artifact_assembly = None;
let mut artifact_storage_layout = None; let mut artifact_storage_layout = None;
let mut generated_sources = None; let mut generated_sources = None;
let mut opcodes = None;
let Contract { let Contract {
abi, abi,
@ -298,13 +309,17 @@ impl ArtifactOutput for ConfigurableArtifacts {
if self.additional_values.function_debug_data { if self.additional_values.function_debug_data {
artifact_function_debug_data = artifact_function_debug_data =
bytecode.as_ref().map(|b| b.function_debug_data.clone()); bytecode.as_mut().map(|code| std::mem::take(&mut code.function_debug_data));
} }
if self.additional_values.generated_sources { if self.additional_values.generated_sources {
generated_sources = generated_sources =
bytecode.as_mut().map(|code| std::mem::take(&mut code.generated_sources)); bytecode.as_mut().map(|code| std::mem::take(&mut code.generated_sources));
} }
if self.additional_values.opcodes {
opcodes = bytecode.as_mut().and_then(|code| code.opcodes.take())
}
artifact_bytecode = bytecode.map(Into::into); artifact_bytecode = bytecode.map(Into::into);
artifact_deployed_bytecode = deployed_bytecode.map(Into::into); artifact_deployed_bytecode = deployed_bytecode.map(Into::into);
artifact_method_identifiers = Some(method_identifiers); artifact_method_identifiers = Some(method_identifiers);
@ -322,6 +337,7 @@ impl ArtifactOutput for ConfigurableArtifacts {
bytecode: artifact_bytecode, bytecode: artifact_bytecode,
deployed_bytecode: artifact_deployed_bytecode, deployed_bytecode: artifact_deployed_bytecode,
assembly: artifact_assembly, assembly: artifact_assembly,
opcodes,
function_debug_data: artifact_function_debug_data, function_debug_data: artifact_function_debug_data,
method_identifiers: artifact_method_identifiers, method_identifiers: artifact_method_identifiers,
gas_estimates: artifact_gas_estimates, gas_estimates: artifact_gas_estimates,
@ -373,6 +389,7 @@ pub struct ExtraOutputValues {
pub function_debug_data: bool, pub function_debug_data: bool,
pub generated_sources: bool, pub generated_sources: bool,
pub source_map: bool, pub source_map: bool,
pub opcodes: bool,
/// PRIVATE: This structure may grow, As such, constructing this structure should /// PRIVATE: This structure may grow, As such, constructing this structure should
/// _always_ be done using a public constructor or update syntax: /// _always_ be done using a public constructor or update syntax:
@ -408,6 +425,7 @@ impl ExtraOutputValues {
function_debug_data: true, function_debug_data: true,
generated_sources: true, generated_sources: true,
source_map: true, source_map: true,
opcodes: true,
__non_exhaustive: (), __non_exhaustive: (),
} }
} }
@ -444,6 +462,7 @@ impl ExtraOutputValues {
config.method_identifiers = true; config.method_identifiers = true;
config.generated_sources = true; config.generated_sources = true;
config.source_map = true; config.source_map = true;
config.opcodes = true;
} }
EvmOutputSelection::Assembly => { EvmOutputSelection::Assembly => {
config.assembly = true; config.assembly = true;
@ -457,6 +476,9 @@ impl ExtraOutputValues {
EvmOutputSelection::ByteCode(BytecodeOutputSelection::FunctionDebugData) => { EvmOutputSelection::ByteCode(BytecodeOutputSelection::FunctionDebugData) => {
config.function_debug_data = true; config.function_debug_data = true;
} }
EvmOutputSelection::ByteCode(BytecodeOutputSelection::Opcodes) => {
config.opcodes = true;
}
EvmOutputSelection::ByteCode(BytecodeOutputSelection::GeneratedSources) => { EvmOutputSelection::ByteCode(BytecodeOutputSelection::GeneratedSources) => {
config.generated_sources = true; config.generated_sources = true;
} }

View File

@ -1,8 +1,16 @@
//! Output artifact handling //! Output artifact handling
use crate::{ use crate::{
artifacts::FileToContractsMap, error::Result, utils, HardhatArtifact, ProjectPathsConfig, artifacts::{
SolcError, contract::{CompactContract, CompactContractBytecode, Contract},
BytecodeObject, CompactBytecode, CompactContractBytecodeCow, CompactDeployedBytecode,
FileToContractsMap, SourceFile,
},
compile::output::{contracts::VersionedContracts, sources::VersionedSourceFiles},
error::Result,
sourcemap::{SourceMap, SyntaxError},
sources::VersionedSourceFile,
utils, HardhatArtifact, ProjectPathsConfig, SolcError,
}; };
use ethers_core::{abi::Abi, types::Bytes}; use ethers_core::{abi::Abi, types::Bytes};
use semver::Version; use semver::Version;
@ -13,18 +21,7 @@ use std::{
fmt, fs, io, fmt, fs, io,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
mod configurable; mod configurable;
use crate::{
artifacts::{
contract::{CompactContract, CompactContractBytecode, Contract},
BytecodeObject, CompactBytecode, CompactContractBytecodeCow, CompactDeployedBytecode,
SourceFile,
},
compile::output::{contracts::VersionedContracts, sources::VersionedSourceFiles},
sourcemap::{SourceMap, SyntaxError},
sources::VersionedSourceFile,
};
pub use configurable::*; pub use configurable::*;
/// Represents unique artifact metadata for identifying artifacts on output /// Represents unique artifact metadata for identifying artifacts on output

View File

@ -139,6 +139,7 @@ fn can_compile_configured() {
metadata: true, metadata: true,
ir: true, ir: true,
ir_optimized: true, ir_optimized: true,
opcodes: true,
..Default::default() ..Default::default()
}, },
..Default::default() ..Default::default()
@ -152,6 +153,7 @@ fn can_compile_configured() {
assert!(artifact.raw_metadata.is_some()); assert!(artifact.raw_metadata.is_some());
assert!(artifact.ir.is_some()); assert!(artifact.ir.is_some());
assert!(artifact.ir_optimized.is_some()); assert!(artifact.ir_optimized.is_some());
assert!(artifact.opcodes.is_some());
} }
#[test] #[test]