Skip to content

Commit

Permalink
Merge branch 'main' into upstream-f5aa05e
Browse files Browse the repository at this point in the history
  • Loading branch information
elfedy committed Oct 31, 2024
2 parents 33034a2 + 9093c3c commit 2915b7f
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 56 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,16 @@ jobs:
files: |
${{ steps.artifacts.outputs.file_name }}
${{ steps.man.outputs.foundry_man }}
retry-on-failure:
if: failure() && fromJSON(github.run_attempt) < 3
needs: [release]
runs-on: ubuntu-latest
steps:
- env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
run: gh workflow run retry.yml -F run_id=${{ github.run_id }}

cleanup:
name: Release cleanup
Expand Down
80 changes: 40 additions & 40 deletions crates/cheatcodes/assets/cheatcodes.json

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

4 changes: 4 additions & 0 deletions crates/cheatcodes/spec/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,10 @@ interface Vm {
#[cheatcode(group = Testing, safety = Safe)]
function zkUsePaymaster(address paymaster_address, bytes calldata paymaster_input) external pure;

/// Marks the contract to be injected as a factory dependency in the next transaction
#[cheatcode(group = Testing, safety = Safe)]
function zkUseFactoryDep(string calldata name) external pure;

/// Registers bytecodes for ZK-VM for transact/call and create instructions.
#[cheatcode(group = Testing, safety = Safe)]
function zkRegisterContract(string calldata name, bytes32 evmBytecodeHash, bytes calldata evmDeployedBytecode, bytes calldata evmBytecode, bytes32 zkBytecodeHash, bytes calldata zkDeployedBytecode) external pure;
Expand Down
2 changes: 1 addition & 1 deletion crates/cheatcodes/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ impl Cheatcode for deployCode_1Call {
/// - `path/to/contract.sol:0.8.23`
/// - `ContractName`
/// - `ContractName:0.8.23`
fn get_artifact_code(state: &Cheatcodes, path: &str, deployed: bool) -> Result<Bytes> {
pub(crate) fn get_artifact_code(state: &Cheatcodes, path: &str, deployed: bool) -> Result<Bytes> {
let path = if path.ends_with(".json") {
PathBuf::from(path)
} else {
Expand Down
29 changes: 27 additions & 2 deletions crates/cheatcodes/src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,10 @@ pub struct Cheatcodes {
/// This is set to `false`, once the startup migration is completed.
pub startup_zk: bool,

/// Factory deps stored through `zkUseFactoryDep`. These factory deps are used in the next
/// CREATE or CALL, and cleared after.
pub zk_use_factory_deps: Vec<String>,

/// The list of factory_deps seen so far during a test or script execution.
/// Ideally these would be persisted in the storage, but since modifying [revm::JournaledState]
/// would be a significant refactor, we maintain the factory_dep part in the [Cheatcodes].
Expand Down Expand Up @@ -667,6 +671,7 @@ impl Cheatcodes {
record_next_create_address: Default::default(),
persisted_factory_deps: Default::default(),
paymaster_params: None,
zk_use_factory_deps: Default::default(),
}
}

Expand Down Expand Up @@ -1037,7 +1042,16 @@ impl Cheatcodes {
paymaster: paymaster_data.address.to_h160(),
paymaster_input: paymaster_data.input.to_vec(),
});
if let Some(factory_deps) = zk_tx {
if let Some(mut factory_deps) = zk_tx {
let injected_factory_deps = self.zk_use_factory_deps.iter().map(|contract| {
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()
}).collect_vec();
factory_deps.extend(injected_factory_deps);
let mut batched =
foundry_zksync_core::vm::batch_factory_dependencies(factory_deps);
debug!(batches = batched.len(), "splitting factory deps for broadcast");
Expand Down Expand Up @@ -1635,6 +1649,16 @@ 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)
.inspect(|_| info!(contract, "pushing factory dep"))
.unwrap_or_else(|_| {
panic!("failed to get bytecode for factory deps contract {contract}")
})
.to_vec()
}).collect_vec();
factory_deps.extend(injected_factory_deps.clone());

let paymaster_params =
self.paymaster_params.clone().map(|paymaster_data| PaymasterParams {
paymaster: paymaster_data.address.to_h160(),
Expand All @@ -1648,7 +1672,8 @@ where {
})
} else {
Some(ZkTransactionMetadata {
factory_deps: Default::default(),
// For this case we use only the injected factory deps
factory_deps: injected_factory_deps,
paymaster_data: paymaster_params,
})
}
Expand Down
9 changes: 9 additions & 0 deletions crates/cheatcodes/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ impl Cheatcode for zkUsePaymasterCall {
}
}

impl Cheatcode for zkUseFactoryDepCall {
fn apply_stateful<DB: DatabaseExt>(&self, ccx: &mut CheatsCtxt<DB>) -> Result {
let Self { name } = self;
info!("Adding factory dependency: {:?}", name);
ccx.state.zk_use_factory_deps.push(name.clone());
Ok(Default::default())
}
}

impl Cheatcode for zkRegisterContractCall {
fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result {
let Self {
Expand Down
2 changes: 1 addition & 1 deletion crates/forge/tests/fixtures/zk/Create2.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ contract Create2Script is Script {
function run() external {
(bool success,) = address(vm).call(abi.encodeWithSignature("zkVm(bool)", true));
require(success, "zkVm() call failed");

vm.startBroadcast();

// Deploy Greeter using create2 with a salt
Expand Down
24 changes: 24 additions & 0 deletions crates/forge/tests/fixtures/zk/DeployCounterWithBytecodeHash.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "forge-std/Script.sol";
import "zksync-contracts/zksync-contracts/l2/system-contracts/libraries/SystemContractsCaller.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "../src/Factory.sol";

contract DeployCounterWithBytecodeHash is Script {
function run() external {
// Read artifact file and get the bytecode hash
string memory artifact = vm.readFile("zkout/Counter.sol/Counter.json");
bytes32 counterBytecodeHash = vm.parseJsonBytes32(artifact, ".hash");
bytes32 salt = "JUAN";

vm.startBroadcast();
Factory factory = new Factory(counterBytecodeHash);
(bool _success,) = address(vm).call(abi.encodeWithSignature("zkUseFactoryDep(string)", "Counter"));
require(_success, "Cheatcode failed");
address counter = factory.deployAccount(salt);
require(counter != address(0), "Counter deployment failed");
vm.stopBroadcast();
}
}
28 changes: 28 additions & 0 deletions crates/forge/tests/fixtures/zk/Factory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
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 {
bytes32 public aaBytecodeHash;

constructor(bytes32 _aaBytecodeHash) {
aaBytecodeHash = _aaBytecodeHash;
}

function deployAccount(bytes32 salt) 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)
)
);
require(success, "Deployment failed");

(accountAddress) = abi.decode(returnData, (address));
}
}
2 changes: 1 addition & 1 deletion crates/forge/tests/fixtures/zk/Paymaster.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ contract TestPaymasterFlow is Test {
vm.deal(address(do_stuff), 1 ether);
require(address(alice).balance == 0, "Balance is not 0 ether");
vm.prank(alice, alice);

do_stuff.do_stuff(bob);
}
}
Expand Down
43 changes: 40 additions & 3 deletions crates/forge/tests/it/zk/cheats.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
//! Forge tests for cheatcodes.
use crate::{config::*, test_helpers::TEST_DATA_DEFAULT};
use std::path::Path;

use crate::{
config::*,
test_helpers::{run_zk_script_test, TEST_DATA_DEFAULT},
};
use forge::revm::primitives::SpecId;
use foundry_config::fs_permissions::PathPermission;
use foundry_test_utils::Filter;
use foundry_config::{fs_permissions::PathPermission, Config, FsPermissions};
use foundry_test_utils::{forgetest_async, util, Filter, TestProject};

#[tokio::test(flavor = "multi_thread")]
async fn test_zk_cheat_roll_works() {
Expand Down Expand Up @@ -140,3 +145,35 @@ async fn test_zk_zk_vm_skip_works() {

TestConfig::with_filter(runner, filter).evm_spec(SpecId::SHANGHAI).run().await;
}

forgetest_async!(test_zk_use_factory_dep, |prj, cmd| {
setup_deploy_prj(&mut prj);

cmd.forge_fuse();
run_zk_script_test(
prj.root(),
&mut cmd,
"./script/DeployCounterWithBytecodeHash.s.sol",
"DeployCounterWithBytecodeHash",
Some("transmissions11/solmate@v7 OpenZeppelin/openzeppelin-contracts cyfrin/zksync-contracts"),
2,
Some(&["-vvvvv", "--via-ir", "--system-mode", "true"]),
);
});

fn setup_deploy_prj(prj: &mut TestProject) {
util::initialize(prj.root());
let permissions = FsPermissions::new(vec![
PathPermission::read(Path::new("zkout/Counter.sol/Counter.json")),
PathPermission::read(Path::new("zkout/Factory.sol/Factory.json")),
]);
let config = Config { fs_permissions: permissions, ..Default::default() };
prj.write_config(config);
prj.add_script(
"DeployCounterWithBytecodeHash.s.sol",
include_str!("../../fixtures/zk/DeployCounterWithBytecodeHash.s.sol"),
)
.unwrap();
prj.add_source("Factory.sol", include_str!("../../fixtures/zk/Factory.sol")).unwrap();
prj.add_source("Counter", "contract Counter {}").unwrap();
}
Loading

0 comments on commit 2915b7f

Please sign in to comment.