From a70c36759e0035291a0cbadc85c0c1ef49e8400e Mon Sep 17 00:00:00 2001 From: mablr <59505383+mablr@users.noreply.github.com> Date: Wed, 28 May 2025 13:53:59 +0200 Subject: [PATCH 1/3] feat(forge build): cache project selectors by default Calls `cache_local_signatures` function like the "forge selectors cache" command. --- crates/forge/src/cmd/build.rs | 8 ++++++- crates/forge/tests/cli/test_cmd.rs | 38 ++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/crates/forge/src/cmd/build.rs b/crates/forge/src/cmd/build.rs index e64569206775b..6e098c15519fb 100644 --- a/crates/forge/src/cmd/build.rs +++ b/crates/forge/src/cmd/build.rs @@ -1,7 +1,10 @@ use super::{install, watch::WatchArgs}; use clap::Parser; use eyre::Result; -use foundry_cli::{opts::BuildOpts, utils::LoadConfig}; +use foundry_cli::{ + opts::BuildOpts, + utils::{cache_local_signatures, LoadConfig}, +}; use foundry_common::{compile::ProjectCompiler, shell}; use foundry_compilers::{ compilers::{multi::MultiCompilerLanguage, Language}, @@ -100,6 +103,9 @@ impl BuildArgs { let output = compiler.compile(&project)?; + // Cache project selectors. + cache_local_signatures(&output, &Config::foundry_cache_dir().unwrap())?; + if format_json && !self.names && !self.sizes { sh_println!("{}", serde_json::to_string_pretty(&output.output())?)?; } diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index af4b2aed7d0e7..0d33025249075 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -3828,3 +3828,41 @@ Encountered a total of 1 failing tests, 0 tests succeeded "#]]); }); + +// This test is a copy of `error_event_decode_with_cache` in cast/tests/cli/selectors.rs +// but it uses `forge build` to check that the project selectors are cached by default. +forgetest_init!(build_with_selectors_cache, |prj, cmd| { + prj.add_source( + "LocalProjectContract", + r#" +contract ContractWithCustomError { + error AnotherValueTooHigh(uint256, address); + event MyUniqueEventWithinLocalProject(uint256 a, address b); +} + "#, + ) + .unwrap(); + // Build and cache project selectors. + cmd.forge_fuse().args(["build"]).assert_success(); + + // Assert cast can decode custom error with local cache. + cmd.cast_fuse() + .args(["decode-error", "0x7191bc6200000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000D0004F"]) + .assert_success() + .stdout_eq(str![[r#" +AnotherValueTooHigh(uint256,address) +101 +0x0000000000000000000000000000000000D0004F + +"#]]); + // Assert cast can decode event with local cache. + cmd.cast_fuse() + .args(["decode-event", "0xbd3699995dcc867b64dbb607be2c33be38df9134bef1178df13bfb9446e73104000000000000000000000000000000000000000000000000000000000000004e00000000000000000000000000000000000000000000000000000dd00000004e"]) + .assert_success() + .stdout_eq(str![[r#" +MyUniqueEventWithinLocalProject(uint256,address) +78 +0x00000000000000000000000000000DD00000004e + +"#]]); +}); From fd92f8c6e173dcbc460d20f489394e4d3d2db36a Mon Sep 17 00:00:00 2001 From: mablr <59505383+mablr@users.noreply.github.com> Date: Wed, 28 May 2025 22:23:40 +0200 Subject: [PATCH 2/3] refactor(forge build): update `cache_local_signatures` to accept an optional `cache_dir` No more need to unwrap the option value returned foundry's `config` crate --- crates/cli/src/utils/cmd.rs | 9 ++++++++- crates/forge/src/cmd/build.rs | 2 +- crates/forge/src/cmd/selectors.rs | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 5f6d5b1074a92..275eea6b144ca 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -440,7 +440,14 @@ pub async fn print_traces( /// Traverse the artifacts in the project to generate local signatures and merge them into the cache /// file. -pub fn cache_local_signatures(output: &ProjectCompileOutput, cache_dir: &Path) -> Result<()> { +pub fn cache_local_signatures( + output: &ProjectCompileOutput, + cache_dir: Option, +) -> Result<()> { + let Some(cache_dir) = cache_dir else { + eyre::bail!("Failed to get `cache_dir` to generate local signatures."); + }; + let path = cache_dir.join("signatures"); let mut signatures = SignaturesCache::load(&path); for (_, artifact) in output.artifacts() { diff --git a/crates/forge/src/cmd/build.rs b/crates/forge/src/cmd/build.rs index 6e098c15519fb..aa62ec8af2f79 100644 --- a/crates/forge/src/cmd/build.rs +++ b/crates/forge/src/cmd/build.rs @@ -104,7 +104,7 @@ impl BuildArgs { let output = compiler.compile(&project)?; // Cache project selectors. - cache_local_signatures(&output, &Config::foundry_cache_dir().unwrap())?; + cache_local_signatures(&output, Config::foundry_cache_dir())?; if format_json && !self.names && !self.sizes { sh_println!("{}", serde_json::to_string_pretty(&output.output())?)?; diff --git a/crates/forge/src/cmd/selectors.rs b/crates/forge/src/cmd/selectors.rs index 5e858c9da9c58..e622ee2de7dd8 100644 --- a/crates/forge/src/cmd/selectors.rs +++ b/crates/forge/src/cmd/selectors.rs @@ -95,7 +95,7 @@ impl SelectorsSubcommands { // compile the project to get the artifacts/abis let project = build_args.project()?; let outcome = ProjectCompiler::new().quiet(true).compile(&project)?; - cache_local_signatures(&outcome, &Config::foundry_cache_dir().unwrap())? + cache_local_signatures(&outcome, Config::foundry_cache_dir())?; } Self::Upload { contract, all, project_paths } => { let build_args = BuildOpts { From e24eefd456a264c8d6f5498adfb170bcfea7f572 Mon Sep 17 00:00:00 2001 From: grandizzy Date: Fri, 30 May 2025 15:52:18 +0300 Subject: [PATCH 3/3] Move cache dir in cache sigs fn --- crates/cli/src/utils/cmd.rs | 8 ++------ crates/forge/src/cmd/build.rs | 2 +- crates/forge/src/cmd/selectors.rs | 3 +-- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 275eea6b144ca..1396d964db8aa 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -440,14 +440,10 @@ pub async fn print_traces( /// Traverse the artifacts in the project to generate local signatures and merge them into the cache /// file. -pub fn cache_local_signatures( - output: &ProjectCompileOutput, - cache_dir: Option, -) -> Result<()> { - let Some(cache_dir) = cache_dir else { +pub fn cache_local_signatures(output: &ProjectCompileOutput) -> Result<()> { + let Some(cache_dir) = Config::foundry_cache_dir() else { eyre::bail!("Failed to get `cache_dir` to generate local signatures."); }; - let path = cache_dir.join("signatures"); let mut signatures = SignaturesCache::load(&path); for (_, artifact) in output.artifacts() { diff --git a/crates/forge/src/cmd/build.rs b/crates/forge/src/cmd/build.rs index aa62ec8af2f79..43b4c89104407 100644 --- a/crates/forge/src/cmd/build.rs +++ b/crates/forge/src/cmd/build.rs @@ -104,7 +104,7 @@ impl BuildArgs { let output = compiler.compile(&project)?; // Cache project selectors. - cache_local_signatures(&output, Config::foundry_cache_dir())?; + cache_local_signatures(&output)?; if format_json && !self.names && !self.sizes { sh_println!("{}", serde_json::to_string_pretty(&output.output())?)?; diff --git a/crates/forge/src/cmd/selectors.rs b/crates/forge/src/cmd/selectors.rs index e622ee2de7dd8..e6ecdcbac7962 100644 --- a/crates/forge/src/cmd/selectors.rs +++ b/crates/forge/src/cmd/selectors.rs @@ -11,7 +11,6 @@ use foundry_common::{ selectors::{import_selectors, SelectorImportData}, }; use foundry_compilers::{artifacts::output_selection::ContractOutputSelection, info::ContractInfo}; -use foundry_config::Config; use std::fs::canonicalize; /// CLI arguments for `forge selectors`. @@ -95,7 +94,7 @@ impl SelectorsSubcommands { // compile the project to get the artifacts/abis let project = build_args.project()?; let outcome = ProjectCompiler::new().quiet(true).compile(&project)?; - cache_local_signatures(&outcome, Config::foundry_cache_dir())?; + cache_local_signatures(&outcome)?; } Self::Upload { contract, all, project_paths } => { let build_args = BuildOpts {