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

[WIP] upstream merge strategy using generics #763

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
33 changes: 33 additions & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ members = [
"crates/script-sequence/",
"crates/macros/",
"crates/test-utils/",
"crates/strategy/core/",
"crates/strategy/zksync/",
]
resolver = "2"

Expand Down Expand Up @@ -173,6 +175,8 @@ foundry-linking = { path = "crates/linking" }
foundry-zksync-core = { path = "crates/zksync/core" }
foundry-zksync-compiler = { path = "crates/zksync/compiler" }
foundry-zksync-inspectors = { path = "crates/zksync/inspectors" }
foundry-strategy-core = { path = "crates/strategy/core" }
foundry-strategy-zksync = { path = "crates/strategy/zksync" }

# solc & compilation utilities
# foundry-block-explorers = { version = "0.7.3", default-features = false }
Expand Down
19 changes: 15 additions & 4 deletions crates/cast/bin/cmd/call.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use crate::tx::{CastTxBuilder, SenderKind};
use alloy_primitives::{TxKind, U256};
use alloy_rpc_types::{BlockId, BlockNumberOrTag};
use cast::{traces::TraceKind, Cast};
use cast::{
backend::strategy::{BackendStrategy, EvmBackendStrategy},
traces::TraceKind,
Cast,
};
use clap::Parser;
use eyre::Result;
use foundry_cli::{
Expand Down Expand Up @@ -171,14 +175,21 @@ impl CallArgs {
}

let (mut env, fork, chain, alphanet) =
TracingExecutor::get_fork_material(&config, evm_opts).await?;
TracingExecutor::<EvmBackendStrategy>::get_fork_material(&config, evm_opts).await?;

// modify settings that usually set in eth_call
env.cfg.disable_block_gas_limit = true;
env.block.gas_limit = U256::MAX;

let mut executor =
TracingExecutor::new(env, fork, evm_version, debug, decode_internal, alphanet);
let mut executor = TracingExecutor::new(
env,
fork,
evm_version,
debug,
decode_internal,
alphanet,
EvmBackendStrategy::new(),
);

let value = tx.value.unwrap_or_default();
let input = tx.inner.input.into_input().unwrap_or_default();
Expand Down
8 changes: 6 additions & 2 deletions crates/cast/bin/cmd/run.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use alloy_primitives::U256;
use alloy_provider::Provider;
use alloy_rpc_types::BlockTransactions;
use cast::revm::primitives::EnvWithHandlerCfg;
use cast::{
backend::strategy::{BackendStrategy, EvmBackendStrategy},
revm::primitives::EnvWithHandlerCfg,
};
use clap::Parser;
use eyre::{Result, WrapErr};
use foundry_cli::{
Expand Down Expand Up @@ -133,7 +136,7 @@ impl RunArgs {
config.fork_block_number = Some(tx_block_number - 1);

let (mut env, fork, chain, alphanet) =
TracingExecutor::get_fork_material(&config, evm_opts).await?;
TracingExecutor::<EvmBackendStrategy>::get_fork_material(&config, evm_opts).await?;

let mut evm_version = self.evm_version;

Expand Down Expand Up @@ -164,6 +167,7 @@ impl RunArgs {
self.debug,
self.decode_internal,
alphanet,
EvmBackendStrategy::new(),
);
let mut env =
EnvWithHandlerCfg::new_with_spec_id(Box::new(env.clone()), executor.spec_id());
Expand Down
24 changes: 14 additions & 10 deletions crates/cheatcodes/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::{
///
/// This is essentially a subset of various `Config` settings `Cheatcodes` needs to know.
#[derive(Clone, Debug)]
pub struct CheatsConfig {
pub struct CheatsConfig<S> {
/// Whether the FFI cheatcode is enabled.
pub ffi: bool,
/// Use the create 2 factory in all cases including tests and non-broadcasting scripts.
Expand Down Expand Up @@ -56,15 +56,15 @@ pub struct CheatsConfig {
pub running_version: Option<Version>,
/// ZKSolc -> Solc Contract codes
pub dual_compiled_contracts: DualCompiledContracts,
/// Use ZK-VM on startup
pub use_zk: bool,
/// Whether to enable legacy (non-reverting) assertions.
pub assertions_revert: bool,
/// Optional seed for the RNG algorithm.
pub seed: Option<U256>,
/// Execution strategy.
pub strategy: S,
}

impl CheatsConfig {
impl<S> CheatsConfig<S> {
/// Extracts the necessary settings from the Config
pub fn new(
config: &Config,
Expand All @@ -73,7 +73,7 @@ impl CheatsConfig {
running_contract: Option<String>,
running_version: Option<Version>,
dual_compiled_contracts: DualCompiledContracts,
use_zk: bool,
strategy: S,
) -> Self {
let mut allowed_paths = vec![config.root.0.clone()];
allowed_paths.extend(config.libs.clone());
Expand Down Expand Up @@ -104,7 +104,7 @@ impl CheatsConfig {
running_contract,
running_version,
dual_compiled_contracts,
use_zk,
strategy,
assertions_revert: config.assertions_revert,
seed: config.fuzz.seed,
}
Expand Down Expand Up @@ -216,7 +216,10 @@ impl CheatsConfig {
}
}

impl Default for CheatsConfig {
impl<S> Default for CheatsConfig<S>
where
S: Default,
{
fn default() -> Self {
Self {
ffi: false,
Expand All @@ -236,7 +239,7 @@ impl Default for CheatsConfig {
running_contract: Default::default(),
running_version: Default::default(),
dual_compiled_contracts: Default::default(),
use_zk: false,
strategy: Default::default(),
assertions_revert: true,
seed: None,
}
Expand All @@ -247,16 +250,17 @@ impl Default for CheatsConfig {
mod tests {
use super::*;
use foundry_config::fs_permissions::PathPermission;
use foundry_evm_core::backend::strategy::EvmBackendStrategy;

fn config(root: &str, fs_permissions: FsPermissions) -> CheatsConfig {
fn config(root: &str, fs_permissions: FsPermissions) -> CheatsConfig<EvmBackendStrategy> {
CheatsConfig::new(
&Config { root: PathBuf::from(root).into(), fs_permissions, ..Default::default() },
Default::default(),
None,
None,
None,
Default::default(),
false,
EvmBackendStrategy,
)
}

Expand Down
18 changes: 9 additions & 9 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use foundry_cheatcodes_common::{
use foundry_common::{evm::Breakpoints, TransactionMaybeSigned, SELECTOR_LEN};
use foundry_evm_core::{
abi::{Vm::stopExpectSafeMemoryCall, HARDHAT_CONSOLE_ADDRESS},
backend::{DatabaseError, DatabaseExt, LocalForkId, RevertDiagnostic},
backend::{strategy::CheatcodeInspectorStrategy, DatabaseError, DatabaseExt, LocalForkId, RevertDiagnostic},
constants::{
CHEATCODE_ADDRESS, CHEATCODE_CONTRACT_HASH, DEFAULT_CREATE2_DEPLOYER,
DEFAULT_CREATE2_DEPLOYER_CODE, MAGIC_ASSUME,
Expand Down Expand Up @@ -96,7 +96,7 @@ pub type InnerEcx<'a, 'b, 'c> = &'a mut InnerEvmContext<&'b mut (dyn DatabaseExt
pub trait CheatcodesExecutor {
/// Core trait method accepting mutable reference to [Cheatcodes] and returning
/// [revm::Inspector].
fn get_inspector<'a>(&'a mut self, cheats: &'a mut Cheatcodes) -> Box<dyn InspectorExt + 'a>;
fn get_inspector<'a, S>(&'a mut self, cheats: &'a mut Cheatcodes<S>) -> Box<dyn InspectorExt + 'a>;

/// Obtains [revm::Evm] instance and executes the given CREATE frame.
fn exec_create(
Expand Down Expand Up @@ -152,7 +152,7 @@ pub trait CheatcodesExecutor {
None
}

fn trace_zksync(&mut self, ccx_state: &mut Cheatcodes, ecx: Ecx, call_traces: Vec<Call>) {
fn trace_zksync<S>(&mut self, ccx_state: &mut Cheatcodes<S>, ecx: Ecx, call_traces: Vec<Call>) {
let mut inspector = self.get_inspector(ccx_state);

// We recreate the EvmContext here to satisfy the lifetime parameters as 'static, with
Expand Down Expand Up @@ -234,7 +234,7 @@ where
struct TransparentCheatcodesExecutor;

impl CheatcodesExecutor for TransparentCheatcodesExecutor {
fn get_inspector<'a>(&'a mut self, cheats: &'a mut Cheatcodes) -> Box<dyn InspectorExt + 'a> {
fn get_inspector<'a, S>(&'a mut self, cheats: &'a mut Cheatcodes<S>) -> Box<dyn InspectorExt + 'a> {
Box::new(cheats)
}
}
Expand Down Expand Up @@ -495,7 +495,7 @@ impl ZkStartupMigration {
/// cheatcode address: by default, the caller, test contract and newly deployed contracts are
/// allowed to execute cheatcodes
#[derive(Clone, Debug)]
pub struct Cheatcodes {
pub struct Cheatcodes<S> {
/// The block environment
///
/// Used in the cheatcode handler to overwrite the block environment separately from the
Expand Down Expand Up @@ -561,7 +561,7 @@ pub struct Cheatcodes {
pub broadcastable_transactions: BroadcastableTransactions,

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

/// Test-scoped context holding data that needs to be reset every test run
pub context: Context,
Expand Down Expand Up @@ -649,15 +649,15 @@ pub struct Cheatcodes {
// This is not derived because calling this in `fn new` with `..Default::default()` creates a second
// `CheatsConfig` which is unused, and inside it `ProjectPathsConfig` is relatively expensive to
// create.
impl Default for Cheatcodes {
impl<S> Default for Cheatcodes<S> where S: CheatcodeInspectorStrategy {
fn default() -> Self {
Self::new(Arc::default())
}
}

impl Cheatcodes {
impl<S> Cheatcodes<S> where S: CheatcodeInspectorStrategy {
/// Creates a new `Cheatcodes` with the given settings.
pub fn new(config: Arc<CheatsConfig>) -> Self {
pub fn new(config: Arc<CheatsConfig<S>>) -> Self {
let mut dual_compiled_contracts = config.dual_compiled_contracts.clone();

// We add the empty bytecode manually so it is correctly translated in zk mode.
Expand Down
34 changes: 21 additions & 13 deletions crates/chisel/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use foundry_config::{
},
Config,
};
use foundry_evm::backend::strategy::{BackendStrategy, EvmBackendStrategy};
use rustyline::{config::Configurer, error::ReadlineError, Editor};
use std::path::PathBuf;
use tracing::debug;
Expand Down Expand Up @@ -132,15 +133,16 @@ async fn main_args(args: Chisel) -> eyre::Result<()> {
let (config, evm_opts) = args.load_config_and_evm_opts()?;

// Create a new cli dispatcher
let mut dispatcher = ChiselDispatcher::new(chisel::session_source::SessionSourceConfig {
// Enable traces if any level of verbosity was passed
traces: config.verbosity > 0,
foundry_config: config,
no_vm: args.no_vm,
evm_opts,
backend: None,
calldata: None,
})?;
let mut dispatcher =
ChiselDispatcher::<EvmBackendStrategy>::new(chisel::session_source::SessionSourceConfig {
// Enable traces if any level of verbosity was passed
traces: config.verbosity > 0,
foundry_config: config,
no_vm: args.no_vm,
evm_opts,
backend: None,
calldata: None,
})?;

// Execute prelude Solidity source files
evaluate_prelude(&mut dispatcher, args.prelude).await?;
Expand Down Expand Up @@ -265,7 +267,10 @@ impl Provider for Chisel {
}

/// Evaluate a single Solidity line.
async fn dispatch_repl_line(dispatcher: &mut ChiselDispatcher, line: &str) -> eyre::Result<bool> {
async fn dispatch_repl_line<B: BackendStrategy>(
dispatcher: &mut ChiselDispatcher<B>,
line: &str,
) -> eyre::Result<bool> {
let r = dispatcher.dispatch(line).await;
match &r {
DispatchResult::Success(msg) | DispatchResult::CommandSuccess(msg) => {
Expand All @@ -288,8 +293,8 @@ async fn dispatch_repl_line(dispatcher: &mut ChiselDispatcher, line: &str) -> ey

/// Evaluate multiple Solidity source files contained within a
/// Chisel prelude directory.
async fn evaluate_prelude(
dispatcher: &mut ChiselDispatcher,
async fn evaluate_prelude<B: BackendStrategy>(
dispatcher: &mut ChiselDispatcher<B>,
maybe_prelude: Option<PathBuf>,
) -> eyre::Result<()> {
let Some(prelude_dir) = maybe_prelude else { return Ok(()) };
Expand All @@ -314,7 +319,10 @@ async fn evaluate_prelude(
}

/// Loads a single Solidity file into the prelude.
async fn load_prelude_file(dispatcher: &mut ChiselDispatcher, file: PathBuf) -> eyre::Result<()> {
async fn load_prelude_file<B: BackendStrategy>(
dispatcher: &mut ChiselDispatcher<B>,
file: PathBuf,
) -> eyre::Result<()> {
let prelude = fs::read_to_string(file)
.wrap_err("Could not load source file. Are you sure this path is correct?")?;
dispatch_repl_line(dispatcher, &prelude).await?;
Expand Down
3 changes: 2 additions & 1 deletion crates/chisel/src/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! can be executed within the REPL.

use crate::prelude::ChiselDispatcher;
use foundry_evm::backend::strategy::EvmBackendStrategy;
use std::{error::Error, str::FromStr};
use strum::EnumIter;

Expand Down Expand Up @@ -79,7 +80,7 @@ impl FromStr for ChiselCommand {
"exec" | "e" => Ok(Self::Exec),
"rawstack" | "rs" => Ok(Self::RawStack),
"edit" => Ok(Self::Edit),
_ => Err(ChiselDispatcher::make_error(format!(
_ => Err(ChiselDispatcher::<EvmBackendStrategy>::make_error(format!(
"Unknown command \"{s}\"! See available commands with `!help`.",
))
.into()),
Expand Down
Loading
Loading