Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow any config to be defined inline #9430

Merged
merged 8 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions crates/cheatcodes/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ impl CheatsConfig {
running_version: Option<Version>,
) -> Self {
let mut allowed_paths = vec![config.root.0.clone()];
allowed_paths.extend(config.libs.clone());
allowed_paths.extend(config.allow_paths.clone());
allowed_paths.extend(config.libs.iter().cloned());
allowed_paths.extend(config.allow_paths.iter().cloned());

let rpc_endpoints = config.rpc_endpoints.clone().resolved();
trace!(?rpc_endpoints, "using resolved rpc endpoints");
Expand Down Expand Up @@ -101,6 +101,17 @@ impl CheatsConfig {
}
}

/// Returns a new `CheatsConfig` configured with the given `Config` and `EvmOpts`.
pub fn clone_with(&self, config: &Config, evm_opts: EvmOpts) -> Self {
Self::new(
config,
evm_opts,
self.available_artifacts.clone(),
self.running_contract.clone(),
self.running_version.clone(),
)
}

/// Attempts to canonicalize (see [std::fs::canonicalize]) the path.
///
/// Canonicalization fails for non-existing paths, in which case we just normalize the path.
Expand Down
4 changes: 2 additions & 2 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ pub struct Cheatcodes {
/// Scripting based transactions
pub broadcastable_transactions: BroadcastableTransactions,

/// Additional, user configurable context this Inspector has access to when inspecting a call
/// Additional, user configurable context this Inspector has access to when inspecting a call.
pub config: Arc<CheatsConfig>,

/// Test-scoped context holding data that needs to be reset every test run
Expand Down Expand Up @@ -540,7 +540,7 @@ impl Cheatcodes {

/// Returns the configured wallets if available, else creates a new instance.
pub fn wallets(&mut self) -> &Wallets {
self.wallets.get_or_insert(Wallets::new(MultiWallet::default(), None))
self.wallets.get_or_insert_with(|| Wallets::new(MultiWallet::default(), None))
}

/// Sets the unlocked wallets.
Expand Down
2 changes: 1 addition & 1 deletion crates/chisel/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ impl SessionSource {
)
})
.gas_limit(self.config.evm_opts.gas_limit())
.spec(self.config.foundry_config.evm_spec_id())
.spec_id(self.config.foundry_config.evm_spec_id())
.legacy_assertions(self.config.foundry_config.legacy_assertions)
.build(env, backend);

Expand Down
32 changes: 25 additions & 7 deletions crates/config/src/inline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use figment::{
value::{Dict, Map, Value},
Figment, Profile, Provider,
};
use foundry_compilers::ProjectCompileOutput;
use itertools::Itertools;

mod natspec;
Expand Down Expand Up @@ -53,6 +54,20 @@ impl InlineConfig {
Self::default()
}

/// Tries to create a new instance by detecting inline configurations from the project compile
/// output.
pub fn new_parsed(output: &ProjectCompileOutput, config: &Config) -> eyre::Result<Self> {
let natspecs: Vec<NatSpec> = NatSpec::parse(output, &config.root);
let profiles = &config.profiles;
let mut inline = Self::new();
for natspec in &natspecs {
inline.insert(natspec)?;
// Validate after parsing as TOML.
natspec.validate_profiles(profiles)?;
}
Ok(inline)
}

