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: add the ability to use specific gas params in era vm environment and use them on script estimations #773

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
892 changes: 464 additions & 428 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions crates/cheatcodes/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use foundry_config::{
};
use foundry_evm_core::opts::EvmOpts;
use foundry_zksync_compiler::DualCompiledContracts;
use foundry_zksync_core::vm::ZkEnv;
use semver::Version;
use std::{
path::{Path, PathBuf},
Expand Down Expand Up @@ -62,10 +63,13 @@ pub struct CheatsConfig {
pub assertions_revert: bool,
/// Optional seed for the RNG algorithm.
pub seed: Option<U256>,
/// Era Vm environment
pub zk_env: Option<ZkEnv>,
}

impl CheatsConfig {
/// Extracts the necessary settings from the Config
#[allow(clippy::too_many_arguments)]
pub fn new(
config: &Config,
evm_opts: EvmOpts,
Expand All @@ -74,6 +78,7 @@ impl CheatsConfig {
running_version: Option<Version>,
dual_compiled_contracts: DualCompiledContracts,
use_zk: bool,
zk_env: Option<ZkEnv>,
) -> Self {
let mut allowed_paths = vec![config.root.0.clone()];
allowed_paths.extend(config.libs.clone());
Expand Down Expand Up @@ -107,6 +112,7 @@ impl CheatsConfig {
use_zk,
assertions_revert: config.assertions_revert,
seed: config.fuzz.seed,
zk_env,
}
}

Expand Down Expand Up @@ -239,6 +245,7 @@ impl Default for CheatsConfig {
use_zk: false,
assertions_revert: true,
seed: None,
zk_env: Default::default(),
}
}
}
Expand All @@ -257,6 +264,7 @@ mod tests {
None,
Default::default(),
false,
None,
)
}

Expand Down
11 changes: 9 additions & 2 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ use foundry_wallets::multi_wallet::MultiWallet;
use foundry_zksync_compiler::{DualCompiledContract, DualCompiledContracts};
use foundry_zksync_core::{
convert::{ConvertAddress, ConvertH160, ConvertH256, ConvertRU256, ConvertU256},
get_account_code_key, get_balance_key, get_nonce_key, Call, ZkPaymasterData,
ZkTransactionMetadata, DEFAULT_CREATE2_DEPLOYER_ZKSYNC,
get_account_code_key, get_balance_key, get_nonce_key,
vm::ZkEnv,
Call, ZkPaymasterData, ZkTransactionMetadata, DEFAULT_CREATE2_DEPLOYER_ZKSYNC,
};
use foundry_zksync_inspectors::TraceCollector;
use itertools::Itertools;
Expand Down Expand Up @@ -650,6 +651,8 @@ pub struct Cheatcodes {

/// Nonce update persistence behavior in zkEVM for the tx caller.
pub zk_persist_nonce_update: ZkPersistNonceUpdate,

pub zk_env: ZkEnv,
}

