From 23046d889c11620ee833d6df79c3304f5b97840d Mon Sep 17 00:00:00 2001 From: lmanini Date: Mon, 29 May 2023 16:52:34 +0200 Subject: [PATCH 1/5] added selectors.rs --- cli/src/cmd/forge/mod.rs | 1 + cli/src/cmd/forge/selectors.rs | 94 ++++++++++++++++++++++++++++++++++ cli/src/forge.rs | 1 + cli/src/opts/forge.rs | 8 +++ 4 files changed, 104 insertions(+) create mode 100644 cli/src/cmd/forge/selectors.rs diff --git a/cli/src/cmd/forge/mod.rs b/cli/src/cmd/forge/mod.rs index 29fcadf9c73c..73e694d8bc33 100644 --- a/cli/src/cmd/forge/mod.rs +++ b/cli/src/cmd/forge/mod.rs @@ -57,6 +57,7 @@ pub mod install; pub mod remappings; pub mod remove; pub mod script; +pub mod selectors; pub mod snapshot; pub mod test; pub mod tree; diff --git a/cli/src/cmd/forge/selectors.rs b/cli/src/cmd/forge/selectors.rs new file mode 100644 index 000000000000..fa6143b259ed --- /dev/null +++ b/cli/src/cmd/forge/selectors.rs @@ -0,0 +1,94 @@ +use crate::{ + cmd::forge::build::{CoreBuildArgs, ProjectPathsArgs}, + opts::forge::CompilerArgs, + utils::FoundryPathExt, +}; +use clap::Parser; +use ethers::prelude::artifacts::output_selection::ContractOutputSelection; +use foundry_common::{ + compile, + selectors::{import_selectors, SelectorImportData}, +}; + +#[derive(Debug, Clone, Parser)] +pub enum SelectorsSubcommands { + /// Upload selectors to registry + #[clap(visible_alias = "up")] + Upload { + /// The name of the contract to upload selectors for. + #[clap(required_unless_present = "all")] + contract: Option, + + /// Upload selectors for all contracts in the project. + #[clap(long, required_unless_present = "contract")] + all: bool, + + #[clap(flatten)] + project_paths: ProjectPathsArgs, + }, +} + +impl SelectorsSubcommands { + pub async fn run(self) -> eyre::Result<()> { + match self { + SelectorsSubcommands::Upload { contract, all, project_paths } => { + let build_args = CoreBuildArgs { + project_paths: project_paths.clone(), + compiler: CompilerArgs { + extra_output: vec![ContractOutputSelection::Abi], + ..Default::default() + }, + ..Default::default() + }; + + let project = build_args.project()?; + let outcome = compile::suppress_compile(&project)?; + let artifacts = if all { + outcome + .into_artifacts_with_files() + .filter(|(file, _, _)| { + let is_sources_path = file + .starts_with(&project.paths.sources.to_string_lossy().to_string()); + let is_test = file.is_sol_test(); + + is_sources_path && !is_test + }) + .map(|(_, contract, artifact)| (contract, artifact)) + .collect() + } else { + let contract = contract.unwrap(); + let found_artifact = outcome.find_first(&contract); + let artifact = found_artifact + .ok_or_else(|| { + eyre::eyre!( + "Could not find artifact `{contract}` in the compiled artifacts" + ) + })? + .clone(); + vec![(contract, artifact)] + }; + + let mut artifacts = artifacts.into_iter().peekable(); + while let Some((contract, artifact)) = artifacts.next() { + let abi = artifact.abi.ok_or(eyre::eyre!("Unable to fetch abi"))?; + if abi.abi.functions.is_empty() && + abi.abi.events.is_empty() && + abi.abi.errors.is_empty() + { + continue + } + + println!("Uploading selectors for {contract}..."); + + // upload abi to selector database + import_selectors(SelectorImportData::Abi(vec![abi])).await?.describe(); + + if artifacts.peek().is_some() { + println!() + } + } + } + } + Ok(()) + } +} diff --git a/cli/src/forge.rs b/cli/src/forge.rs index 815383cabffe..9d7a38e5f3c5 100644 --- a/cli/src/forge.rs +++ b/cli/src/forge.rs @@ -96,5 +96,6 @@ fn main() -> eyre::Result<()> { Ok(()) } Subcommands::Doc(cmd) => cmd.run(), + Subcommands::Selectors { command } => utils::block_on(command.run()), } } diff --git a/cli/src/opts/forge.rs b/cli/src/opts/forge.rs index 7db36a9fc5d8..f0ae4c7a5e9e 100644 --- a/cli/src/opts/forge.rs +++ b/cli/src/opts/forge.rs @@ -16,6 +16,7 @@ use crate::cmd::forge::{ remappings::RemappingArgs, remove::RemoveArgs, script::ScriptArgs, + selectors::SelectorsSubcommands, snapshot, test, tree, update, verify::{VerifyArgs, VerifyCheckArgs}, }; @@ -155,6 +156,13 @@ pub enum Subcommands { /// Generate documentation for the project. Doc(DocArgs), + + /// Function selector utilities + #[clap(visible_alias = "se")] + Selectors { + #[clap(subcommand)] + command: SelectorsSubcommands, + }, } // A set of solc compiler settings that can be set via command line arguments, which are intended From 62cd5cd3243f7371d77d2ab976553d09315343b5 Mon Sep 17 00:00:00 2001 From: lmanini Date: Mon, 29 May 2023 17:17:33 +0200 Subject: [PATCH 2/5] added warning msg to 'forge upload-selectors' --- cli/src/cmd/forge/fourbyte.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/src/cmd/forge/fourbyte.rs b/cli/src/cmd/forge/fourbyte.rs index 37f48d4a0996..1941f317fe9f 100644 --- a/cli/src/cmd/forge/fourbyte.rs +++ b/cli/src/cmd/forge/fourbyte.rs @@ -28,6 +28,8 @@ pub struct UploadSelectorsArgs { impl UploadSelectorsArgs { /// Builds a contract and uploads the ABI to selector database pub async fn run(self) -> eyre::Result<()> { + println!("Warning! This command is deprecated and will be removed in v1, use `forge selectors upload` instead"); + let UploadSelectorsArgs { contract, all, project_paths } = self; let build_args = CoreBuildArgs { From ed0321f7a60c5b5542001849c69210d0773e73f0 Mon Sep 17 00:00:00 2001 From: lmanini Date: Mon, 29 May 2023 19:33:53 +0200 Subject: [PATCH 3/5] added yellow warning msg --- cli/src/cmd/forge/fourbyte.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cli/src/cmd/forge/fourbyte.rs b/cli/src/cmd/forge/fourbyte.rs index 1941f317fe9f..3b00dbd075d0 100644 --- a/cli/src/cmd/forge/fourbyte.rs +++ b/cli/src/cmd/forge/fourbyte.rs @@ -8,7 +8,9 @@ use ethers::prelude::artifacts::output_selection::ContractOutputSelection; use foundry_common::{ compile, selectors::{import_selectors, SelectorImportData}, + shell }; +use yansi::Paint; /// CLI arguments for `forge upload-selectors`. #[derive(Debug, Clone, Parser)] @@ -28,7 +30,7 @@ pub struct UploadSelectorsArgs { impl UploadSelectorsArgs { /// Builds a contract and uploads the ABI to selector database pub async fn run(self) -> eyre::Result<()> { - println!("Warning! This command is deprecated and will be removed in v1, use `forge selectors upload` instead"); + shell::println(Paint::yellow("Warning! This command is deprecated and will be removed in v1, use `forge selectors upload` instead"))?; let UploadSelectorsArgs { contract, all, project_paths } = self; From 5f41039eeeeedc908d39341712fc7694a31372f1 Mon Sep 17 00:00:00 2001 From: lmanini Date: Mon, 29 May 2023 19:49:04 +0200 Subject: [PATCH 4/5] added doc --- cli/src/cmd/forge/selectors.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/src/cmd/forge/selectors.rs b/cli/src/cmd/forge/selectors.rs index fa6143b259ed..db6293d80bea 100644 --- a/cli/src/cmd/forge/selectors.rs +++ b/cli/src/cmd/forge/selectors.rs @@ -10,6 +10,7 @@ use foundry_common::{ selectors::{import_selectors, SelectorImportData}, }; +/// CLI arguments for `forge selectors`. #[derive(Debug, Clone, Parser)] pub enum SelectorsSubcommands { /// Upload selectors to registry From 4e9e0596aa3790bcfff9e3fc8b50550149179e97 Mon Sep 17 00:00:00 2001 From: lmanini Date: Mon, 29 May 2023 19:50:06 +0200 Subject: [PATCH 5/5] ran nightly toolchain --- cli/src/cmd/forge/fourbyte.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/src/cmd/forge/fourbyte.rs b/cli/src/cmd/forge/fourbyte.rs index 3b00dbd075d0..d11128038c9d 100644 --- a/cli/src/cmd/forge/fourbyte.rs +++ b/cli/src/cmd/forge/fourbyte.rs @@ -8,7 +8,7 @@ use ethers::prelude::artifacts::output_selection::ContractOutputSelection; use foundry_common::{ compile, selectors::{import_selectors, SelectorImportData}, - shell + shell, }; use yansi::Paint;