mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-27 08:08:15 -05:00
feat(gas_oracle): implement median-based priority fee suggestion for Optimism (#16794)
This commit is contained in:
@@ -244,9 +244,8 @@ where
|
||||
}
|
||||
|
||||
async fn suggested_priority_fee(&self) -> Result<U256, Self::Error> {
|
||||
let base_tip = self.inner.eth_api.gas_oracle().suggest_tip_cap().await?;
|
||||
let min_tip = U256::from(self.inner.min_suggested_priority_fee);
|
||||
Ok(base_tip.max(min_tip))
|
||||
self.inner.eth_api.gas_oracle().op_suggest_tip_cap(min_tip).await.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//! previous blocks.
|
||||
|
||||
use super::{EthApiError, EthResult, EthStateCache, RpcInvalidTransactionError};
|
||||
use alloy_consensus::{constants::GWEI_TO_WEI, BlockHeader, Transaction};
|
||||
use alloy_consensus::{constants::GWEI_TO_WEI, BlockHeader, Transaction, TxReceipt};
|
||||
use alloy_eips::BlockNumberOrTag;
|
||||
use alloy_primitives::{B256, U256};
|
||||
use alloy_rpc_types_eth::BlockId;
|
||||
@@ -273,6 +273,78 @@ where
|
||||
Ok(Some((parent_hash, prices)))
|
||||
}
|
||||
|
||||
/// Suggests a max priority fee value using a simplified and more predictable algorithm
|
||||
/// appropriate for chains like Optimism with a single known block builder.
|
||||
///
|
||||
/// It returns either:
|
||||
/// - The minimum suggested priority fee when blocks have capacity
|
||||
/// - 10% above the median effective priority fee from the last block when at capacity
|
||||
///
|
||||
/// A block is considered at capacity if its total gas used plus the maximum single transaction
|
||||
/// gas would exceed the block's gas limit.
|
||||
pub async fn op_suggest_tip_cap(&self, min_suggested_priority_fee: U256) -> EthResult<U256> {
|
||||
let header = self
|
||||
.provider
|
||||
.sealed_header_by_number_or_tag(BlockNumberOrTag::Latest)?
|
||||
.ok_or(EthApiError::HeaderNotFound(BlockId::latest()))?;
|
||||
|
||||
let mut inner = self.inner.lock().await;
|
||||
|
||||
// if we have stored a last price, then we check whether or not it was for the same head
|
||||
if inner.last_price.block_hash == header.hash() {
|
||||
return Ok(inner.last_price.price);
|
||||
}
|
||||
|
||||
let mut suggestion = min_suggested_priority_fee;
|
||||
|
||||
// find the maximum gas used by any of the transactions in the block to use as the
|
||||
// capacity margin for the block, if no receipts are found return the
|
||||
// suggested_min_priority_fee
|
||||
let Some(max_tx_gas_used) = self
|
||||
.cache
|
||||
.get_receipts(header.hash())
|
||||
.await?
|
||||
.ok_or(EthApiError::ReceiptsNotFound(BlockId::latest()))?
|
||||
// get the gas used by each transaction in the block, by subtracting the
|
||||
// cumulative gas used of the previous transaction from the cumulative gas used of the
|
||||
// current transaction. This is because there is no gas_used() method on the Receipt
|
||||
// trait.
|
||||
.windows(2)
|
||||
.map(|window| {
|
||||
let prev = window[0].cumulative_gas_used();
|
||||
let curr = window[1].cumulative_gas_used();
|
||||
curr - prev
|
||||
})
|
||||
.max()
|
||||
else {
|
||||
return Ok(suggestion);
|
||||
};
|
||||
|
||||
// if the block is at capacity, the suggestion must be increased
|
||||
if header.gas_used() + max_tx_gas_used > header.gas_limit() {
|
||||
let Some(median_tip) = self.get_block_median_tip(header.hash()).await? else {
|
||||
return Ok(suggestion);
|
||||
};
|
||||
|
||||
let new_suggestion = median_tip + median_tip / U256::from(10);
|
||||
|
||||
if new_suggestion > suggestion {
|
||||
suggestion = new_suggestion;
|
||||
}
|
||||
}
|
||||
|
||||
// constrain to the max price
|
||||
if let Some(max_price) = self.oracle_config.max_price {
|
||||
if suggestion > max_price {
|
||||
suggestion = max_price;
|
||||
}
|
||||
}
|
||||
|
||||
inner.last_price = GasPriceOracleResult { block_hash: header.hash(), price: suggestion };
|
||||
|
||||
Ok(suggestion)
|
||||
}
|
||||
|
||||
/// Get the median tip value for the given block. This is useful for determining
|
||||
/// tips when a block is at capacity.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user