From 717449b0766a20ec6be4d04f54bb1a44a91fa790 Mon Sep 17 00:00:00 2001 From: Mablr <59505383+mablr@users.noreply.github.com> Date: Thu, 5 Jun 2025 10:21:40 +0200 Subject: [PATCH] feat(GasOracle): new function to compute median (#16645) Co-authored-by: Matthias Seitz --- crates/rpc/rpc-eth-types/src/gas_oracle.rs | 38 +++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/crates/rpc/rpc-eth-types/src/gas_oracle.rs b/crates/rpc/rpc-eth-types/src/gas_oracle.rs index 18e4e14aa2..27b23b54e4 100644 --- a/crates/rpc/rpc-eth-types/src/gas_oracle.rs +++ b/crates/rpc/rpc-eth-types/src/gas_oracle.rs @@ -272,8 +272,44 @@ where Ok(Some((parent_hash, prices))) } -} + /// Get the median tip value for the given block. This is useful for determining + /// tips when a block is at capacity. + /// + /// If the block cannot be found or has no transactions, this will return `None`. + pub async fn get_block_median_tip(&self, block_hash: B256) -> EthResult> { + // check the cache (this will hit the disk if the block is not cached) + let Some(block) = self.cache.get_recovered_block(block_hash).await? else { + return Ok(None) + }; + + let base_fee_per_gas = block.base_fee_per_gas(); + + // Filter, sort and collect the prices + let prices = block + .transactions_recovered() + .filter_map(|tx| { + if let Some(base_fee) = base_fee_per_gas { + (*tx).effective_tip_per_gas(base_fee) + } else { + Some((*tx).priority_fee_or_price()) + } + }) + .sorted() + .collect::>(); + + let median = if prices.is_empty() { + // if there are no prices, return `None` + None + } else if prices.len() % 2 == 1 { + Some(U256::from(prices[prices.len() / 2])) + } else { + Some(U256::from((prices[prices.len() / 2 - 1] + prices[prices.len() / 2]) / 2)) + }; + + Ok(median) + } +} /// Container type for mutable inner state of the [`GasPriceOracle`] #[derive(Debug)] struct GasPriceOracleInner {