// This is not derived because calling this in `fn new` with `..Default::default()` creates a second
Expand Down Expand Up @@ -703,6 +706,7 @@ impl Cheatcodes {
persisted_factory_deps.insert(zk_bytecode_hash, zk_deployed_bytecode);

let zk_startup_migration = config.use_zk.then_some(ZkStartupMigration::Defer);
let zk_env = config.zk_env.clone().unwrap_or_default();

Self {
fs_commit: true,
Expand Down Expand Up @@ -750,6 +754,7 @@ impl Cheatcodes {
paymaster_params: None,
zk_use_factory_deps: Default::default(),
zk_persist_nonce_update: Default::default(),
zk_env,
}
}

Expand Down Expand Up @@ -1304,6 +1309,7 @@ impl Cheatcodes {
persisted_factory_deps: Some(&mut self.persisted_factory_deps),
paymaster_data: self.paymaster_params.take(),
persist_nonce_update: self.broadcast.is_some() || zk_persist_nonce_update,
zk_env: self.zk_env.clone(),
};

let zk_create = foundry_zksync_core::vm::ZkCreateInputs {
Expand Down Expand Up @@ -1968,6 +1974,7 @@ where {
persisted_factory_deps: Some(&mut self.persisted_factory_deps),
paymaster_data: self.paymaster_params.take(),
persist_nonce_update: self.broadcast.is_some() || zk_persist_nonce_update,
zk_env: self.zk_env.clone(),
};

let mut gas = Gas::new(call.gas_limit);
Expand Down
1 change: 1 addition & 0 deletions crates/chisel/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ impl SessionSource {
Some(self.solc.version.clone()),
Default::default(),
false,
None,
)
.into(),
)
Expand Down
4 changes: 3 additions & 1 deletion crates/evm/core/src/backend/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use alloy_primitives::{map::HashMap, Address, B256, U256};
use alloy_rpc_types::TransactionRequest;
use eyre::WrapErr;
use foundry_fork_db::DatabaseError;
use foundry_zksync_core::PaymasterParams;
use foundry_zksync_core::{vm::ZkEnv, PaymasterParams};
use revm::{
db::DatabaseRef,
primitives::{
Expand Down Expand Up @@ -65,6 +65,7 @@ impl<'a> CowBackend<'a> {
pub fn inspect_ref_zk(
&mut self,
env: &mut Env,
zk_env: &ZkEnv,
persisted_factory_deps: &mut HashMap<foundry_zksync_core::H256, Vec<u8>>,
factory_deps: Option<Vec<Vec<u8>>>,
paymaster_data: Option<PaymasterParams>,
Expand All @@ -78,6 +79,7 @@ impl<'a> CowBackend<'a> {
factory_deps,
paymaster_data,
env,
zk_env,
self,
)
}
Expand Down
4 changes: 3 additions & 1 deletion crates/evm/core/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use eyre::Context;
use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE};
pub use foundry_fork_db::{cache::BlockchainDbMeta, BlockchainDb, SharedBackend};
use foundry_zksync_core::{
convert::ConvertH160, PaymasterParams, ACCOUNT_CODE_STORAGE_ADDRESS,
convert::ConvertH160, vm::ZkEnv, PaymasterParams, ACCOUNT_CODE_STORAGE_ADDRESS,
IMMUTABLE_SIMULATOR_STORAGE_ADDRESS, KNOWN_CODES_STORAGE_ADDRESS, L2_BASE_TOKEN_ADDRESS,
NONCE_HOLDER_ADDRESS,
};
Expand Down Expand Up @@ -840,6 +840,7 @@ impl Backend {
pub fn inspect_ref_zk(
&mut self,
env: &mut EnvWithHandlerCfg,
zk_env: &ZkEnv,
persisted_factory_deps: &mut HashMap<foundry_zksync_core::H256, Vec<u8>>,
factory_deps: Option<Vec<Vec<u8>>>,
paymaster_data: Option<PaymasterParams>,
Expand All @@ -851,6 +852,7 @@ impl Backend {
factory_deps,
paymaster_data,
env,
zk_env,
self,
)
}
Expand Down
24 changes: 18 additions & 6 deletions crates/evm/evm/src/executors/builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{executors::Executor, inspectors::InspectorStackBuilder};
use foundry_evm_core::backend::Backend;
use foundry_zksync_core::vm::ZkEnv;
use revm::primitives::{Env, EnvWithHandlerCfg, SpecId};

/// The builder that allows to configure an evm [`Executor`] which a stack of optional
Expand All @@ -19,8 +20,10 @@ pub struct ExecutorBuilder {
/// The spec ID.
spec_id: SpecId,

use_zk: bool,
legacy_assertions: bool,

use_zk: bool,
zk_env: ZkEnv,
}

impl Default for ExecutorBuilder {
Expand All @@ -30,8 +33,9 @@ impl Default for ExecutorBuilder {
stack: InspectorStackBuilder::new(),
gas_limit: None,
spec_id: SpecId::LATEST,
use_zk: false,
legacy_assertions: false,
use_zk: false,
zk_env: Default::default(),
}
}
}
Expand Down Expand Up @@ -67,24 +71,31 @@ impl ExecutorBuilder {
self
}

/// Sets the `legacy_assertions` flag.
#[inline]
pub fn legacy_assertions(mut self, legacy_assertions: bool) -> Self {
self.legacy_assertions = legacy_assertions;
self
}

/// Sets the EVM spec to use
#[inline]
pub fn use_zk_vm(mut self, enable: bool) -> Self {
self.use_zk = enable;
self
}

/// Sets the `legacy_assertions` flag.
/// Sets zk_env
#[inline]
pub fn legacy_assertions(mut self, legacy_assertions: bool) -> Self {
self.legacy_assertions = legacy_assertions;
pub fn zk_env(mut self, zk_env: ZkEnv) -> Self {
self.zk_env = zk_env;
self
}

/// Builds the executor as configured.
#[inline]
pub fn build(self, env: Env, db: Backend) -> Executor {
let Self { mut stack, gas_limit, spec_id, legacy_assertions, use_zk } = self;
let Self { mut stack, gas_limit, spec_id, legacy_assertions, use_zk, zk_env } = self;
if stack.block.is_none() {
stack.block = Some(env.block.clone());
}
Expand All @@ -95,6 +106,7 @@ impl ExecutorBuilder {
let env = EnvWithHandlerCfg::new_with_spec_id(Box::new(env), spec_id);
let mut exec = Executor::new(db, env, stack.build(), gas_limit, legacy_assertions);
exec.use_zk = use_zk;
exec.zk_env = zk_env;
exec
}
}
6 changes: 5 additions & 1 deletion crates/evm/evm/src/executors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use foundry_evm_core::{
};
use foundry_evm_coverage::HitMaps;
use foundry_evm_traces::{SparsedTraceArena, TraceMode};
use foundry_zksync_core::ZkTransactionMetadata;
use foundry_zksync_core::{vm::ZkEnv, ZkTransactionMetadata};
use revm::{
db::{DatabaseCommit, DatabaseRef},
interpreter::{return_ok, InstructionResult},
Expand Down Expand Up @@ -97,6 +97,7 @@ pub struct Executor {
zk_persisted_factory_deps: HashMap<foundry_zksync_core::H256, Vec<u8>>,

pub use_zk: bool,
pub zk_env: ZkEnv,
}

impl Executor {
Expand Down Expand Up @@ -137,6 +138,7 @@ impl Executor {
zk_tx: None,
zk_persisted_factory_deps: Default::default(),
use_zk: false,
zk_env: Default::default(),
}
}

Expand Down Expand Up @@ -453,6 +455,7 @@ impl Executor {
env.tx.gas_price = self.env.tx.gas_price;
backend.inspect_ref_zk(
&mut env,
&self.zk_env,
&mut self.zk_persisted_factory_deps.clone(),
Some(zk_tx.factory_deps.clone()),
zk_tx.paymaster_data.clone(),
Expand All @@ -476,6 +479,7 @@ impl Executor {
env.tx.gas_price = self.env.tx.gas_price;
backend.inspect_ref_zk(
&mut env,
&self.zk_env,
// this will persist the added factory deps,
// no need to commit them later
&mut self.zk_persisted_factory_deps,
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 @@ -256,6 +256,7 @@ impl MultiContractRunner {
Some(artifact_id.version.clone()),
self.dual_compiled_contracts.clone(),
self.use_zk,
None,
);

let trace_mode = TraceMode::default()
Expand Down
6 changes: 3 additions & 3 deletions crates/forge/tests/it/zk/factory_deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ contract ZkLargeFactoryDependenciesScript is Script {

let node = ZkSyncNode::start();

// foundry default gas-limit is not enough to pay for factory deps in our current
// default environment
let gas_limit = u32::MAX >> 1;
// foundry default gas-limit is not enough to pay for factory deps
// with era_test_node's environment
let gas_limit = (u32::MAX >> 1) * 2;

cmd.arg("script").args([
"--zk-startup",
Expand Down
35 changes: 35 additions & 0 deletions crates/script/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use alloy_primitives::{
Address, Bytes, Log, TxKind, U256,
};
use alloy_signer::Signer;
use alloy_zksync::provider::{zksync_provider, ZksyncProvider};
use broadcast::next_nonce;
use build::PreprocessedState;
use clap::{Parser, ValueHint};
Expand Down Expand Up @@ -57,6 +58,7 @@ use foundry_evm::{
};
use foundry_wallets::MultiWalletOpts;
use foundry_zksync_compiler::DualCompiledContracts;
use foundry_zksync_core::vm::ZkEnv;
use serde::Serialize;
use std::path::PathBuf;

Expand Down Expand Up @@ -621,6 +623,38 @@ impl ScriptConfig {
.legacy_assertions(self.config.legacy_assertions);

let use_zk = self.config.zksync.run_in_zk_mode();
let mut maybe_zk_env = None;
if use_zk {
if let Some(fork_url) = &self.evm_opts.fork_url {
let provider =
zksync_provider().with_recommended_fillers().on_http(fork_url.parse()?);
// TODO(zk): switch to getFeeParams call when it is implemented for anvil-zksync
let maybe_details =
provider.get_block_details(env.block.number.try_into()?).await?;
dutterbutter marked this conversation as resolved.
Show resolved Hide resolved
if let Some(details) = maybe_details {
let zk_env = ZkEnv {
l1_gas_price: details
.l1_gas_price
.try_into()
.expect("failed to convert l1_gas_price to u64"),
fair_l2_gas_price: details
.l2_fair_gas_price
.try_into()
.expect("failed to convert fair_l2_gas_price to u64"),
fair_pubdata_price: details
.fair_pubdata_price
// TODO(zk): None as a value might mean L1Pegged model
// we need to find out if it will ever be relevant to
// us
.unwrap_or_default()
.try_into()
.expect("failed to convert fair_pubdata_price to u64"),
};
builder = builder.zk_env(zk_env.clone());
maybe_zk_env = Some(zk_env);
}
};
}
if let Some((known_contracts, script_wallets, target, dual_compiled_contracts)) =
cheats_data
{
Expand All @@ -636,6 +670,7 @@ impl ScriptConfig {
Some(target.version),
dual_compiled_contracts,
use_zk,
maybe_zk_env,
)
.into(),
)
Expand Down
4 changes: 2 additions & 2 deletions crates/zksync/core/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub fn fix_l2_gas_price(gas_price: U256) -> U256 {

/// Limits the gas_limit proportional to a user's available balance given the gas_price.
///
/// Additionally, fixes the gas limit to be maximum of 2^31, which is below the VM gas limit of
/// Additionally, fixes the gas limit to be maximum of 2^31 * 2, which is below the VM gas limit of
/// 2^32. This is required so the bootloader does not throw an error for not having enough balance
/// to pay for gas.
///
Expand All @@ -131,5 +131,5 @@ pub fn fix_l2_gas_limit(
U256::min(proposed_gas_limit, max_gas_limit)
};

U256::min(gas_limit, U256::from(u32::MAX >> 1))
U256::min(gas_limit, U256::from((u32::MAX >> 1) * 2))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this should also be a constant as it's being used in multiple places.

}
Loading
Loading