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(script): support custom create2 deployer #9278

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
bfc0dc3
script: add --create2-deployer
jsvisa Oct 31, 2024
0b98a13
script: add create2 deployer
jsvisa Oct 31, 2024
c29badc
evm/constants: add get_create2_deployer from env or default
jsvisa Nov 7, 2024
b940dbb
evm/core: use env's create2
jsvisa Nov 7, 2024
d40332e
script: fetch create2_deployer from env or default
jsvisa Nov 7, 2024
d8bf750
fmt
jsvisa Nov 7, 2024
42aa878
docs
jsvisa Nov 7, 2024
1747000
evm/constants: use sync::LazyLock
jsvisa Nov 8, 2024
5e71a94
evm/inspector: add fn create2_deployer
jsvisa Nov 8, 2024
a358748
config: add create2_deployer
jsvisa Nov 8, 2024
43ff018
evm/inpector: set create2 deployer
jsvisa Nov 8, 2024
60d6986
evm-opts: add create2_deployer
jsvisa Nov 8, 2024
864deb2
script: pass deployer2-creater from cli or config
jsvisa Nov 8, 2024
86978b9
script: use create2 address to fill tx meta
jsvisa Nov 9, 2024
0fb8f17
config: create2 address ,no Option
jsvisa Nov 9, 2024
fa6f9ba
script/runner: set inspector.create2_deployer with evm_opts
jsvisa Nov 9, 2024
ea5dc19
clippy
jsvisa Nov 10, 2024
70c03c5
doc typo
jsvisa Nov 10, 2024
6c2ae28
fix/evm-opts: default value of create2_deployer
jsvisa Nov 10, 2024
fa4ab37
evm/core: no need to extract create2 deployer from env
jsvisa Nov 10, 2024
3761598
evm/core: implement Default for EvmOpts.create2_deployer
jsvisa Nov 10, 2024
21bf5a3
evm/core: use constants::DEFAULT create2 deployer
jsvisa Nov 10, 2024
3a41b4f
evm/core: output create2 deployer
jsvisa Nov 20, 2024
857ca97
evm/evm: set create2 deployer for trace and stack
jsvisa Nov 20, 2024
5a8c849
cast/{run,call}: set create2 deployer
jsvisa Nov 20, 2024
4484c9c
forge/runner: set create2 deployer
jsvisa Nov 20, 2024
b190fcb
script: set create2 deployer for stack
jsvisa Nov 20, 2024
d73f65e
verify: set create2 deployer
jsvisa Nov 20, 2024
2f1abdf
clipy
jsvisa Nov 20, 2024
28e7d8d
fmt
jsvisa Nov 20, 2024
ec358ef
script: use executor's create2 deployer
jsvisa Nov 21, 2024
639ff34
script: wrap create2_deployer inside executor
jsvisa Nov 21, 2024
a958c24
script: add custom create2 test
jsvisa Nov 21, 2024
4f27792
script: add nonexist create2
jsvisa Nov 21, 2024
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
12 changes: 10 additions & 2 deletions crates/cast/bin/cmd/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,23 @@ impl CallArgs {
config.fork_block_number = Some(block_number);
}

let create2_deployer = evm_opts.create2_deployer;
let (mut env, fork, chain, alphanet) =
TracingExecutor::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,
create2_deployer,
);

let value = tx.value.unwrap_or_default();
let input = tx.inner.input.into_input().unwrap_or_default();
Expand Down
2 changes: 2 additions & 0 deletions crates/cast/bin/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ impl RunArgs {
// we need to fork off the parent block
config.fork_block_number = Some(tx_block_number - 1);

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

Expand Down Expand Up @@ -166,6 +167,7 @@ impl RunArgs {
self.debug,
self.decode_internal,
alphanet,
create2_deployer,
);
let mut env =
EnvWithHandlerCfg::new_with_spec_id(Box::new(env.clone()), executor.spec_id());
Expand Down
4 changes: 4 additions & 0 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1587,6 +1587,10 @@ impl InspectorExt for Cheatcodes {
false
}
}

fn create2_deployer(&self) -> Address {
self.config.evm_opts.create2_deployer
}
}

