use alloy::{network::Ethereum, primitives::U256, providers::Provider};
use anyhow::{Context, Result};
use tracing::info;
#[derive(Debug, Clone)]
pub struct AdjustedGasPrices {
pub max_priority_fee_per_gas: Option<U256>,
pub max_fee_per_gas: Option<U256>,
}
#[tracing::instrument(skip(provider), fields(
provided_max_priority_fee_per_gas = ?provided_max_priority_fee_per_gas,
provided_max_fee_per_gas = ?provided_max_fee_per_gas,
buffer_multiplier = buffer_multiplier
))]
pub async fn adjust_gas_prices<P: Provider<Ethereum> + ?Sized>(
provider: &P,
provided_max_priority_fee_per_gas: Option<U256>,
provided_max_fee_per_gas: Option<U256>,
buffer_multiplier: u64,
) -> Result<AdjustedGasPrices> {
let fee_estimate =
provider.estimate_eip1559_fees().await.context("Failed to estimate EIP-1559 fees")?;
let current_max_priority_fee = U256::from(fee_estimate.max_priority_fee_per_gas);
let current_max_fee = U256::from(fee_estimate.max_fee_per_gas);
let buffer_multiplier_u256 = U256::from(buffer_multiplier);
let base_multiplier = U256::from(100u64);
let adjusted_max_priority_fee =
(current_max_priority_fee * buffer_multiplier_u256) / base_multiplier;
let adjusted_max_fee = (current_max_fee * buffer_multiplier_u256) / base_multiplier;
info!(
current_max_priority_fee_per_gas = ?current_max_priority_fee,
current_max_fee_per_gas = ?current_max_fee,
adjusted_max_priority_fee_per_gas = ?adjusted_max_priority_fee,
adjusted_max_fee_per_gas = ?adjusted_max_fee,
provided_max_priority_fee_per_gas = ?provided_max_priority_fee_per_gas,
provided_max_fee_per_gas = ?provided_max_fee_per_gas,
buffer_multiplier = buffer_multiplier,
"Fetched and adjusted current gas price estimates"
);
let max_priority_fee_per_gas = match provided_max_priority_fee_per_gas {
Some(provided) => {
let final_fee = if provided > adjusted_max_priority_fee {
provided
} else {
adjusted_max_priority_fee
};
info!(
final_max_priority_fee_per_gas = ?final_fee,
"Using higher of provided ({:?}) or adjusted current ({:?}) priority fee",
provided, adjusted_max_priority_fee
);
Some(final_fee)
}
None => {
info!(
max_priority_fee_per_gas = ?adjusted_max_priority_fee,
"Using dynamically adjusted current priority fee estimate"
);
Some(adjusted_max_priority_fee)
}
};
let max_fee_per_gas = match provided_max_fee_per_gas {
Some(provided) => {
let final_fee = if provided > adjusted_max_fee { provided } else { adjusted_max_fee };
info!(
final_max_fee_per_gas = ?final_fee,
"Using higher of provided ({:?}) or adjusted current ({:?}) max fee",
provided, adjusted_max_fee
);
Some(final_fee)
}
None => {
info!(
max_fee_per_gas = ?adjusted_max_fee,
"Using dynamically adjusted current max fee estimate"
);
Some(adjusted_max_fee)
}
};
Ok(AdjustedGasPrices { max_priority_fee_per_gas, max_fee_per_gas })
}