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

fix: Add Paymaster Params to transact #728

Merged
merged 8 commits into from
Nov 20, 2024
9 changes: 8 additions & 1 deletion crates/evm/core/src/backend/cow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,19 @@ impl<'a> CowBackend<'a> {
env: &mut Env,
persisted_factory_deps: &mut HashMap<foundry_zksync_core::H256, Vec<u8>>,
factory_deps: Option<Vec<Vec<u8>>>,
paymaster_data: Option<foundry_zksync_core::PaymasterParams>,
) -> eyre::Result<ResultAndState> {
// this is a new call to inspect with a new env, so even if we've cloned the backend
// already, we reset the initialized state
self.is_initialized = false;

foundry_zksync_core::vm::transact(Some(persisted_factory_deps), factory_deps, env, self)
foundry_zksync_core::vm::transact(
Some(persisted_factory_deps),
factory_deps,
paymaster_data,
env,
self,
)
}

/// Executes the configured transaction of the `env` without committing state changes
Expand Down
9 changes: 8 additions & 1 deletion crates/evm/core/src/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,10 +840,17 @@ impl Backend {
env: &mut EnvWithHandlerCfg,
persisted_factory_deps: &mut HashMap<foundry_zksync_core::H256, Vec<u8>>,
factory_deps: Option<Vec<Vec<u8>>>,
paymaster_data: Option<foundry_zksync_core::PaymasterParams>,
) -> eyre::Result<ResultAndState> {
self.initialize(env);

foundry_zksync_core::vm::transact(Some(persisted_factory_deps), factory_deps, env, self)
foundry_zksync_core::vm::transact(
Some(persisted_factory_deps),
factory_deps,
paymaster_data,
env,
self,
)
}

/// Returns true if the address is a precompile
Expand Down
2 changes: 2 additions & 0 deletions crates/evm/evm/src/executors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ impl Executor {
&mut env,
&mut self.zk_persisted_factory_deps.clone(),
Some(zk_tx.factory_deps.clone()),
zk_tx.paymaster_data.clone(),
)?
}
};
Expand All @@ -464,6 +465,7 @@ impl Executor {
// no need to commit them later
&mut self.zk_persisted_factory_deps,
Some(zk_tx.factory_deps),
zk_tx.paymaster_data,
)?
}
};
Expand Down
40 changes: 40 additions & 0 deletions crates/forge/tests/fixtures/zk/Paymaster.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console} from "forge-std/Script.sol";
import {Greeter} from "../src/Greeter.sol";
import {MyPaymaster} from "../src/MyPaymaster.sol";

contract PaymasterScript is Script {
MyPaymaster private paymaster;
bytes private paymaster_encoded_input;
address private alice;

function run() public {
// random private key to get the address of alice with zero balance
alice = vm.rememberKey(0x60d80818010eb4826dc44d7342076a36978544fc89199061f452ea65d67e99e1);
require(address(alice).balance == 0, "Alice balance is not 0");

// We broadcast first to deploy the paymaster and fund it
vm.startBroadcast();
paymaster = new MyPaymaster();
(bool transferSuccess,) = address(paymaster).call{value: 10 ether}("");
require(transferSuccess, "Paymaster funding failed");
vm.stopBroadcast();

// Encode paymaster input
paymaster_encoded_input = abi.encodeWithSelector(bytes4(keccak256("general(bytes)")), bytes("0x"));

// We broadcast the transaction from alice's account to avoid having balance
vm.startBroadcast(alice);

(bool success,) = address(vm).call(
abi.encodeWithSignature("zkUsePaymaster(address,bytes)", address(paymaster), paymaster_encoded_input)
);
require(success, "zkUsePaymaster call failed");

Greeter greeter = new Greeter();

vm.stopBroadcast();
}
}
1 change: 0 additions & 1 deletion crates/forge/tests/it/test_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,6 @@ pub fn run_zk_script_test(
let mut script_args = vec![
"--zk-startup",
&script_path_contract,
"--broadcast",
"--private-key",
private_key,
"--chain",
Expand Down
2 changes: 1 addition & 1 deletion crates/forge/tests/it/zk/cheats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ forgetest_async!(test_zk_use_factory_dep, |prj, cmd| {
"DeployCounterWithBytecodeHash",
Some("transmissions11/solmate@v7 OpenZeppelin/openzeppelin-contracts cyfrin/zksync-contracts"),
2,
Some(&["-vvvvv", "--via-ir", "--system-mode", "true"]),
Some(&["-vvvvv", "--via-ir", "--system-mode", "true", "--broadcast"]),
);
});

Expand Down
2 changes: 1 addition & 1 deletion crates/forge/tests/it/zk/create2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ forgetest_async!(can_deploy_via_create2, |prj, cmd| {
"Create2Script",
None,
2,
Some(&["-vvvvv"]),
Some(&["-vvvvv", "--broadcast"]),
);
});

