Skip to content

Commit

Permalink
feat: make artifact type configurable (#762)
Browse files Browse the repository at this point in the history
* feat: add additional output options

* feat: add extra output options

* feat: update types

* fix: breaking change

* chore: cargo fix

* test: add extra output tests

* bump ethers

* Update config/src/lib.rs

Co-authored-by: Georgios Konstantopoulos <[email protected]>

* fix: rustfmt

Co-authored-by: Georgios Konstantopoulos <[email protected]>
  • Loading branch information
mattsse and gakonst authored Feb 17, 2022
1 parent 9a08488 commit bc88a98
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 68 deletions.
30 changes: 15 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions cli/src/cmd/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! build command
use ethers::solc::{MinimalCombinedArtifacts, Project, ProjectCompileOutput};
use ethers::solc::{Project, ProjectCompileOutput};
use std::path::PathBuf;

use crate::{cmd::Cmd, opts::forge::CompilerArgs};
Expand Down Expand Up @@ -152,7 +152,7 @@ pub struct BuildArgs {
}

impl Cmd for BuildArgs {
type Output = ProjectCompileOutput<MinimalCombinedArtifacts>;
type Output = ProjectCompileOutput;
fn run(self) -> eyre::Result<Self::Output> {
let project = self.project()?;
super::compile(&project)
Expand Down Expand Up @@ -220,8 +220,14 @@ impl Provider for BuildArgs {
dict.insert("optimizer".to_string(), self.compiler.optimize.into());
}

if let Some(extra) = &self.compiler.extra_output {
dict.insert("extra_output".to_string(), extra.clone().into());
if let Some(ref extra) = self.compiler.extra_output {
let selection: Vec<_> = extra.iter().map(|s| s.to_string()).collect();
dict.insert("extra_output".to_string(), selection.into());
}

if let Some(ref extra) = self.compiler.extra_output_files {
let selection: Vec<_> = extra.iter().map(|s| s.to_string()).collect();
dict.insert("extra_output_files".to_string(), selection.into());
}

Ok(Map::from([(Config::selected_profile(), dict)]))
Expand Down
14 changes: 6 additions & 8 deletions cli/src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,11 @@ pub trait Cmd: clap::Parser + Sized {
fn run(self) -> eyre::Result<Self::Output>;
}

use ethers::solc::{
artifacts::CompactContractBytecode, MinimalCombinedArtifacts, Project, ProjectCompileOutput,
};
use ethers::solc::{artifacts::CompactContractBytecode, Project, ProjectCompileOutput};

/// Compiles the provided [`Project`], throws if there's any compiler error and logs whether
/// compilation was successful or if there was a cache hit.
pub fn compile(project: &Project) -> eyre::Result<ProjectCompileOutput<MinimalCombinedArtifacts>> {
pub fn compile(project: &Project) -> eyre::Result<ProjectCompileOutput> {
if !project.paths.sources.exists() {
eyre::bail!(
r#"no contracts to compile, contracts folder "{}" does not exist.
Expand All @@ -101,9 +99,9 @@ If you are in a subdirectory in a Git repository, try adding `--root .`"#,

/// Manually compile a project with added sources
pub fn manual_compile(
project: &Project<MinimalCombinedArtifacts>,
project: &Project,
added_sources: Vec<PathBuf>,
) -> eyre::Result<ProjectCompileOutput<MinimalCombinedArtifacts>> {
) -> eyre::Result<ProjectCompileOutput> {
let mut sources = project.paths.read_input_files()?;
sources.extend(Source::read_all_files(added_sources)?);
println!("compiling...");
Expand Down Expand Up @@ -135,7 +133,7 @@ pub fn manual_compile(
/// Runtime Bytecode of the given contract.
pub fn read_artifact(
project: &Project,
compiled: ProjectCompileOutput<MinimalCombinedArtifacts>,
compiled: ProjectCompileOutput,
contract: ContractInfo,
) -> eyre::Result<(Abi, CompactBytecode, CompactDeployedBytecode)> {
Ok(match contract.path {
Expand All @@ -149,7 +147,7 @@ pub fn read_artifact(
// contract name?
fn get_artifact_from_name(
contract: ContractInfo,
compiled: ProjectCompileOutput<MinimalCombinedArtifacts>,
compiled: ProjectCompileOutput,
) -> eyre::Result<(Abi, CompactBytecode, CompactDeployedBytecode)> {
let mut has_found_contract = false;
let mut contract_artifact = None;
Expand Down
4 changes: 2 additions & 2 deletions cli/src/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use foundry_utils::IntoFunction;
use std::{collections::BTreeMap, path::PathBuf};
use ui::{TUIExitReason, Tui, Ui};

use ethers::solc::{MinimalCombinedArtifacts, Project};
use ethers::solc::Project;

use crate::opts::evm::EvmArgs;
use ansi_term::Colour;
Expand Down Expand Up @@ -264,7 +264,7 @@ struct ExtraLinkingInfo<'a> {
}

pub struct BuildOutput {
pub project: Project<MinimalCombinedArtifacts>,
pub project: Project,
pub contract: CompactContractBytecode,
pub highlevel_known_contracts: BTreeMap<String, ContractBytecodeSome>,
pub sources: BTreeMap<u32, String>,
Expand Down
13 changes: 10 additions & 3 deletions cli/src/opts/forge.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clap::{Parser, Subcommand, ValueHint};

use ethers::solc::EvmVersion;
use ethers::solc::{artifacts::output_selection::ContractOutputSelection, EvmVersion};
use std::{path::PathBuf, str::FromStr};

use crate::cmd::{
Expand Down Expand Up @@ -138,11 +138,18 @@ pub struct CompilerArgs {
pub optimize_runs: Option<usize>,

#[clap(
help = "Extra output types [evm.assembly, ewasm, ir, irOptimized] eg: `--extra-output evm.assembly`",
help = "Extra output types to include in the contract's json artifact [evm.assembly, ewasm, ir, irOptimized, metadata] eg: `--extra-output evm.assembly`",
long
)]
#[serde(skip_serializing_if = "Option::is_none")]
pub extra_output: Option<Vec<String>>,
pub extra_output: Option<Vec<ContractOutputSelection>>,

#[clap(
help = "Extra output types to write to a separate file [metadata, ir, irOptimized, ewasm] eg: `--extra-output-files metadata`",
long
)]
#[serde(skip_serializing_if = "Option::is_none")]
pub extra_output_files: Option<Vec<ContractOutputSelection>>,
}

/// Represents the common dapp argument pattern for `<path>:<contractname>` where `<path>:` is
Expand Down
9 changes: 7 additions & 2 deletions cli/test-utils/src/util.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use ethers_solc::{
cache::SolFilesCache,
project_util::{copy_dir, TempProject},
ArtifactOutput, MinimalCombinedArtifacts, PathStyle, ProjectPathsConfig,
ArtifactOutput, ConfigurableArtifacts, PathStyle, ProjectPathsConfig,
};
use foundry_config::Config;
use once_cell::sync::Lazy;
Expand Down Expand Up @@ -75,7 +75,7 @@ pub fn setup_project(test: TestProject) -> (TestProject, TestCommand) {
///
/// Test projects are created from a global atomic counter to avoid duplicates.
#[derive(Clone, Debug)]
pub struct TestProject<T: ArtifactOutput = MinimalCombinedArtifacts> {
pub struct TestProject<T: ArtifactOutput = ConfigurableArtifacts> {
/// The directory in which this test executable is running.
root: PathBuf,
/// The project in which the test should run.
Expand Down Expand Up @@ -267,6 +267,11 @@ impl TestCommand {
self
}

/// Resets the command
pub fn fuse(&mut self) -> &mut TestCommand {
self.set_cmd(self.project.bin())
}

/// Sets the current working directory
pub fn set_current_dir(&mut self, p: impl AsRef<Path>) {
drop(self.current_dir_lock.take());
Expand Down
20 changes: 20 additions & 0 deletions cli/tests/cmd.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Contains various tests for checking forge's commands
use ethers::solc::{artifacts::Metadata, ConfigurableContractArtifact};
use evm_adapters::evm_opts::{EvmOpts, EvmType};
use foundry_cli_test_utils::{
ethers_solc::{remappings::Remapping, PathStyle},
Expand Down Expand Up @@ -242,6 +243,25 @@ forgetest!(can_clean_hardhat, PathStyle::HardHat, |prj: TestProject, mut cmd: Te
prj.assert_cleaned();
});

// checks that extra output works
forgetest_init!(can_emit_extra_output, |prj: TestProject, mut cmd: TestCommand| {
cmd.args(["build", "--extra-output", "metadata"]);
cmd.assert_non_empty_stdout();

let artifact_path = prj.paths().artifacts.join("Contract.sol/Contract.json");
let artifact: ConfigurableContractArtifact =
ethers::solc::utils::read_json_file(artifact_path).unwrap();
assert!(artifact.metadata.is_some());

cmd.fuse()
.args(["build", "--extra-output-files", "metadata", "--force", "--root"])
.arg(prj.root());
cmd.assert_non_empty_stdout();

let metadata_path = prj.paths().artifacts.join("Contract.sol/Contract.metadata.json");
let artifact: Metadata = ethers::solc::utils::read_json_file(metadata_path).unwrap();
});

// test against a local checkout, useful to debug with local ethers-rs patch
forgetest_ignore!(can_compile_local_spells, |_: TestProject, mut cmd: TestCommand| {
let current_dir = std::env::current_dir().unwrap();
Expand Down
Loading

0 comments on commit bc88a98

Please sign in to comment.