Skip to content

Commit

Permalink
Pass down priority and max fee per gas for broadcasting script txs
Browse files Browse the repository at this point in the history
  • Loading branch information
Jrigada committed Jan 15, 2025
1 parent 1b49d91 commit 6961fc6
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 7 deletions.
2 changes: 1 addition & 1 deletion crates/cast/bin/cmd/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ async fn cast_send_zk<P: Provider<T, AnyNetwork>, Z: ZksyncProvider<T>, T: Trans
zk_tx.set_paymaster_params(paymaster_params);
}

foundry_zksync_core::estimate_gas(&mut zk_tx, &zk_provider).await?;
foundry_zksync_core::estimate_gas(&mut zk_tx, &zk_provider, 130).await?;

let cast = ZkCast::new(zk_provider, Cast::new(provider));
let pending_tx = cast.send_zk(zk_tx).await?;
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 @@ -692,7 +692,7 @@ impl CreateArgs {
deployer.tx.set_gas_price(gas_price);

// estimate fee
foundry_zksync_core::estimate_gas(&mut deployer.tx, &provider).await?;
foundry_zksync_core::estimate_gas(&mut deployer.tx, &provider, 130).await?;

if !is_legacy {
let estimate = provider.estimate_eip1559_fees(None).await.wrap_err("Failed to estimate EIP1559 fees. This chain might not support EIP1559, try adding --legacy to your command.")?;
Expand Down
13 changes: 13 additions & 0 deletions crates/forge/tests/fixtures/zk/Gas.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

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

contract GasScript is Script {
function run() public {
vm.startBroadcast();
Greeter greeter = new Greeter();
vm.stopBroadcast();
}
}
69 changes: 69 additions & 0 deletions crates/forge/tests/it/zk/gas.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use foundry_test_utils::{forgetest_async, util, TestProject};

use foundry_test_utils::{util::OutputExt, ZkSyncNode};

forgetest_async!(script_execution_with_gas_price, |prj, cmd| {
setup_gas_prj(&mut prj);

let node = ZkSyncNode::start().await;
let url = node.url();

cmd.forge_fuse();

let private_key =
ZkSyncNode::rich_wallets().next().map(|(_, pk, _)| pk).expect("No rich wallets available");

let script_args = vec![
"--zk-startup",
"./script/Gas.s.sol",
"--private-key",
&private_key,
"--chain",
"260",
"--rpc-url",
url.as_str(),
"--slow",
"--evm-version",
"shanghai",
"-vvvvv",
"--broadcast",
"--with-gas-price",
"370000037",
"--priority-gas-price",
"123123",
];

cmd.arg("script").args(&script_args);

let stdout = cmd.assert_success().get_output().stdout_lossy();
assert!(stdout.contains("ONCHAIN EXECUTION COMPLETE & SUCCESSFUL"));

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(&foundry_common::fs::read_to_string(run_latest).unwrap()).unwrap();

assert_eq!(json["transactions"].as_array().expect("broadcastable txs").len(), 1);

let transaction_hash = json["receipts"][0]["transactionHash"].as_str().unwrap();
let stdout = cmd
.cast_fuse()
.arg("tx")
.arg(transaction_hash)
.arg("--rpc-url")
.arg(url.as_str())
.assert_success()
.get_output()
.stdout_lossy();

assert!(stdout.contains("maxFeePerGas 370000037"));
assert!(stdout.contains("maxPriorityFeePerGas 123123"));
});

fn setup_gas_prj(prj: &mut TestProject) {
util::initialize(prj.root());
prj.add_script("Gas.s.sol", include_str!("../../fixtures/zk/Gas.s.sol")).unwrap();
prj.add_source("Greeter.sol", include_str!("../../../../../testdata/zk/Greeter.sol")).unwrap();
}
1 change: 1 addition & 0 deletions crates/forge/tests/it/zk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod factory;
mod factory_deps;
mod fork;
mod fuzz;
mod gas;
mod invariant;
mod linking;
mod logs;
Expand Down
20 changes: 18 additions & 2 deletions crates/script/src/broadcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ pub async fn send_transaction(
},
);
}
foundry_zksync_core::estimate_gas(&mut zk_tx, &zk_provider).await?;
foundry_zksync_core::estimate_gas(&mut zk_tx, &zk_provider, estimate_multiplier)
.await?;

let zk_signer = alloy_zksync::wallet::ZksyncWallet::new(signer.default_signer());
let signed = zk_tx.build(&zk_signer).await?.encoded_2718();
Expand Down Expand Up @@ -317,7 +318,15 @@ impl BundledState {
self.args.with_gas_price,
self.args.priority_gas_price,
) {
(true, Some(gas_price), _) => (Some(gas_price.to()), None),
(true, Some(gas_price), priority_fee) => (
Some(gas_price.to()),
// NOTE(zk): Zksync is marked as legacy in alloy chains but it is compliant
// with EIP-1559 so we need to pass down the user provided values
priority_fee.map(|fee| Eip1559Estimation {
max_fee_per_gas: gas_price.to(),
max_priority_fee_per_gas: fee.to(),
}),
),
(true, None, _) => (Some(provider.get_gas_price().await?), None),
(false, Some(max_fee_per_gas), Some(max_priority_fee_per_gas)) => (
None,
Expand Down Expand Up @@ -367,6 +376,13 @@ impl BundledState {

if let Some(gas_price) = gas_price {
tx.set_gas_price(gas_price);
// NOTE(zk): Also set EIP-1559 fees for zk transactions
if let Some(eip1559_fees) = eip1559_fees {
tx.set_max_priority_fee_per_gas(
eip1559_fees.max_priority_fee_per_gas,
);
tx.set_max_fee_per_gas(eip1559_fees.max_fee_per_gas);
}
} else {
let eip1559_fees = eip1559_fees.expect("was set above");
tx.set_max_priority_fee_per_gas(
Expand Down
14 changes: 11 additions & 3 deletions crates/zksync/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,19 @@ pub struct EstimatedGas {
pub async fn estimate_gas<P: ZksyncProvider<T>, T: Transport + Clone>(
tx: &mut ZkTransactionRequest,
provider: P,
estimate_multiplier: u64,
) -> Result<()> {
let fee = provider.estimate_fee(tx.clone()).await?;
tx.set_gas_limit(fee.gas_limit);
tx.set_max_fee_per_gas(fee.max_fee_per_gas);
tx.set_max_priority_fee_per_gas(fee.max_priority_fee_per_gas);
tx.set_gas_limit(fee.gas_limit * estimate_multiplier / 100);
// If user provided a gas price, use it for both maxFeePerGas
let max_fee = tx
.max_fee_per_gas()
.map_or(fee.max_fee_per_gas * (estimate_multiplier as u128) / 100, |price| price);
let max_priority_fee = tx
.max_priority_fee_per_gas()
.map_or(fee.max_priority_fee_per_gas * (estimate_multiplier as u128) / 100, |price| price);
tx.set_max_fee_per_gas(max_fee);
tx.set_max_priority_fee_per_gas(max_priority_fee);
tx.set_gas_per_pubdata(fee.gas_per_pubdata_limit);

Ok(())
Expand Down

0 comments on commit 6961fc6

Please sign in to comment.