impl Cheatcodes {
Expand Down
8 changes: 8 additions & 0 deletions crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,9 @@ pub struct Config {
/// CREATE2 salt to use for the library deployment in scripts.
pub create2_library_salt: B256,

/// The CREATE2 deployer address to use.
pub create2_deployer: Address,

/// Configuration for Vyper compiler
pub vyper: VyperConfig,

Expand Down Expand Up @@ -553,6 +556,10 @@ impl Config {
/// Default salt for create2 library deployments
pub const DEFAULT_CREATE2_LIBRARY_SALT: FixedBytes<32> = FixedBytes::<32>::ZERO;

/// Default create2 deployer
pub const DEFAULT_CREATE2_DEPLOYER: Address =
address!("4e59b44847b379578588920ca78fbf26c0b4956c");

/// Docker image with eof-enabled solc binary
pub const EOF_SOLC_IMAGE: &'static str = "ghcr.io/paradigmxyz/forge-eof@sha256:46f868ce5264e1190881a3a335d41d7f42d6f26ed20b0c823609c715e38d603f";

Expand Down Expand Up @@ -2301,6 +2308,7 @@ impl Default for Config {
labels: Default::default(),
unchecked_cheatcode_artifacts: false,
create2_library_salt: Self::DEFAULT_CREATE2_LIBRARY_SALT,
create2_deployer: Self::DEFAULT_CREATE2_DEPLOYER,
skip: vec![],
dependencies: Default::default(),
soldeer: Default::default(),
Expand Down
7 changes: 7 additions & 0 deletions crates/evm/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

use crate::constants::DEFAULT_CREATE2_DEPLOYER;
use alloy_primitives::Address;
use auto_impl::auto_impl;
use backend::DatabaseExt;
use revm::{inspectors::NoOpInspector, interpreter::CreateInputs, EvmContext, Inspector};
Expand Down Expand Up @@ -54,6 +56,11 @@ pub trait InspectorExt: for<'a> Inspector<&'a mut dyn DatabaseExt> {
fn is_alphanet(&self) -> bool {
false
}

/// Returns the CREATE2 deployer address.
fn create2_deployer(&self) -> Address {
DEFAULT_CREATE2_DEPLOYER
}
}

impl InspectorExt for NoOpInspector {}
Expand Down
32 changes: 30 additions & 2 deletions crates/evm/core/src/opts.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::fork::environment;
use crate::fork::CreateFork;
use crate::{constants::DEFAULT_CREATE2_DEPLOYER, fork::CreateFork};
use alloy_primitives::{Address, B256, U256};
use alloy_provider::{network::AnyRpcBlock, Provider};
use eyre::WrapErr;
Expand All @@ -9,7 +9,7 @@ use revm::primitives::{BlockEnv, CfgEnv, TxEnv};
use serde::{Deserialize, Deserializer, Serialize};
use url::Url;

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EvmOpts {
/// The EVM environment configuration.
#[serde(flatten)]
Expand Down Expand Up @@ -66,6 +66,34 @@ pub struct EvmOpts {

/// whether to enable Alphanet features.
pub alphanet: bool,

/// The CREATE2 deployer's address.
pub create2_deployer: Address,
}

impl Default for EvmOpts {
fn default() -> Self {
Self {
env: Env::default(),
fork_url: None,
fork_block_number: None,
fork_retries: None,
fork_retry_backoff: None,
compute_units_per_second: None,
no_rpc_rate_limit: false,
no_storage_caching: false,
initial_balance: U256::default(),
sender: Address::default(),
ffi: false,
always_use_create_2_factory: false,
verbosity: 0,
memory_limit: 0,
isolate: false,
disable_block_gas_limit: false,
alphanet: false,
create2_deployer: DEFAULT_CREATE2_DEPLOYER,
}
}
}

impl EvmOpts {
Expand Down
25 changes: 14 additions & 11 deletions crates/evm/core/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
pub use crate::ic::*;
use crate::{
backend::DatabaseExt, constants::DEFAULT_CREATE2_DEPLOYER, precompiles::ALPHANET_P256,
InspectorExt,
};
use crate::{backend::DatabaseExt, precompiles::ALPHANET_P256, InspectorExt};
use alloy_consensus::BlockHeader;
use alloy_json_abi::{Function, JsonAbi};
use alloy_network::AnyTxEnvelope;
Expand Down Expand Up @@ -149,12 +146,16 @@ pub fn gas_used(spec: SpecId, spent: u64, refunded: u64) -> u64 {
spent - (refunded).min(spent / refund_quotient)
}

fn get_create2_factory_call_inputs(salt: U256, inputs: CreateInputs) -> CallInputs {
fn get_create2_factory_call_inputs(
salt: U256,
inputs: CreateInputs,
deployer: Address,
) -> CallInputs {
let calldata = [&salt.to_be_bytes::<32>()[..], &inputs.init_code[..]].concat();
CallInputs {
caller: inputs.caller,
bytecode_address: DEFAULT_CREATE2_DEPLOYER,
target_address: DEFAULT_CREATE2_DEPLOYER,
bytecode_address: deployer,
target_address: deployer,
scheme: CallScheme::Call,
value: CallValue::Transfer(inputs.value),
input: calldata.into(),
Expand All @@ -165,7 +166,7 @@ fn get_create2_factory_call_inputs(salt: U256, inputs: CreateInputs) -> CallInpu
}
}

/// Used for routing certain CREATE2 invocations through [DEFAULT_CREATE2_DEPLOYER].
/// Used for routing certain CREATE2 invocations through CREATE2_DEPLOYER.
///
/// Overrides create hook with CALL frame if [InspectorExt::should_use_create2_factory] returns
/// true. Keeps track of overridden frames and handles outcome in the overridden insert_call_outcome
Expand All @@ -190,8 +191,10 @@ pub fn create2_handler_register<I: InspectorExt>(

let gas_limit = inputs.gas_limit;

// Get CREATE2 deployer.
let create2_deployer = ctx.external.create2_deployer();
// Generate call inputs for CREATE2 factory.
let mut call_inputs = get_create2_factory_call_inputs(salt, *inputs);
let mut call_inputs = get_create2_factory_call_inputs(salt, *inputs, create2_deployer);

// Call inspector to change input or return outcome.
let outcome = ctx.external.call(&mut ctx.evm, &mut call_inputs);
Expand All @@ -202,12 +205,12 @@ pub fn create2_handler_register<I: InspectorExt>(
.push((ctx.evm.journaled_state.depth(), call_inputs.clone()));

// Sanity check that CREATE2 deployer exists.
let code_hash = ctx.evm.load_account(DEFAULT_CREATE2_DEPLOYER)?.info.code_hash;
let code_hash = ctx.evm.load_account(create2_deployer)?.info.code_hash;
if code_hash == KECCAK_EMPTY {
return Ok(FrameOrResult::Result(FrameResult::Call(CallOutcome {
result: InterpreterResult {
result: InstructionResult::Revert,
output: "missing CREATE2 deployer".into(),
output: format!("missing CREATE2 deployer: {create2_deployer}").into(),
gas: Gas::new(gas_limit),
},
memory_offset: 0..0,
Expand Down
12 changes: 12 additions & 0 deletions crates/evm/evm/src/executors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use foundry_evm_core::{
},
decode::{RevertDecoder, SkipReason},
utils::StateChangeset,
InspectorExt,
};
use foundry_evm_coverage::HitMaps;
use foundry_evm_traces::{SparsedTraceArena, TraceMode};
Expand Down Expand Up @@ -237,6 +238,17 @@ impl Executor {
self
}

#[inline]
pub fn set_create2_deployer(&mut self, create2_deployer: Address) -> &mut Self {
self.inspector_mut().set_create2_deployer(create2_deployer);
self
}

#[inline]
pub fn create2_deployer(&self) -> Address {
self.inspector().create2_deployer()
}

/// 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
9 changes: 8 additions & 1 deletion crates/evm/evm/src/executors/trace.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::executors::{Executor, ExecutorBuilder};
use alloy_primitives::Address;
use foundry_compilers::artifacts::EvmVersion;
use foundry_config::{utils::evm_spec_id, Chain, Config};
use foundry_evm_core::{backend::Backend, fork::CreateFork, opts::EvmOpts};
Expand All @@ -19,6 +20,7 @@ impl TracingExecutor {
debug: bool,
decode_internal: bool,
alphanet: bool,
create2_deployer: Address,
) -> Self {
let db = Backend::spawn(fork);
let trace_mode =
Expand All @@ -31,7 +33,12 @@ impl TracingExecutor {
// configures a bare version of the evm executor: no cheatcode inspector is enabled,
// tracing will be enabled only for the targeted transaction
executor: ExecutorBuilder::new()
.inspectors(|stack| stack.trace_mode(trace_mode).alphanet(alphanet))
.inspectors(|stack| {
stack
.trace_mode(trace_mode)
.alphanet(alphanet)
.create2_deployer(create2_deployer)
})
.spec(evm_spec_id(&version.unwrap_or_default(), alphanet))
.build(env, db),
}
Expand Down
25 changes: 25 additions & 0 deletions crates/evm/evm/src/inspectors/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub struct InspectorStackBuilder {
pub alphanet: bool,
/// The wallets to set in the cheatcodes context.
pub wallets: Option<Wallets>,
/// The CREATE2 deployer address.
pub create2_deployer: Address,
}

impl InspectorStackBuilder {
Expand Down Expand Up @@ -156,6 +158,12 @@ impl InspectorStackBuilder {
self
}

#[inline]
pub fn create2_deployer(mut self, create2_deployer: Address) -> Self {
self.create2_deployer = create2_deployer;
self
}

/// Builds the stack of inspectors to use when transacting/committing on the EVM.
pub fn build(self) -> InspectorStack {
let Self {
Expand All @@ -171,6 +179,7 @@ impl InspectorStackBuilder {
enable_isolation,
alphanet,
wallets,
create2_deployer,
} = self;
let mut stack = InspectorStack::new();

Expand All @@ -197,6 +206,7 @@ impl InspectorStackBuilder {

stack.enable_isolation(enable_isolation);
stack.alphanet(alphanet);
stack.set_create2_deployer(create2_deployer);

// environment, must come after all of the inspectors
if let Some(block) = block {
Expand Down Expand Up @@ -282,6 +292,7 @@ pub struct InspectorStackInner {
pub tracer: Option<TracingInspector>,
pub enable_isolation: bool,
pub alphanet: bool,
pub create2_deployer: Address,

/// Flag marking if we are in the inner EVM context.
pub in_inner_context: bool,
Expand Down Expand Up @@ -398,6 +409,12 @@ impl InspectorStack {
self.alphanet = yes;
}

/// Set the CREATE2 deployer address.
#[inline]
pub fn set_create2_deployer(&mut self, deployer: Address) {
self.create2_deployer = deployer;
}

/// Set whether to enable the log collector.
#[inline]
pub fn collect_logs(&mut self, yes: bool) {
Expand Down Expand Up @@ -1022,6 +1039,10 @@ impl InspectorExt for InspectorStackRefMut<'_> {
fn is_alphanet(&self) -> bool {
self.inner.alphanet
}

fn create2_deployer(&self) -> Address {
self.inner.create2_deployer
}
}

impl Inspector<&mut dyn DatabaseExt> for InspectorStack {
Expand Down Expand Up @@ -1124,6 +1145,10 @@ impl InspectorExt for InspectorStack {
fn is_alphanet(&self) -> bool {
self.alphanet
}

fn create2_deployer(&self) -> Address {
self.create2_deployer
}
}

impl<'a> Deref for InspectorStackRefMut<'a> {
Expand Down
1 change: 1 addition & 0 deletions crates/forge/src/multi_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ impl MultiContractRunner {
.coverage(self.coverage)
.enable_isolation(self.isolation)
.alphanet(self.alphanet)
.create2_deployer(self.evm_opts.create2_deployer)
})
.spec(self.evm_spec)
.gas_limit(self.evm_opts.gas_limit())
Expand Down
1 change: 1 addition & 0 deletions crates/forge/tests/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ forgetest!(can_extract_config_values, |prj, cmd| {
isolate: true,
unchecked_cheatcode_artifacts: false,
create2_library_salt: Config::DEFAULT_CREATE2_LIBRARY_SALT,
create2_deployer: Config::DEFAULT_CREATE2_DEPLOYER,
vyper: Default::default(),
skip: vec![],
dependencies: Default::default(),
Expand Down
Loading
Loading