/// Inserts a new [`NatSpec`] into the [`InlineConfig`].
pub fn insert(&mut self, natspec: &NatSpec) -> Result<(), InlineConfigError> {
let map = if let Some(function) = &natspec.function {
Expand Down Expand Up @@ -92,13 +107,16 @@ impl InlineConfig {
Figment::from(base).merge(self.provide(contract, function))
}

/// Returns `true` if a configuration is present at the given contract and function level.
pub fn contains(&self, contract: &str, function: &str) -> bool {
// Order swapped to avoid allocation in `get_function` since order doesn't matter here.
self.get_contract(contract)
.filter(|map| !map.is_empty())
.or_else(|| self.get_function(contract, function))
.is_some_and(|map| !map.is_empty())
/// Returns `true` if a configuration is present at the given contract level.
pub fn contains_contract(&self, contract: &str) -> bool {
self.get_contract(contract).is_some_and(|map| !map.is_empty())
}

/// Returns `true` if a configuration is present at the function level.
///
/// Does not include contract-level configurations.
pub fn contains_function(&self, contract: &str, function: &str) -> bool {
self.get_function(contract, function).is_some_and(|map| !map.is_empty())
}

fn get_contract(&self, contract: &str) -> Option<&DataMap> {
Expand Down
2 changes: 1 addition & 1 deletion crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1108,7 +1108,7 @@ impl Config {
/// Returns the [SpecId] derived from the configured [EvmVersion]
#[inline]
pub fn evm_spec_id(&self) -> SpecId {
evm_spec_id(&self.evm_version, self.alphanet)
evm_spec_id(self.evm_version, self.alphanet)
}

/// Returns whether the compiler version should be auto-detected
Expand Down
2 changes: 1 addition & 1 deletion crates/config/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ impl FromStr for Numeric {

/// Returns the [SpecId] derived from [EvmVersion]
#[inline]
pub fn evm_spec_id(evm_version: &EvmVersion, alphanet: bool) -> SpecId {
pub fn evm_spec_id(evm_version: EvmVersion, alphanet: bool) -> SpecId {
if alphanet {
return SpecId::OSAKA;
}
Expand Down
3 changes: 1 addition & 2 deletions crates/evm/core/src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,8 @@ impl EvmOpts {
/// And the block that was used to configure the environment.
pub async fn fork_evm_env(
&self,
fork_url: impl AsRef<str>,
fork_url: &str,
) -> eyre::Result<(revm::primitives::Env, AnyRpcBlock)> {
let fork_url = fork_url.as_ref();
let provider = ProviderBuilder::new(fork_url)
.compute_units_per_second(self.get_compute_units_per_second())
.build()?;
Expand Down
5 changes: 1 addition & 4 deletions crates/evm/core/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,7 @@ pub fn apply_chain_and_block_specific_env_changes<N: Network>(

return;
}
NamedChain::Arbitrum |
NamedChain::ArbitrumGoerli |
NamedChain::ArbitrumNova |
NamedChain::ArbitrumTestnet => {
c if c.is_arbitrum() => {
// on arbitrum `block.number` is the L1 block which is included in the
// `l1BlockNumber` field
if let Some(l1_block_number) = block
Expand Down
2 changes: 1 addition & 1 deletion crates/evm/evm/src/executors/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl ExecutorBuilder {

/// Sets the EVM spec to use.
#[inline]
pub fn spec(mut self, spec: SpecId) -> Self {
pub fn spec_id(mut self, spec: SpecId) -> Self {
self.spec_id = spec;
self
}
Expand Down
40 changes: 31 additions & 9 deletions crates/evm/evm/src/executors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ pub struct Executor {
env: EnvWithHandlerCfg,
/// The Revm inspector stack.
inspector: InspectorStack,
/// The gas limit for calls and deployments. This is different from the gas limit imposed by
/// the passed in environment, as those limits are used by the EVM for certain opcodes like
/// `gaslimit`.
/// The gas limit for calls and deployments.
gas_limit: u64,
/// Whether `failed()` should be called on the test contract to determine if the test failed.
legacy_assertions: bool,
Expand Down Expand Up @@ -162,6 +160,36 @@ impl Executor {
self.env.spec_id()
}

/// Sets the EVM spec ID.
pub fn set_spec_id(&mut self, spec_id: SpecId) {
self.env.handler_cfg.spec_id = spec_id;
}

/// Returns the gas limit for calls and deployments.
///
/// This is different from the gas limit imposed by the passed in environment, as those limits
/// are used by the EVM for certain opcodes like `gaslimit`.
pub fn gas_limit(&self) -> u64 {
self.gas_limit
}

/// Sets the gas limit for calls and deployments.
pub fn set_gas_limit(&mut self, gas_limit: u64) {
self.gas_limit = gas_limit;
}

/// Returns whether `failed()` should be called on the test contract to determine if the test
/// failed.
pub fn legacy_assertions(&self) -> bool {
self.legacy_assertions
}

/// Sets whether `failed()` should be called on the test contract to determine if the test
/// failed.
pub fn set_legacy_assertions(&mut self, legacy_assertions: bool) {
self.legacy_assertions = legacy_assertions;
}

/// Creates the default CREATE2 Contract Deployer for local tests and scripts.
pub fn deploy_create2_deployer(&mut self) -> eyre::Result<()> {
trace!("deploying local create2 deployer");
Expand Down Expand Up @@ -231,12 +259,6 @@ impl Executor {
self
}

#[inline]
pub fn set_gas_limit(&mut self, gas_limit: u64) -> &mut Self {
self.gas_limit = gas_limit;
self
}

/// Deploys a contract and commits the new state to the underlying database.
///
/// Executes a CREATE transaction with the contract `code` and persistent database state
Expand Down
2 changes: 1 addition & 1 deletion crates/evm/evm/src/executors/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl TracingExecutor {
// tracing will be enabled only for the targeted transaction
executor: ExecutorBuilder::new()
.inspectors(|stack| stack.trace_mode(trace_mode).alphanet(alphanet))
.spec(evm_spec_id(&version.unwrap_or_default(), alphanet))
.spec_id(evm_spec_id(version.unwrap_or_default(), alphanet))
.build(env, db),
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/evm/traces/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ impl TraceMode {
}
}

pub fn with_verbosity(self, verbosiy: u8) -> Self {
if verbosiy >= 3 {
pub fn with_verbosity(self, verbosity: u8) -> Self {
if verbosity >= 3 {
std::cmp::max(self, Self::Call)
} else {
self
Expand Down
3 changes: 1 addition & 2 deletions crates/forge/bin/cmd/coverage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use forge::{
},
opts::EvmOpts,
utils::IcPcMap,
MultiContractRunnerBuilder, TestOptions,
MultiContractRunnerBuilder,
};
use foundry_cli::utils::{LoadConfig, STATIC_FUZZ_SEED};
use foundry_common::{compile::ProjectCompiler, fs};
Expand Down Expand Up @@ -230,7 +230,6 @@ impl CoverageArgs {
.evm_spec(config.evm_spec_id())
.sender(evm_opts.sender)
.with_fork(evm_opts.get_fork(&config, env.clone()))
.with_test_options(TestOptions::new(output, config.clone())?)
.set_coverage(true)
.build(&root, output, env, evm_opts)?;

Expand Down
7 changes: 2 additions & 5 deletions crates/forge/bin/cmd/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use forge::{
identifier::SignaturesIdentifier,
CallTraceDecoderBuilder, InternalTraceMode, TraceKind,
},
MultiContractRunner, MultiContractRunnerBuilder, TestFilter, TestOptions,
MultiContractRunner, MultiContractRunnerBuilder, TestFilter,
};
use foundry_cli::{
opts::{CoreBuildArgs, GlobalOpts},
Expand Down Expand Up @@ -313,9 +313,6 @@ impl TestArgs {
}
}

let config = Arc::new(config);
let test_options = TestOptions::new(&output, config.clone())?;

let should_debug = self.debug.is_some();
let should_draw = self.flamegraph || self.flamechart;

Expand All @@ -342,14 +339,14 @@ impl TestArgs {
};

// Prepare the test builder.
let config = Arc::new(config);
let runner = MultiContractRunnerBuilder::new(config.clone())
.set_debug(should_debug)
.set_decode_internal(decode_internal)
.initial_balance(evm_opts.initial_balance)
.evm_spec(config.evm_spec_id())
.sender(evm_opts.sender)
.with_fork(evm_opts.get_fork(&config, env.clone()))
.with_test_options(test_options)
.enable_isolation(evm_opts.isolate)
.alphanet(evm_opts.alphanet)
.build(project_root, &output, env, evm_opts)?;
Expand Down
Loading