Skip to content

Commit

Permalink
refactor: only script/test evm or zksync (#435)
Browse files Browse the repository at this point in the history
  • Loading branch information
Karrq authored Jun 25, 2024
1 parent 56b536b commit f505a53
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 45 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ out = 'out'
libs = ['lib']
[profile.default.zksync]
enable = true
compile = true
fallback_oz = true
mode = '3'
```
Expand Down
2 changes: 2 additions & 0 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,7 @@ impl<DB: DatabaseExt + Send> Inspector<DB> for Cheatcodes {

let constructor_input =
call.init_code[contract.evm_bytecode.len()..].to_vec();

let create_input = foundry_zksync_core::encode_create_params(
&call.scheme,
contract.zk_bytecode_hash,
Expand Down Expand Up @@ -1712,6 +1713,7 @@ impl<DB: DatabaseExt + Send> Inspector<DB> for Cheatcodes {

let factory_deps = self.dual_compiled_contracts.fetch_all_factory_deps(zk_contract);
tracing::debug!(contract = zk_contract.name, "using dual compiled contract");

let ccx = foundry_zksync_core::vm::CheatcodeTracerContext {
mocked_calls: self.mocked_calls.clone(),
expected_calls: Some(&mut self.expected_calls),
Expand Down
53 changes: 44 additions & 9 deletions crates/cli/src/opts/build/zksync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,27 @@ use serde::Serialize;
#[derive(Clone, Debug, Default, Serialize, Parser)]
#[clap(next_help_heading = "ZKSync configuration")]
pub struct ZkSyncArgs {
/// Use ZKSync era vm.
#[clap(long = "zksync", visible_alias = "zk")]
pub enable: bool,
/// Compile for zkVM
#[clap(
long = "zk-compile",
value_name = "COMPILE_FOR_ZKVM",
num_args = 0..=1,
require_equals = true,
default_missing_value = "true",
default_value_if("startup", "true", "true"))]
pub compile: Option<bool>,

/// Enable zkVM at startup
#[clap(
long = "zk-startup",
visible_alias = "zksync",
display_order = 0,
value_name = "ENABLE_ZKVM_AT_STARTUP",
num_args = 0..=1,
require_equals = true,
default_missing_value = "true",
)]
pub startup: Option<bool>,

#[clap(
help = "Solc compiler path to use when compiling with zksolc",
Expand All @@ -25,7 +43,10 @@ pub struct ZkSyncArgs {
long = "zk-eravm-extensions",
visible_alias = "enable-eravm-extensions",
visible_alias = "system-mode",
value_name = "ENABLE_ERAVM_EXTENSIONS"
value_name = "ENABLE_ERAVM_EXTENSIONS",
num_args = 0..=1,
require_equals = true,
default_missing_value = "true"
)]
#[serde(skip_serializing_if = "Option::is_none")]
pub eravm_extensions: Option<bool>,
Expand All @@ -35,14 +56,23 @@ pub struct ZkSyncArgs {
help = "Forcibly switch to the EVM legacy assembly pipeline.",
long = "zk-force-evmla",
visible_alias = "force-evmla",
value_name = "FORCE_EVMLA"
value_name = "FORCE_EVMLA",
num_args = 0..=1,
require_equals = true,
default_missing_value = "true"
)]
#[serde(skip_serializing_if = "Option::is_none")]
pub force_evmla: Option<bool>,

/// Try to recompile with -Oz if the bytecode is too large.
#[clap(long = "zk-fallback-oz", visible_alias = "fallback-oz", value_name = "FALLBACK_OZ")]
#[serde(skip_serializing_if = "Option::is_none")]
#[clap(
long = "zk-fallback-oz",
visible_alias = "fallback-oz",
value_name = "FALLBACK_OZ",
num_args = 0..=1,
require_equals = true,
default_missing_value = "true"
)]
pub fallback_oz: Option<bool>,

/// Detect missing libraries, instead of erroring
Expand All @@ -64,7 +94,6 @@ pub struct ZkSyncArgs {

/// Enables optimizations
#[clap(long = "zk-optimizer")]
#[serde(skip)]
pub optimizer: bool,

/// Contracts to avoid compiling on zkSync
Expand All @@ -73,6 +102,11 @@ pub struct ZkSyncArgs {
}

impl ZkSyncArgs {
/// Returns true if zksync mode is enabled
pub fn enabled(&self) -> bool {
self.compile.unwrap_or_default()
}

/// Merge the current cli arguments into the specified zksync configuration
pub(crate) fn apply_overrides(&self, mut zksync: ZkSyncConfig) -> ZkSyncConfig {
macro_rules! set_if_some {
Expand All @@ -83,7 +117,8 @@ impl ZkSyncArgs {
};
}

set_if_some!(self.enable.then_some(true), zksync.enable);
set_if_some!(self.compile, zksync.compile);
set_if_some!(self.startup, zksync.startup);
set_if_some!(self.solc_path.clone(), zksync.solc_path);
set_if_some!(self.eravm_extensions, zksync.eravm_extensions);
set_if_some!(self.force_evmla, zksync.force_evmla);
Expand Down
6 changes: 4 additions & 2 deletions crates/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,10 @@ The `zksync` settings must be prefixed with the profile they correspond to:

``` toml
[profile.default.zksync]
# Overridden by `--zksync` flag
enable = false
# Compile contracts for zkVM
compile = false
# Enable zkVM at startup, needs `compile = true` to have effect
startup = true
# By default the latest version is used
zksolc = "1.5.0"
# By default the corresponding solc patched version from matter-labs is used
Expand Down
17 changes: 13 additions & 4 deletions crates/config/src/zksync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ use crate::SolcReq;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
/// ZkSync configuration
pub struct ZkSyncConfig {
/// Enable zksync mode
pub enable: bool,
/// Compile for zkVM
pub compile: bool,

/// Start VM in zkVM mode
pub startup: bool,

/// The zkSolc instance to use if any.
pub zksolc: Option<SolcReq>,
Expand Down Expand Up @@ -54,7 +57,8 @@ pub struct ZkSyncConfig {
impl Default for ZkSyncConfig {
fn default() -> Self {
Self {
enable: Default::default(),
compile: Default::default(),
startup: true,
zksolc: Default::default(),
solc_path: Default::default(),
bytecode_hash: Default::default(),
Expand All @@ -73,7 +77,12 @@ impl Default for ZkSyncConfig {
impl ZkSyncConfig {
/// Returns true if zk mode is enabled and it if tests should be run in zk mode
pub fn run_in_zk_mode(&self) -> bool {
self.enable
self.compile && self.startup
}

/// Returns true if contracts should be compiled for zk
pub fn should_compile(&self) -> bool {
self.compile
}

/// Convert the zksync config to a foundry_compilers zksync Settings
Expand Down
2 changes: 1 addition & 1 deletion crates/forge/bin/cmd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl BuildArgs {
project = config.project()?;
}

if !config.zksync.enable {
if !config.zksync.should_compile() {
let mut compiler = ProjectCompiler::new()
.print_names(self.names)
.print_sizes(self.sizes)
Expand Down
2 changes: 1 addition & 1 deletion crates/forge/bin/cmd/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl CreateArgs {
pub async fn run(self) -> Result<()> {
let mut config = self.eth.try_load_config_emit_warnings()?;
let project_root = config.project_paths().root;
let zksync = self.opts.compiler.zk.enable;
let zksync = self.opts.compiler.zk.enabled();

// Resolve missing libraries
let libs_batches = if zksync && self.deploy_missing_libraries {
Expand Down
23 changes: 14 additions & 9 deletions crates/forge/bin/cmd/script/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,19 @@ impl ScriptArgs {
let root = project.root();
let output = output.with_stripped_file_prefixes(root);

// ZK
// TODO: see if we need to support the `get_project_and_output` flow
// seems it verifies script is part of the project
let zk_compiler = ProjectCompiler::new().quiet(self.opts.args.silent);
let zk_output = zk_compiler.zksync_compile(&project)?;

let dual_compiled_contracts =
DualCompiledContracts::new(&output, &zk_output, &project.paths);
// TODO: find a way to not compile _all_ contracts but only the ones necessary
// in each mode
let dual_compiled_contracts = if script_config.config.zksync.should_compile() {
// ZK
// TODO: see if we need to support the `get_project_and_output` flow
// seems it verifies script is part of the project
let zk_compiler = ProjectCompiler::new().quiet(self.opts.args.silent);
let zk_output = zk_compiler.zksync_compile(&project)?;

Some(DualCompiledContracts::new(&output, &zk_output, &project.paths))
} else {
None
};

let sources = ContractSources::from_project_output(&output, root)?;
let contracts = output.into_artifacts().collect();
Expand Down Expand Up @@ -64,7 +69,7 @@ impl ScriptArgs {
libraries,
predeploy_libraries,
sources,
dual_compiled_contracts: Some(dual_compiled_contracts),
dual_compiled_contracts,
})
}

Expand Down
13 changes: 8 additions & 5 deletions crates/forge/bin/cmd/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,13 @@ impl TestArgs {
}
let output = compiler.compile(&project)?;

let zk_compiler = ProjectCompiler::new().quiet_if(self.json || self.opts.silent);
let zk_output = zk_compiler.zksync_compile(&project)?;
let dual_compiled_contracts =
DualCompiledContracts::new(&output, &zk_output, &project.paths);
let dual_compiled_contracts = if config.zksync.should_compile() {
let zk_compiler = ProjectCompiler::new().quiet_if(self.json || self.opts.silent);
let zk_output = zk_compiler.zksync_compile(&project)?;
Some(DualCompiledContracts::new(&output, &zk_output, &project.paths))
} else {
None
};

// Create test options from general project settings and compiler output.
let project_root = &project.paths.root;
Expand Down Expand Up @@ -209,7 +212,7 @@ impl TestArgs {
&config,
evm_opts.clone(),
None,
dual_compiled_contracts,
dual_compiled_contracts.unwrap_or_default(),
config.zksync.run_in_zk_mode(),
))
.with_test_options(test_options.clone())
Expand Down
26 changes: 13 additions & 13 deletions zk-tests/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,41 +128,41 @@ build_forge "${REPO_ROOT}"
start_era_test_node

# Test missing libraries detection and deploy
output=$(RUST_LOG=warn "${FORGE}" build --zksync 2>&1 || true)
output=$(RUST_LOG=warn "${FORGE}" build --zk-compile 2>&1 || true)

if echo "$output" | grep -q "Missing libraries detected"; then
RUST_LOG=warn "${FORGE}" create --deploy-missing-libraries --rpc-url $RPC_URL --private-key $PRIVATE_KEY --zksync
RUST_LOG=warn "${FORGE}" script ./src/MissingLibraries.sol:MathematicianScript --rpc-url $RPC_URL --private-key $PRIVATE_KEY --zksync --chain 260 --use "./${SOLC}" -vvv || fail "forge script with libs failed"
RUST_LOG=warn "${FORGE}" script ./src/NestedMissingLibraries.sol:NestedMathematicianScript --rpc-url $RPC_URL --private-key $PRIVATE_KEY --zksync --chain 260 --use "./${SOLC}" -vvv || fail "forge script with nested libs failed"
RUST_LOG=warn "${FORGE}" create --deploy-missing-libraries --rpc-url $RPC_URL --private-key $PRIVATE_KEY --zk-compile
RUST_LOG=warn "${FORGE}" script ./src/MissingLibraries.sol:MathematicianScript --rpc-url $RPC_URL --private-key $PRIVATE_KEY --zk-startup --chain 260 --use "./${SOLC}" -vvv || fail "forge script with libs failed"
RUST_LOG=warn "${FORGE}" script ./src/NestedMissingLibraries.sol:NestedMathematicianScript --rpc-url $RPC_URL --private-key $PRIVATE_KEY --zk-startup --chain 260 --use "./${SOLC}" -vvv || fail "forge script with nested libs failed"
else
echo "No missing libraries detected."
fi

echo "Running tests..."
RUST_LOG=warn "${FORGE}" test --use "./${SOLC}" --chain 300 -vvv || fail "forge test failed"
RUST_LOG=warn "${FORGE}" test --use "./${SOLC}" --chain 300 -vvv --zk-compile || fail "forge test failed"

echo "Running tests with '--zksync'..."
RUST_LOG=warn "${FORGE}" test --use "./${SOLC}" --chain 300 -vvv --zksync || fail "forge test --zksync failed"
echo "Running tests with '--zk-startup'..."
RUST_LOG=warn "${FORGE}" test --use "./${SOLC}" --chain 300 -vvv --zk-startup || fail "forge test --zk-startup failed"

echo "Running script..."
RUST_LOG=warn "${FORGE}" script ./script/Deploy.s.sol:DeployScript --broadcast --private-key "$PRIVATE_KEY" --chain 260 --gas-estimate-multiplier 310 --rpc-url "$RPC_URL" --use "./${SOLC}" --slow -vvv || fail "forge script failed"
RUST_LOG=warn "${FORGE}" script ./script/Deploy.s.sol:DeployScript --broadcast --private-key "$PRIVATE_KEY" --chain 260 --gas-estimate-multiplier 310 --rpc-url "$RPC_URL" --use "./${SOLC}" --slow -vvv || fail "forge script failed on 2nd deploy"
RUST_LOG=warn "${FORGE}" script ./script/Deploy.s.sol:DeployScript --broadcast --private-key "$PRIVATE_KEY" --chain 260 --gas-estimate-multiplier 310 --rpc-url "$RPC_URL" --use "./${SOLC}" --slow -vvv --zk-compile || fail "forge script failed"
RUST_LOG=warn "${FORGE}" script ./script/Deploy.s.sol:DeployScript --broadcast --private-key "$PRIVATE_KEY" --chain 260 --gas-estimate-multiplier 310 --rpc-url "$RPC_URL" --use "./${SOLC}" --slow -vvv --zk-compile || fail "forge script failed on 2nd deploy"

echo "Running NFT script"
RUST_LOG=warn "${FORGE}" script ./script/NFT.s.sol:MyScript --broadcast --private-key $PRIVATE_KEY --rpc-url $RPC_URL --use 0.8.20 --zksync || fail "forge script failed"
RUST_LOG=warn "${FORGE}" script ./script/NFT.s.sol:MyScript --broadcast --private-key $PRIVATE_KEY --rpc-url $RPC_URL --use 0.8.20 --zk-startup || fail "forge script failed"

echo "Running Proxy script"
RUST_LOG=warn "${FORGE}" script ./script/Proxy.s.sol:ProxyScript --broadcast --private-key $PRIVATE_KEY --rpc-url $RPC_URL --use 0.8.20 --zksync || fail "forge proxy script failed"
RUST_LOG=warn "${FORGE}" script ./script/Proxy.s.sol:ProxyScript --broadcast --private-key $PRIVATE_KEY --rpc-url $RPC_URL --use 0.8.20 --zk-startup || fail "forge proxy script failed"

# Deploy ERC20
echo "Deploying MyToken..."
MYTOKEN_DEPLOYMENT=$(RUST_LOG=warn "${FORGE}" create ./src/ERC20.sol:MyToken --rpc-url $RPC_URL --private-key $PRIVATE_KEY --use 0.8.20 --zksync) || fail "forge script failed"
MYTOKEN_DEPLOYMENT=$(RUST_LOG=warn "${FORGE}" create ./src/ERC20.sol:MyToken --rpc-url $RPC_URL --private-key $PRIVATE_KEY --use 0.8.20 --zk-startup) || fail "forge script failed"
MYTOKEN_ADDRESS=$(echo $MYTOKEN_DEPLOYMENT | awk '/Deployed to:/ {for (i=1; i<=NF; i++) if ($i == "to:") print $(i+1)}')
echo "MyToken deployed at: $MYTOKEN_ADDRESS"

# Deploy TokenReceiver
echo "Deploying TokenReceiver..."
TOKENRECEIVER_DEPLOYMENT=$(RUST_LOG=warn "${FORGE}" create ./src/TokenReceiver.sol:TokenReceiver --rpc-url $RPC_URL --private-key $PRIVATE_KEY --use "./${SOLC}" --zksync) || fail "forge script failed"
TOKENRECEIVER_DEPLOYMENT=$(RUST_LOG=warn "${FORGE}" create ./src/TokenReceiver.sol:TokenReceiver --rpc-url $RPC_URL --private-key $PRIVATE_KEY --use "./${SOLC}" --zk-startup) || fail "forge script failed"
TOKENRECEIVER_ADDRESS=$(echo $TOKENRECEIVER_DEPLOYMENT | awk '/Deployed to:/ {for (i=1; i<=NF; i++) if ($i == "to:") print $(i+1)}')
echo "TokenReceiver deployed at: $TOKENRECEIVER_ADDRESS"

Expand Down

0 comments on commit f505a53

Please sign in to comment.