Skip to content

Commit

Permalink
feat: Paymaster support in Forge create (#609)
Browse files Browse the repository at this point in the history
paymaster support in forge create
  • Loading branch information
Jrigada authored Oct 15, 2024
1 parent cbd6940 commit 902f992
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 5 deletions.
1 change: 1 addition & 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/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ foundry-config.workspace = true
foundry-debugger.workspace = true
foundry-evm.workspace = true
foundry-wallets.workspace = true
zksync-web3-rs.workspace = true

foundry-compilers = { workspace = true, features = ["full"] }

Expand Down
17 changes: 17 additions & 0 deletions crates/cli/src/opts/build/zksync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::path::PathBuf;
use clap::Parser;
use foundry_config::ZkSyncConfig;
use serde::Serialize;
use zksync_web3_rs::types::{Address, Bytes};

#[derive(Clone, Debug, Default, Serialize, Parser)]
#[clap(next_help_heading = "ZKSync configuration")]
Expand Down Expand Up @@ -104,6 +105,22 @@ pub struct ZkSyncArgs {
/// Contracts to avoid compiling on zkSync
#[clap(long = "zk-avoid-contracts", visible_alias = "avoid-contracts", value_delimiter = ',')]
pub avoid_contracts: Option<Vec<String>>,

/// Paymaster address
#[clap(
long = "zk-paymaster-address",
value_name = "PAYMASTER_ADDRESS",
visible_alias = "paymaster-address"
)]
pub paymaster_address: Option<Address>,

/// Paymaster input
#[clap(
long = "zk-paymaster-input",
value_name = "PAYMASTER_INPUT",
visible_alias = "paymaster-input"
)]
pub paymaster_input: Option<Bytes>,
}

impl ZkSyncArgs {
Expand Down
35 changes: 31 additions & 4 deletions crates/forge/bin/cmd/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use std::{
sync::Arc,
};
use zksync_types::H256;
use zksync_web3_rs::eip712::PaymasterParams;

merge_impl_figment_convert!(CreateArgs, opts, eth);

Expand Down Expand Up @@ -114,6 +115,7 @@ pub struct ZkSyncData {
bytecode: Vec<u8>,
bytecode_hash: H256,
factory_deps: Vec<Vec<u8>>,
paymaster_params: Option<PaymasterParams>,
}

impl CreateArgs {
Expand All @@ -125,6 +127,22 @@ impl CreateArgs {

let zksync = self.opts.compiler.zk.enabled();
if zksync {
let paymaster_params =
if let Some(paymaster_address) = self.opts.compiler.zk.paymaster_address {
Some(PaymasterParams {
paymaster: paymaster_address,
paymaster_input: self
.opts
.compiler
.zk
.paymaster_input
.clone()
.unwrap_or_default()
.to_vec(),
})
} else {
None
};
let target_path = if let Some(ref mut path) = self.contract.path {
canonicalize(project.root().join(path))?
} else {
Expand Down Expand Up @@ -223,7 +241,7 @@ impl CreateArgs {
visited_bytecodes.insert(bytecode.clone());
visited_bytecodes.into_iter().collect()
};
let zk_data = ZkSyncData { bytecode, bytecode_hash, factory_deps };
let zk_data = ZkSyncData { bytecode, bytecode_hash, factory_deps, paymaster_params };

let result = if self.unlocked {
// Deploy with unlocked account
Expand Down Expand Up @@ -555,7 +573,7 @@ impl CreateArgs {
let is_args_empty = args.is_empty();
let mut deployer =
factory.deploy_tokens_zk(args.clone(), &zk_data).context("failed to deploy contract")
.map(|deployer| deployer.set_zk_factory_deps(zk_data.factory_deps.clone())).map_err(|e| {
.map(|deployer| deployer.set_zk_factory_deps(zk_data.factory_deps.clone()).set_zk_paymaster_params(zk_data.paymaster_params.clone())).map_err(|e| {
if is_args_empty {
e.wrap_err("no arguments provided for contract constructor; consider --constructor-args or --constructor-args-path")
} else {
Expand Down Expand Up @@ -777,6 +795,7 @@ pub struct Deployer<B, P, T> {
confs: usize,
timeout: u64,
zk_factory_deps: Option<Vec<Vec<u8>>>,
zk_paymaster_params: Option<PaymasterParams>,
_p: PhantomData<P>,
_t: PhantomData<T>,
}
Expand All @@ -793,6 +812,7 @@ where
confs: self.confs,
timeout: self.timeout,
zk_factory_deps: self.zk_factory_deps.clone(),
zk_paymaster_params: self.zk_paymaster_params.clone(),
_p: PhantomData,
_t: PhantomData,
}
Expand All @@ -811,6 +831,12 @@ where
self
}

/// Set zksync's paymaster params.
pub fn set_zk_paymaster_params(mut self, params: Option<PaymasterParams>) -> Self {
self.zk_paymaster_params = params;
self
}

/// Broadcasts the zk contract deployment transaction and after waiting for it to
/// be sufficiently confirmed (default: 1), it returns a tuple with
/// the [`Contract`](crate::Contract) struct at the deployed contract's address
Expand All @@ -823,12 +849,12 @@ where
let tx = foundry_zksync_core::new_eip712_transaction(
self.tx,
factory_deps,
self.zk_paymaster_params.clone(),
self.client.borrow(),
signer.expect("No signer was found"),
)
.await
.map_err(|_| ContractDeploymentError::ContractNotDeployed)?;

let receipt = self
.client
.borrow()
Expand Down Expand Up @@ -975,6 +1001,7 @@ where
confs: 1,
timeout: self.timeout,
zk_factory_deps: None,
zk_paymaster_params: None,
_p: PhantomData,
_t: PhantomData,
})
Expand Down Expand Up @@ -1012,14 +1039,14 @@ where
.to(foundry_zksync_core::CONTRACT_DEPLOYER_ADDRESS.to_address())
.input(data.into()),
);

Ok(Deployer {
client: self.client.clone(),
abi: self.abi,
tx,
confs: 1,
timeout: self.timeout,
zk_factory_deps: Some(vec![zk_data.bytecode.clone()]),
zk_paymaster_params: zk_data.paymaster_params.clone(),
_p: PhantomData,
_t: PhantomData,
})
Expand Down
6 changes: 5 additions & 1 deletion crates/zksync/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pub async fn new_eip712_transaction<
>(
tx: WithOtherFields<TransactionRequest>,
factory_deps: Vec<Vec<u8>>,
paymaster_data: Option<PaymasterParams>,
provider: P,
signer: S,
) -> Result<Bytes> {
Expand All @@ -126,7 +127,10 @@ pub async fn new_eip712_transaction<
let gas_price = tx.gas_price.ok_or_eyre("`gas_price` cannot be empty")?;

let data = tx.input.clone().into_input().unwrap_or_default();
let custom_data = Eip712Meta::new().factory_deps(factory_deps);
let mut custom_data = Eip712Meta::new().factory_deps(factory_deps);
if let Some(params) = paymaster_data {
custom_data = custom_data.paymaster_params(params);
}

let mut deploy_request = Eip712TransactionRequest::new()
.r#type(EIP712_TX_TYPE)
Expand Down

0 comments on commit 902f992

Please sign in to comment.