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: update run with dynamic fee params #377

Merged
merged 10 commits into from
Nov 11, 2024
25 changes: 14 additions & 11 deletions e2e-tests/test/zks-apis.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface Fee {
}

describe("zks_estimateFee", function () {
it("Should return fee estimation data for transfer of 1 ETH", async function () {
it("Should return valid fee estimation data for transfer of 1 ETH", async function () {
// Arrange
const wallet = new Wallet(RichAccounts[0].PrivateKey, provider);
const userWallet = Wallet.createRandom().connect(provider);
Expand All @@ -29,17 +29,20 @@ describe("zks_estimateFee", function () {

// Act
const response: Fee = await provider.send("zks_estimateFee", [transaction]);

// Assert
expect(ethers.BigNumber.from(response.gas_limit).toNumber()).to.eql(4048728, "Unexpected gas_limit");
expect(ethers.BigNumber.from(response.gas_per_pubdata_limit)).to.eql(
ethers.BigNumber.from("50000"),
"Unexpected gas_per_pubdata_limit"
);
expect(ethers.BigNumber.from(response.max_fee_per_gas).toNumber()).to.eql(37500000, "Unexpected max_fee_per_gas");
expect(ethers.BigNumber.from(response.max_priority_fee_per_gas)).to.eql(
ethers.BigNumber.from("0"),
"Unexpected max_priority_fee_per_gas"
);
expect(response).to.have.property("gas_limit");
expect(response).to.have.property("gas_per_pubdata_limit");
expect(response).to.have.property("max_fee_per_gas");
expect(response).to.have.property("max_priority_fee_per_gas");

const gasLimit = ethers.BigNumber.from(response.gas_limit);
const gasPerPubdataLimit = ethers.BigNumber.from(response.gas_per_pubdata_limit);
const maxFeePerGas = ethers.BigNumber.from(response.max_fee_per_gas);

expect(gasLimit.toNumber()).to.be.greaterThan(0, "gas_limit should be greater than 0");
expect(gasPerPubdataLimit.toNumber()).to.be.greaterThan(0, "gas_per_pubdata_limit should be greater than 0");
expect(maxFeePerGas.toNumber()).to.be.greaterThan(0, "max_fee_per_gas should be greater than 0");
});
});

Expand Down
7 changes: 6 additions & 1 deletion src/config/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ pub struct Cli {
/// Use a given chain id. If not set uses 260 (or the one from the forked network).
#[arg(long)]
pub chain_id: Option<u32>,

/// Run the node in offline mode. This will disable all network requests.
/// Can only be run alongside `run` command.
#[arg(long)]
pub offline: bool,
}

#[derive(Debug, Subcommand)]
Expand All @@ -125,7 +130,7 @@ pub struct ForkArgs {
/// If not set - will start a new network from genesis.
/// If set - will try to fork a remote network. Possible values:
/// - mainnet
/// - testnet
/// - sepolia-testnet
/// - http://XXX:YY
pub network: String,
// Fork at a given L2 miniblock height.
Expand Down
14 changes: 7 additions & 7 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,15 +301,13 @@ pub mod node {
pub mod gas {
use serde::Deserialize;

/// L1 Gas Price.
pub const DEFAULT_L1_GAS_PRICE: u64 = 50_000_000_000;
// TODO: for now, that's fine, as computation overhead is set to zero, but we may consider using calculated fee input everywhere.
pub const DEFAULT_L1_GAS_PRICE: u64 = 14_932_364_075;
/// The default L2 Gas Price to be used if not supplied via the CLI argument.
pub const DEFAULT_L2_GAS_PRICE: u64 = 25_000_000;
// Default fair pubdata price based on an average from Sepolia Testnet blocks
pub const DEFAULT_FAIR_PUBDATA_PRICE: u64 = 450_000_000_000;
pub const DEFAULT_L2_GAS_PRICE: u64 = 45_250_000;
/// Default fair pubdata price based on the provided value.
pub const DEFAULT_FAIR_PUBDATA_PRICE: u64 = 13_607_659_111;
/// L1 Gas Price Scale Factor for gas estimation.
pub const DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR: f64 = 1.5;
pub const DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR: f64 = 2.0;
/// The factor by which to scale the gasLimit.
pub const DEFAULT_ESTIMATE_GAS_SCALE_FACTOR: f32 = 1.3;

Expand All @@ -319,6 +317,8 @@ pub mod gas {
pub l1_gas_price: Option<u64>,
/// L2 gas price.
pub l2_gas_price: Option<u64>,
/// Fair pubdata price.
pub l1_pubdata_price: Option<u64>,
/// Factors used in estimating gas.
pub estimation: Option<Estimation>,
}
Expand Down
6 changes: 3 additions & 3 deletions src/fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ impl ForkNetwork {
ForkNetwork::Other(url) => url,
}
}

// TODO: This needs to be dynamic based on the network.
/// Returns the local gas scale factors currently in use by the upstream network.
pub fn local_gas_scale_factors(&self) -> (f64, f32) {
match self {
ForkNetwork::Mainnet => (1.5, 1.2),
ForkNetwork::SepoliaTestnet => (2.0, 1.2),
ForkNetwork::Mainnet => (1.5, 1.4),
ForkNetwork::SepoliaTestnet => (2.0, 1.3),
ForkNetwork::GoerliTestnet => (1.2, 1.2),
ForkNetwork::Other(_) => (
DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR,
Expand Down
45 changes: 43 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ use bytecode_override::override_bytecodes;
use clap::Parser;
use colored::Colorize;
use config::cli::{Cli, Command};
use config::gas::{
Estimation, GasConfig, DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR,
DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
};
use config::TestNodeConfig;
use fork::{ForkDetails, ForkSource};
use http_fork_source::HttpForkSource;
Expand Down Expand Up @@ -31,13 +35,14 @@ mod testing;
mod utils;

use node::InMemoryNode;

use std::fs::File;
use std::{
env,
net::{IpAddr, Ipv4Addr, SocketAddr},
str::FromStr,
};
use zksync_types::fee_model::FeeParams;
use zksync_web3_decl::namespaces::ZksNamespaceClient;

use futures::{
channel::oneshot,
Expand Down Expand Up @@ -118,7 +123,43 @@ async fn main() -> anyhow::Result<()> {
// Use `Command::Run` as default.
let command = opt.command.as_ref().unwrap_or(&Command::Run);
let fork_details = match command {
Command::Run => None,
Command::Run => {
if opt.offline {
tracing::warn!(
"Running in offline mode: default fee parameters will be used. \
To override, specify values in `config.toml` and use the `--config` flag."
);
None
} else {
// Initialize the client to get the fee params
let (_, client) = ForkDetails::fork_network_and_client("mainnet")
.map_err(|e| anyhow!("Failed to initialize client: {:?}", e))?;

let fee = client.get_fee_params().await.map_err(|e| {
tracing::error!("Failed to fetch fee params: {:?}", e);
anyhow!(e)
})?;

let gas_config = match fee {
FeeParams::V2(fee_v2) => GasConfig {
l1_gas_price: Some(fee_v2.l1_gas_price()),
l2_gas_price: Some(fee_v2.config().minimal_l2_gas_price),
l1_pubdata_price: Some(fee_v2.l1_pubdata_price()),
estimation: Some(Estimation {
price_scale_factor: Some(DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR),
limit_scale_factor: Some(DEFAULT_ESTIMATE_GAS_SCALE_FACTOR),
}),
},
FeeParams::V1(_) => {
return Err(anyhow!("Unsupported FeeParams::V1 in this context"))
}
};

config.gas = Some(gas_config);

None
}
}
Command::Fork(fork) => {
match ForkDetails::from_network(&fork.network, fork.fork_block_number, config.cache)
.await
Expand Down
2 changes: 1 addition & 1 deletion src/node/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2400,7 +2400,7 @@ mod tests {
.await
.expect("failed getting filter changes")
{
FilterChanges::Logs(result) => assert_eq!(3, result.len()),
FilterChanges::Logs(result) => assert_eq!(4, result.len()),
changes => panic!("unexpected filter changes: {:?}", changes),
}

Expand Down
24 changes: 8 additions & 16 deletions src/node/fee_model.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use zksync_types::fee_model::{BatchFeeInput, FeeModelConfigV2, FeeParams, FeeParamsV2};
use zksync_types::L1_GAS_PER_PUBDATA_BYTE;

use crate::config::gas::{
GasConfig, DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR, DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
DEFAULT_L1_GAS_PRICE, DEFAULT_L2_GAS_PRICE,
DEFAULT_FAIR_PUBDATA_PRICE, DEFAULT_L1_GAS_PRICE, DEFAULT_L2_GAS_PRICE,
};
use crate::utils::to_human_size;

#[derive(Debug, Clone, PartialEq)]
pub struct TestNodeFeeInputProvider {
pub l1_gas_price: u64,
Expand Down Expand Up @@ -63,19 +60,14 @@ impl TestNodeFeeInputProvider {
};

if let Some(l1_gas_price) = gas_config.l1_gas_price {
tracing::info!(
"L1 gas price set to {} (overridden from {})",
to_human_size(l1_gas_price.into()),
to_human_size(self.l1_gas_price.into())
);
self.l1_gas_price = l1_gas_price;
}

if let Some(l1_pubdata_price) = gas_config.l1_pubdata_price {
self.l1_pubdata_price = l1_pubdata_price;
}

if let Some(l2_gas_price) = gas_config.l2_gas_price {
tracing::info!(
"L2 gas price set to {} (overridden from {})",
to_human_size(l2_gas_price.into()),
to_human_size(self.l2_gas_price.into())
);
self.l2_gas_price = l2_gas_price;
}

Expand Down Expand Up @@ -126,13 +118,13 @@ impl Default for TestNodeFeeInputProvider {
fn default() -> Self {
Self {
l1_gas_price: DEFAULT_L1_GAS_PRICE,
l1_pubdata_price: DEFAULT_L1_GAS_PRICE * L1_GAS_PER_PUBDATA_BYTE as u64,
l1_pubdata_price: DEFAULT_FAIR_PUBDATA_PRICE,
l2_gas_price: DEFAULT_L2_GAS_PRICE,
compute_overhead_part: 0.0,
pubdata_overhead_part: 1.0,
batch_overhead_l1_gas: 800000,
max_gas_per_batch: 200000000,
max_pubdata_per_batch: 100000,
max_pubdata_per_batch: 500000,
estimate_gas_price_scale_factor: DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR,
estimate_gas_scale_factor: DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
}
Expand Down
1 change: 1 addition & 0 deletions src/node/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,7 @@ impl<S: ForkSource + std::fmt::Debug + Clone> InMemoryNode<S> {
Ok(GasConfig {
l1_gas_price: Some(fee_input_provider.l1_gas_price),
l2_gas_price: Some(fee_input_provider.l2_gas_price),
l1_pubdata_price: Some(fee_input_provider.l1_pubdata_price),
estimation: Some(gas::Estimation {
price_scale_factor: Some(fee_input_provider.estimate_gas_price_scale_factor),
limit_scale_factor: Some(fee_input_provider.estimate_gas_scale_factor),
Expand Down
6 changes: 3 additions & 3 deletions src/node/zks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,10 +625,10 @@ mod tests {

let result = node.estimate_fee(mock_request).await.unwrap();

assert_eq!(result.gas_limit, U256::from(4490368));
assert_eq!(result.max_fee_per_gas, U256::from(37500000));
assert_eq!(result.gas_limit, U256::from(279779));
assert_eq!(result.max_fee_per_gas, U256::from(45250000));
assert_eq!(result.max_priority_fee_per_gas, U256::from(0));
assert_eq!(result.gas_per_pubdata_limit, U256::from(50000));
assert_eq!(result.gas_per_pubdata_limit, U256::from(1658));
}

#[tokio::test]
Expand Down
Loading