Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into upstream-fef2098-main…
Browse files Browse the repository at this point in the history
…-update
  • Loading branch information
Karrq committed Dec 4, 2024
2 parents aca67aa + 0dcc03e commit aa1ac7a
Show file tree
Hide file tree
Showing 17 changed files with 351 additions and 494 deletions.
5 changes: 3 additions & 2 deletions .github/scripts/matrices.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ def __init__(
# TODO: Figure out how to make this work
# t_linux_arm = Target("ubuntu-latest", "aarch64-unknown-linux-gnu", "linux-aarch64")
t_macos = Target("macos-latest", "aarch64-apple-darwin", "macosx-aarch64")
t_windows = Target("windows-latest", "x86_64-pc-windows-msvc", "windows-amd64")
targets = [t_linux_x86, t_windows] if is_pr else [t_linux_x86, t_macos, t_windows]
# NOTE(zk): ZKsync-era doesn't support windows as of now
# t_windows = Target("windows-latest", "x86_64-pc-windows-msvc", "windows-amd64")
targets = [t_linux_x86] if is_pr else [t_linux_x86, t_macos]

config = [
Case(
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ env:
TARGET_RUST_VERSION: "nightly-2024-09-01"

jobs:
nextest:
uses: ./.github/workflows/nextest.yml
with:
profile: default
secrets: inherit

doctest:
runs-on: ubuntu-22.04
timeout-minutes: 60
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/cast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ foundry-config.workspace = true
foundry-evm.workspace = true
foundry-wallets.workspace = true
foundry-zksync-core.workspace = true
rustls = { version = "0.23", features = ["ring"] }

alloy-chains.workspace = true
alloy-consensus = { workspace = true, features = ["serde", "kzg"] }
Expand Down
3 changes: 2 additions & 1 deletion crates/cast/bin/cmd/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ async fn cast_send<P: Provider<T, AnyNetwork>, T: Transport + Clone>(
async fn cast_send_zk<P: Provider<T, AnyNetwork>, Z: ZksyncProvider<T>, T: Transport + Clone>(
provider: P,
zk_provider: Z,
tx: WithOtherFields<TransactionRequest>,
mut tx: WithOtherFields<TransactionRequest>,
zksync_params: ZksyncParams,
cast_async: bool,
confs: u64,
Expand All @@ -280,6 +280,7 @@ async fn cast_send_zk<P: Provider<T, AnyNetwork>, Z: ZksyncProvider<T>, T: Trans
paymaster_input: Bytes::from_str(&input).expect("Invalid paymaster input"),
});

tx.inner.transaction_type = Some(zksync_types::l2::TransactionType::EIP712Transaction as u8);
let mut zk_tx: ZkTransactionRequest = tx.inner.clone().into();
if let Some(paymaster_params) = paymaster_params {
zk_tx.set_paymaster_params(paymaster_params);
Expand Down
5 changes: 5 additions & 0 deletions crates/cast/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ fn main() {
}

fn run() -> Result<()> {
// NOTE(zk): We need to manually install the crypto provider as zksync-era uses `aws-lc-rs`
// provider, while foundry uses the `ring` provider. As a result, rustls cannot disambiguate
// between the two while selecting a default provider.
let _ = rustls::crypto::ring::default_provider().install_default();

handler::install();
utils::load_dotenv();
utils::subscriber();
Expand Down
41 changes: 35 additions & 6 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1273,7 +1273,27 @@ impl Cheatcodes {
constructor_args.to_vec(),
);

let factory_deps = self.dual_compiled_contracts.fetch_all_factory_deps(contract);
let mut factory_deps = self.dual_compiled_contracts.fetch_all_factory_deps(contract);
let injected_factory_deps = self
.zk_use_factory_deps
.iter()
.flat_map(|contract| {
let artifact_code = crate::fs::get_artifact_code(self, contract, false)
.inspect(|_| info!(contract, "pushing factory dep"))
.unwrap_or_else(|_| {
panic!(
"failed to get bytecode for injected factory deps contract {contract}"
)
})
.to_vec();
let res = self.dual_compiled_contracts.find_bytecode(&artifact_code).unwrap();
self.dual_compiled_contracts.fetch_all_factory_deps(res.contract())
})
.collect_vec();
factory_deps.extend(injected_factory_deps);

// NOTE(zk): Clear injected factory deps so that they are not sent on further transactions
self.zk_use_factory_deps.clear();
tracing::debug!(contract = contract.name, "using dual compiled contract");

let zk_persist_nonce_update = self.zk_persist_nonce_update.check();
Expand Down Expand Up @@ -1557,8 +1577,10 @@ where {
let prev = account.info.nonce;
let nonce = prev.saturating_sub(1);
account.info.nonce = nonce;
// NOTE(zk): We sync with the nonce changes to ensure that the nonce matches
foundry_zksync_core::cheatcodes::set_nonce(sender, U256::from(nonce), &mut ecx.inner);
if self.use_zk_vm {
// NOTE(zk): We sync with the nonce changes to ensure that the nonce matches
foundry_zksync_core::cheatcodes::set_nonce(sender, U256::from(nonce), ecx);
}

trace!(target: "cheatcodes", %sender, nonce, prev, "corrected nonce");
}
Expand Down Expand Up @@ -1765,13 +1787,15 @@ where {
ecx_inner.journaled_state.state().get_mut(&broadcast.new_origin).unwrap();

let zk_tx = if self.use_zk_vm {
let injected_factory_deps = self.zk_use_factory_deps.iter().map(|contract| {
crate::fs::get_artifact_code(self, contract, false)
let injected_factory_deps = self.zk_use_factory_deps.iter().flat_map(|contract| {
let artifact_code = crate::fs::get_artifact_code(self, contract, false)
.inspect(|_| info!(contract, "pushing factory dep"))
.unwrap_or_else(|_| {
panic!("failed to get bytecode for factory deps contract {contract}")
})
.to_vec()
.to_vec();
let res = self.dual_compiled_contracts.find_bytecode(&artifact_code).unwrap();
self.dual_compiled_contracts.fetch_all_factory_deps(res.contract())
}).collect_vec();
factory_deps.extend(injected_factory_deps.clone());

Expand Down Expand Up @@ -1932,6 +1956,11 @@ where {

info!("running call in zkEVM {:#?}", call);
let zk_persist_nonce_update = self.zk_persist_nonce_update.check();

// NOTE(zk): Clear injected factory deps here even though it's actually used in broadcast.
// To be consistent with where we clear factory deps in try_create_in_zk.
self.zk_use_factory_deps.clear();

let ccx = foundry_zksync_core::vm::CheatcodeTracerContext {
mocked_calls: self.mocked_calls.clone(),
expected_calls: Some(&mut self.expected_calls),
Expand Down
9 changes: 7 additions & 2 deletions crates/cli/src/opts/build/zksync.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{collections::HashSet, path::PathBuf};

use alloy_primitives::{Address, Bytes};
use alloy_primitives::{hex, Address, Bytes};
use clap::Parser;
use foundry_compilers::zksolc::settings::{ZkSolcError, ZkSolcWarning};
use foundry_config::ZkSyncConfig;
Expand Down Expand Up @@ -115,7 +115,8 @@ pub struct ZkSyncArgs {
#[clap(
long = "zk-paymaster-input",
value_name = "PAYMASTER_INPUT",
visible_alias = "paymaster-input"
visible_alias = "paymaster-input",
value_parser = parse_hex_bytes
)]
pub paymaster_input: Option<Bytes>,

Expand Down Expand Up @@ -185,3 +186,7 @@ impl ZkSyncArgs {
zksync
}
}

fn parse_hex_bytes(s: &str) -> Result<Bytes, String> {
hex::decode(s).map(Bytes::from).map_err(|e| format!("Invalid hex string: {e}"))
}
1 change: 1 addition & 0 deletions crates/forge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ watchexec-events = "3.0"
watchexec-signals = "3.0"
clearscreen = "3.0"
evm-disassembler.workspace = true
rustls = { version = "0.23", features = ["ring"] }

# doc server
axum = { workspace = true, features = ["ws"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract DeployCounterWithBytecodeHash is Script {
Factory factory = new Factory(counterBytecodeHash);
(bool _success,) = address(vm).call(abi.encodeWithSignature("zkUseFactoryDep(string)", "Counter"));
require(_success, "Cheatcode failed");
address counter = factory.deployAccount(salt);
address counter = factory.deployContract(salt, abi.encode());
require(counter != address(0), "Counter deployment failed");
vm.stopBroadcast();
}
Expand Down
28 changes: 25 additions & 3 deletions crates/forge/tests/fixtures/zk/Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,47 @@ pragma solidity ^0.8.17;
import "zksync-contracts/zksync-contracts/l2/system-contracts/Constants.sol";
import "zksync-contracts/zksync-contracts/l2/system-contracts/libraries/SystemContractsCaller.sol";

contract Factory {
contract AAFactory {
bytes32 public aaBytecodeHash;

constructor(bytes32 _aaBytecodeHash) {
aaBytecodeHash = _aaBytecodeHash;
}

function deployAccount(bytes32 salt) external returns (address accountAddress) {
function deployAccount(bytes32 salt, bytes memory constructorArgs) external returns (address accountAddress) {
(bool success, bytes memory returnData) = SystemContractsCaller.systemCallWithReturndata(
uint32(gasleft()),
address(DEPLOYER_SYSTEM_CONTRACT),
uint128(0),
abi.encodeCall(
DEPLOYER_SYSTEM_CONTRACT.create2Account,
(salt, aaBytecodeHash, abi.encode(), IContractDeployer.AccountAbstractionVersion.Version1)
(salt, aaBytecodeHash, constructorArgs, IContractDeployer.AccountAbstractionVersion.Version1)
)
);
require(success, "Deployment failed");

(accountAddress) = abi.decode(returnData, (address));
}
}

contract Factory {
bytes32 public bytecodeHash;

constructor(bytes32 _bytecodeHash) {
bytecodeHash = _bytecodeHash;
}


function deployContract(bytes32 salt, bytes memory constructorArgs) external returns (address contractAddress) {
(bool success, bytes memory returnData) = SystemContractsCaller.systemCallWithReturndata(
uint32(gasleft()),
address(DEPLOYER_SYSTEM_CONTRACT),
uint128(0),
abi.encodeCall(DEPLOYER_SYSTEM_CONTRACT.create2, (salt, bytecodeHash, constructorArgs))
);

require(success, "Deployment failed");

(contractAddress) = abi.decode(returnData, (address));
}
}
4 changes: 4 additions & 0 deletions crates/forge/tests/it/test_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@ impl ForgeTestData {
pub fn new(profile: ForgeTestProfile) -> Self {
init_tracing();

// NOTE(zk): We need to manually install the crypto provider as zksync-era uses `aws-lc-rs`
// provider, while foundry uses the `ring` provider. As a result, rustls cannot
// disambiguate between the two while selecting a default provider.
let _ = rustls::crypto::ring::default_provider().install_default();
let mut project = profile.project();
let output = get_compiled(&mut project);
let test_opts = profile.test_opts(&output);
Expand Down
89 changes: 44 additions & 45 deletions crates/forge/tests/it/zk/factory_deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use foundry_test_utils::{
use crate::{config::TestConfig, test_helpers::TEST_DATA_DEFAULT};

#[tokio::test(flavor = "multi_thread")]
#[ignore = "disabled since #476"]
async fn test_zk_can_deploy_large_factory_deps() {
let runner = TEST_DATA_DEFAULT.runner_zksync();
{
Expand All @@ -19,20 +18,17 @@ async fn test_zk_can_deploy_large_factory_deps() {
}
}

forgetest_async!(
#[ignore = "disabled since #476"]
script_zk_can_deploy_large_factory_deps,
|prj, cmd| {
util::initialize(prj.root());
forgetest_async!(script_zk_can_deploy_large_factory_deps, |prj, cmd| {
util::initialize(prj.root());

prj.add_source(
"LargeContracts.sol",
include_str!("../../../../../testdata/zk/LargeContracts.sol"),
)
.unwrap();
prj.add_script(
"LargeContracts.s.sol",
r#"
prj.add_source(
"LargeContracts.sol",
include_str!("../../../../../testdata/zk/LargeContracts.sol"),
)
.unwrap();
prj.add_script(
"LargeContracts.s.sol",
r#"
import "forge-std/Script.sol";
import "../src/LargeContracts.sol";
Expand All @@ -43,39 +39,42 @@ contract ZkLargeFactoryDependenciesScript is Script {
}
}
"#,
)
.unwrap();
)
.unwrap();
let node = ZkSyncNode::start();
let node = ZkSyncNode::start();
cmd.arg("script").args([
"--zk-startup",
"./script/LargeContracts.s.sol",
"--broadcast",
"--private-key",
"0x3d3cbc973389cb26f657686445bcc75662b415b656078503592ac8c1abb8810e",
"--chain",
"260",
"--gas-estimate-multiplier",
"310",
"--rpc-url",
node.url().as_str(),
"--slow",
"--evm-version",
"shanghai",
]);
cmd.assert_success()
.get_output()
.stdout_lossy()
.contains("ONCHAIN EXECUTION COMPLETE & SUCCESSFUL");
// foundry default gas-limit is not enough to pay for factory deps in our current
// default environment
let gas_limit = u32::MAX >> 1;
let run_latest = foundry_common::fs::json_files(prj.root().join("broadcast").as_path())
.find(|file| file.ends_with("run-latest.json"))
.expect("No broadcast artifacts");
cmd.arg("script").args([
"--zk-startup",
"./script/LargeContracts.s.sol",
"--broadcast",
"--private-key",
"0x3d3cbc973389cb26f657686445bcc75662b415b656078503592ac8c1abb8810e",
"--chain",
"260",
"--gas-estimate-multiplier",
"310",
"--rpc-url",
node.url().as_str(),
"--slow",
"--gas-limit",
&gas_limit.to_string(),
]);
cmd.assert_success()
.get_output()
.stdout_lossy()
.contains("ONCHAIN EXECUTION COMPLETE & SUCCESSFUL");
let content = foundry_common::fs::read_to_string(run_latest).unwrap();
let run_latest = foundry_common::fs::json_files(prj.root().join("broadcast").as_path())
.find(|file| file.ends_with("run-latest.json"))
.expect("No broadcast artifacts");
let json: serde_json::Value = serde_json::from_str(&content).unwrap();
assert_eq!(json["transactions"].as_array().expect("broadcastable txs").len(), 1);
}
);
let content = foundry_common::fs::read_to_string(run_latest).unwrap();
let json: serde_json::Value = serde_json::from_str(&content).unwrap();
assert_eq!(json["transactions"].as_array().expect("broadcastable txs").len(), 3);
});
Loading

0 comments on commit aa1ac7a

Please sign in to comment.