Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion crates/driver/src/infra/blockchain/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,25 @@ impl GasPriceEstimator {
)
};

// Add headroom on top of the estimate so a base-fee increase between
// submission and inclusion does not strand the tx below the new base
// fee. max_fee_per_gas is a ceiling, not the amount paid.
let factor_as_bps = self.adjustments.max_fee_per_gas_factor * 10000.0;
let suggested_max_fee_per_gas = eth::U256::from(estimate.max_fee_per_gas)
.checked_mul(eth::U256::from(factor_as_bps as u128))
.ok_or_else(|| {
Error::GasPrice(anyhow!(
"overflow on multiplication (max_fee_per_gas * max_fee_per_gas_factor)"
))
})?
/ eth::U256::from(10000u128);

// make sure the used max fee per gas is at least big enough to cover
// the tip - otherwise the tx will be rejected by the node
// immediately
let suggested_max_fee_per_gas = eth::U256::from(estimate.max_fee_per_gas);
let suggested_max_fee_per_gas =
std::cmp::max(suggested_max_fee_per_gas, max_priority_fee_per_gas);

if suggested_max_fee_per_gas > self.adjustments.max_fee_per_gas {
return Err(Error::GasPrice(anyhow::anyhow!(
"suggested gas price is higher than maximum allowed gas price (network is too \
Expand Down Expand Up @@ -123,6 +136,9 @@ pub struct GasPriceParameters {
max_fee_per_gas: eth::U256,
/// We'll always tip at least this value for `max_priority_fee_per_gas`.
min_priority_fee: eth::U256,
/// The `max_fee_per_gas` suggested by the estimator gets multiplied with
/// this factor to leave headroom for a base-fee increase before inclusion.
max_fee_per_gas_factor: f64,
}

pub fn adjustments(mempools: &[mempool::Config]) -> GasPriceParameters {
Expand All @@ -133,19 +149,22 @@ pub fn adjustments(mempools: &[mempool::Config]) -> GasPriceParameters {
let mut additional_tip_percentage = 0.0f64;
let mut max_fee_per_gas = eth::U256::MAX;
let mut min_priority_fee = eth::U256::ZERO;
let mut max_fee_per_gas_factor = 1.0f64;

for mempool in mempools {
max_additional_tip = max_additional_tip.max(mempool.max_additional_tip);
additional_tip_percentage =
additional_tip_percentage.max(mempool.additional_tip_percentage);
max_fee_per_gas = max_fee_per_gas.min(mempool.gas_price_cap);
min_priority_fee = min_priority_fee.max(mempool.min_priority_fee);
max_fee_per_gas_factor = max_fee_per_gas_factor.max(mempool.max_fee_per_gas_factor);
}

GasPriceParameters {
max_additional_tip,
additional_tip_factor: additional_tip_percentage,
max_fee_per_gas,
min_priority_fee,
max_fee_per_gas_factor,
}
}
1 change: 1 addition & 0 deletions crates/driver/src/infra/config/file/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ pub async fn load(chain: Chain, path: &Path) -> infra::Config {
.map(|(index, mempool)| mempool::Config {
min_priority_fee: config.submission.min_priority_fee,
gas_price_cap: config.submission.gas_price_cap,
max_fee_per_gas_factor: config.submission.max_fee_per_gas_factor,
target_confirm_time: config.submission.target_confirm_time,
retry_interval: config.submission.retry_interval,
nonce_block_number: config.submission.nonce_block_number.map(Into::into),
Expand Down
10 changes: 10 additions & 0 deletions crates/driver/src/infra/config/file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ struct SubmissionConfig {
#[serde_as(as = "serde_ext::U256")]
gas_price_cap: eth::U256,

/// Factor applied to the estimated `max_fee_per_gas` to leave headroom for
/// a base-fee increase between submission and inclusion.
#[serde(default = "default_max_fee_per_gas_factor")]
max_fee_per_gas_factor: f64,

/// The target confirmation time for settlement transactions used
/// to estimate gas price.
#[serde(with = "humantime_serde", default = "default_target_confirm_time")]
Expand Down Expand Up @@ -213,6 +218,11 @@ fn default_gas_price_cap() -> eth::U256 {
eth::U256::from(1000) * eth::U256::from(10).pow(eth::U256::from(9))
}

/// No headroom over the estimated `max_fee_per_gas` by default.
fn default_max_fee_per_gas_factor() -> f64 {
1.0
}

fn default_target_confirm_time() -> Duration {
Duration::from_secs(30)
}
Expand Down
2 changes: 2 additions & 0 deletions crates/driver/src/infra/mempool/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use {
pub struct Config {
pub min_priority_fee: eth::U256,
pub gas_price_cap: eth::U256,
pub max_fee_per_gas_factor: f64,
pub target_confirm_time: std::time::Duration,
pub retry_interval: std::time::Duration,
/// Optional block number to use when fetching nonces. If None, uses the
Expand All @@ -40,6 +41,7 @@ impl Config {
Self {
min_priority_fee: Default::default(),
gas_price_cap: eth::U256::from(1000000000000_u128),
max_fee_per_gas_factor: 1.,
target_confirm_time: Default::default(),
retry_interval: Default::default(),
name: "default_rpc".to_string(),
Expand Down
Loading