Expand Down
4 changes: 2 additions & 2 deletions crates/forge/tests/it/zk/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ forgetest_async!(multiple_deployments_of_the_same_contract, |prj, cmd| {
"DeployScript",
None,
3,
Some(&["-vvvvv"]),
Some(&["-vvvvv", "--broadcast"]),
);
run_zk_script_test(
prj.root(),
Expand All @@ -20,7 +20,7 @@ forgetest_async!(multiple_deployments_of_the_same_contract, |prj, cmd| {
"DeployScript",
None,
3,
Some(&["-vvvvv"]),
Some(&["-vvvvv", "--broadcast"]),
);
});

Expand Down
12 changes: 6 additions & 6 deletions crates/forge/tests/it/zk/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ forgetest_async!(script_zk_can_deploy_in_method, |prj, cmd| {
"ZkClassicFactoryScript",
None,
2,
None,
Some(&["--broadcast"]),
);
run_zk_script_test(
prj.root(),
Expand All @@ -57,7 +57,7 @@ forgetest_async!(script_zk_can_deploy_in_method, |prj, cmd| {
"ZkNestedFactoryScript",
None,
2,
None,
Some(&["--broadcast"]),
);
});

Expand All @@ -70,7 +70,7 @@ forgetest_async!(script_zk_can_deploy_in_constructor, |prj, cmd| {
"ZkConstructorFactoryScript",
None,
1,
None,
Some(&["--broadcast"]),
);
run_zk_script_test(
prj.root(),
Expand All @@ -79,7 +79,7 @@ forgetest_async!(script_zk_can_deploy_in_constructor, |prj, cmd| {
"ZkNestedConstructorFactoryScript",
None,
1,
None,
Some(&["--broadcast"]),
);
});

Expand All @@ -92,7 +92,7 @@ forgetest_async!(script_zk_can_use_predeployed_factory, |prj, cmd| {
"ZkUserFactoryScript",
None,
3,
None,
Some(&["--broadcast"]),
);
run_zk_script_test(
prj.root(),
Expand All @@ -101,7 +101,7 @@ forgetest_async!(script_zk_can_use_predeployed_factory, |prj, cmd| {
"ZkUserConstructorFactoryScript",
None,
2,
None,
Some(&["--broadcast"]),
);
});

Expand Down
2 changes: 1 addition & 1 deletion crates/forge/tests/it/zk/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ forgetest_async!(script_zk_can_deploy_nft, |prj, cmd| {
"MyScript",
Some("transmissions11/solmate@v7 OpenZeppelin/openzeppelin-contracts"),
1,
Some(&["-vvvvv"]),
Some(&["-vvvvv", "--broadcast"]),
);
});

Expand Down
29 changes: 28 additions & 1 deletion crates/forge/tests/it/zk/paymaster.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
//! Forge tests for zksync contracts.

use foundry_test_utils::util::{self, OutputExt};
use foundry_test_utils::{
forgetest_async,
util::{self, OutputExt},
TestProject,
};

use crate::test_helpers::run_zk_script_test;

#[tokio::test(flavor = "multi_thread")]
async fn test_zk_contract_paymaster() {
Expand Down Expand Up @@ -29,3 +35,24 @@ async fn test_zk_contract_paymaster() {
cmd.args(["test", "--zk-startup", "--via-ir", "--match-contract", "TestPaymasterFlow"]);
assert!(cmd.assert_success().get_output().stdout_lossy().contains("Suite result: ok"));
}

forgetest_async!(paymaster_script_test, |prj, cmd| {
setup_deploy_prj(&mut prj);
cmd.forge_fuse();
run_zk_script_test(
prj.root(),
&mut cmd,
"./script/Paymaster.s.sol",
"PaymasterScript",
Some("OpenZeppelin/openzeppelin-contracts cyfrin/zksync-contracts"),
3,
Some(&["-vvvvv", "--via-ir"]),
);
});

fn setup_deploy_prj(prj: &mut TestProject) {
util::initialize(prj.root());
prj.add_script("Paymaster.s.sol", include_str!("../../fixtures/zk/Paymaster.s.sol")).unwrap();
prj.add_source("MyPaymaster.sol", include_str!("../../fixtures/zk/MyPaymaster.sol")).unwrap();
prj.add_source("Greeter.sol", include_str!("../../../../../testdata/zk/Greeter.sol")).unwrap();
}
2 changes: 1 addition & 1 deletion crates/forge/tests/it/zk/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ forgetest_async!(script_zk_can_deploy_proxy, |prj, cmd| {
"ProxyScript",
Some("OpenZeppelin/openzeppelin-contracts"),
4,
None,
Some(&["--broadcast"]),
);
});

Expand Down
2 changes: 1 addition & 1 deletion crates/zksync/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub use zksync_types::{
};
use zksync_types::{utils::storage_key_for_eth_balance, U256};
pub use zksync_utils::bytecode::hash_bytecode;
use zksync_web3_rs::{
pub use zksync_web3_rs::{
eip712::{Eip712Meta, Eip712Transaction, Eip712TransactionRequest, PaymasterParams},
zks_provider::types::Fee,
zks_utils::EIP712_TX_TYPE,
Expand Down
12 changes: 10 additions & 2 deletions crates/zksync/core/src/vm/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::{
pub fn transact<'a, DB>(
persisted_factory_deps: Option<&'a mut HashMap<H256, Vec<u8>>>,
factory_deps: Option<Vec<Vec<u8>>>,
paymaster_data: Option<zksync_web3_rs::eip712::PaymasterParams>,
env: &'a mut Env,
db: &'a mut DB,
) -> eyre::Result<ResultAndState>
Expand All @@ -37,6 +38,13 @@ where
{
info!(calldata = ?env.tx.data, fdeps = factory_deps.as_ref().map(|deps| deps.iter().map(|dep| dep.len()).join(",")).unwrap_or_default(), "zk transact");

let paymaster_params = PaymasterParams {
paymaster: paymaster_data.as_ref().map_or_else(Default::default, |data| data.paymaster),
paymaster_input: paymaster_data
.as_ref()
.map_or_else(Vec::new, |data| data.paymaster_input.to_vec()),
};

let mut ecx = EvmContext::new_with_env(db, Box::new(env.clone()));
let caller = env.tx.caller;
let nonce = ZKVMData::new(&mut ecx).get_tx_nonce(caller);
Expand All @@ -45,7 +53,7 @@ where
TransactTo::Create => (CONTRACT_DEPLOYER_ADDRESS, true),
};

let (gas_limit, max_fee_per_gas) = gas_params(&mut ecx, caller, &PaymasterParams::default());
let (gas_limit, max_fee_per_gas) = gas_params(&mut ecx, caller, &paymaster_params);
debug!(?gas_limit, ?max_fee_per_gas, "tx gas parameters");
let tx = L2Tx::new(
Some(transact_to),
Expand All @@ -60,7 +68,7 @@ where
caller.to_h160(),
env.tx.value.to_u256(),
factory_deps.unwrap_or_default(),
PaymasterParams::default(),
paymaster_params,
);

let call_ctx = CallContext {
Expand Down