From d4a8ef92d7856a689ffc3243c6144dd7a3edeff5 Mon Sep 17 00:00:00 2001 From: Rupam Dey <117000803+rupam-04@users.noreply.github.com> Date: Tue, 16 Apr 2024 03:28:54 +0530 Subject: [PATCH] refactor: replace ```calculate_next_block_base_fee``` with alloy's builtin function (#7641) Co-authored-by: Matthias Seitz --- crates/primitives/src/basefee.rs | 279 +++++++++------------- crates/primitives/src/header.rs | 12 +- crates/rpc/rpc/src/eth/api/fee_history.rs | 12 +- crates/rpc/rpc/src/eth/api/fees.rs | 14 +- crates/rpc/rpc/src/eth/api/server.rs | 43 ++-- 5 files changed, 153 insertions(+), 207 deletions(-) diff --git a/crates/primitives/src/basefee.rs b/crates/primitives/src/basefee.rs index 442cb6640..fb5ca7571 100644 --- a/crates/primitives/src/basefee.rs +++ b/crates/primitives/src/basefee.rs @@ -1,168 +1,111 @@ -//! Helpers for working with EIP-1559 base fee - -/// Calculate the base fee for the next block based on the EIP-1559 specification. -/// -/// This function calculates the base fee for the next block according to the rules defined in the -/// EIP-1559. EIP-1559 introduces a new transaction pricing mechanism that includes a -/// fixed-per-block network fee that is burned and dynamically adjusts block sizes to handle -/// transient congestion. -/// -/// For each block, the base fee per gas is determined by the gas used in the parent block and the -/// target gas (the block gas limit divided by the elasticity multiplier). The algorithm increases -/// the base fee when blocks are congested and decreases it when they are under the target gas -/// usage. The base fee per gas is always burned. -/// -/// Parameters: -/// - `gas_used`: The gas used in the current block. -/// - `gas_limit`: The gas limit of the current block. -/// - `base_fee`: The current base fee per gas. -/// - `base_fee_params`: Base fee parameters such as elasticity multiplier and max change -/// denominator. -/// -/// Returns: -/// The calculated base fee for the next block as a `u64`. -/// -/// For more information, refer to the [EIP-1559 spec](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md). -pub fn calculate_next_block_base_fee( - gas_used: u64, - gas_limit: u64, - base_fee: u64, - base_fee_params: crate::BaseFeeParams, -) -> u64 { - // Calculate the target gas by dividing the gas limit by the elasticity multiplier. - let gas_target = gas_limit / base_fee_params.elasticity_multiplier as u64; - - match gas_used.cmp(&gas_target) { - // If the gas used in the current block is equal to the gas target, the base fee remains the - // same (no increase). - std::cmp::Ordering::Equal => base_fee, - // If the gas used in the current block is greater than the gas target, calculate a new - // increased base fee. - std::cmp::Ordering::Greater => { - // Calculate the increase in base fee based on the formula defined by EIP-1559. - base_fee + - (std::cmp::max( - // Ensure a minimum increase of 1. - 1, - base_fee as u128 * (gas_used - gas_target) as u128 / - (gas_target as u128 * base_fee_params.max_change_denominator), - ) as u64) - } - // If the gas used in the current block is less than the gas target, calculate a new - // decreased base fee. - std::cmp::Ordering::Less => { - // Calculate the decrease in base fee based on the formula defined by EIP-1559. - base_fee.saturating_sub( - (base_fee as u128 * (gas_target - gas_used) as u128 / - (gas_target as u128 * base_fee_params.max_change_denominator)) - as u64, - ) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[cfg(feature = "optimism")] - use crate::chain::{OP_BASE_FEE_PARAMS, OP_SEPOLIA_BASE_FEE_PARAMS}; - - #[test] - fn calculate_base_fee_success() { - let base_fee = [ - 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, - 1, 2, - ]; - let gas_used = [ - 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, - 10000000, - ]; - let gas_limit = [ - 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, - 18000000, 18000000, - ]; - let next_base_fee = [ - 1125000000, 1083333333, 1053571428, 1179939062, 1116028649, 918084097, 1063811730, 1, - 2, 3, - ]; - - for i in 0..base_fee.len() { - assert_eq!( - next_base_fee[i], - calculate_next_block_base_fee( - gas_used[i], - gas_limit[i], - base_fee[i], - crate::BaseFeeParams::ethereum(), - ) - ); - } - } - - #[cfg(feature = "optimism")] - #[test] - fn calculate_optimism_base_fee_success() { - let base_fee = [ - 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, - 1, 2, - ]; - let gas_used = [ - 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, - 10000000, - ]; - let gas_limit = [ - 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, - 18000000, 18000000, - ]; - let next_base_fee = [ - 1100000048, 1080000000, 1065714297, 1167067046, 1128881311, 1028254188, 1098203452, 1, - 2, 3, - ]; - - for i in 0..base_fee.len() { - assert_eq!( - next_base_fee[i], - calculate_next_block_base_fee( - gas_used[i], - gas_limit[i], - base_fee[i], - OP_BASE_FEE_PARAMS, - ) - ); - } - } - - #[cfg(feature = "optimism")] - #[test] - fn calculate_optimism_sepolia_base_fee_success() { - let base_fee = [ - 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, - 1, 2, - ]; - let gas_used = [ - 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, - 10000000, - ]; - let gas_limit = [ - 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, - 18000000, 18000000, - ]; - let next_base_fee = [ - 1180000000, 1146666666, 1122857142, 1244299375, 1189416692, 1028254188, 1144836295, 1, - 2, 3, - ]; - - for i in 0..base_fee.len() { - assert_eq!( - next_base_fee[i], - calculate_next_block_base_fee( - gas_used[i], - gas_limit[i], - base_fee[i], - OP_SEPOLIA_BASE_FEE_PARAMS, - ) - ); - } - } -} +//! Helpers for working with EIP-1559 base fee + +// re-export +#[doc(inline)] +pub use alloy_eips::eip1559::calc_next_block_base_fee; + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg(feature = "optimism")] + use crate::chain::{OP_BASE_FEE_PARAMS, OP_SEPOLIA_BASE_FEE_PARAMS}; + + #[test] + fn calculate_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1125000000, 1083333333, 1053571428, 1179939062, 1116028649, 918084097, 1063811730, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + crate::BaseFeeParams::ethereum(), + ) as u64 + ); + } + } + + #[cfg(feature = "optimism")] + #[test] + fn calculate_optimism_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1100000048, 1080000000, 1065714297, 1167067046, 1128881311, 1028254188, 1098203452, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + OP_BASE_FEE_PARAMS, + ) as u64 + ); + } + } + + #[cfg(feature = "optimism")] + #[test] + fn calculate_optimism_sepolia_base_fee_success() { + let base_fee = [ + 1000000000, 1000000000, 1000000000, 1072671875, 1059263476, 1049238967, 1049238967, 0, + 1, 2, + ]; + let gas_used = [ + 10000000, 10000000, 10000000, 9000000, 10001000, 0, 10000000, 10000000, 10000000, + 10000000, + ]; + let gas_limit = [ + 10000000, 12000000, 14000000, 10000000, 14000000, 2000000, 18000000, 18000000, + 18000000, 18000000, + ]; + let next_base_fee = [ + 1180000000, 1146666666, 1122857142, 1244299375, 1189416692, 1028254188, 1144836295, 1, + 2, 3, + ]; + + for i in 0..base_fee.len() { + assert_eq!( + next_base_fee[i], + calc_next_block_base_fee( + gas_used[i] as u128, + gas_limit[i] as u128, + base_fee[i] as u128, + OP_SEPOLIA_BASE_FEE_PARAMS, + ) as u64 + ); + } + } +} diff --git a/crates/primitives/src/header.rs b/crates/primitives/src/header.rs index f12dc3d59..3846679dc 100644 --- a/crates/primitives/src/header.rs +++ b/crates/primitives/src/header.rs @@ -1,7 +1,7 @@ #[cfg(any(test, feature = "arbitrary"))] use crate::block::{generate_valid_header, valid_header_strategy}; use crate::{ - basefee::calculate_next_block_base_fee, + basefee::calc_next_block_base_fee, constants, constants::{ ALLOWED_FUTURE_BLOCK_TIME_SECONDS, EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH, @@ -247,12 +247,12 @@ impl Header { /// /// Returns a `None` if no base fee is set, no EIP-1559 support pub fn next_block_base_fee(&self, base_fee_params: BaseFeeParams) -> Option { - Some(calculate_next_block_base_fee( - self.gas_used, - self.gas_limit, - self.base_fee_per_gas?, + Some(calc_next_block_base_fee( + self.gas_used as u128, + self.gas_limit as u128, + self.base_fee_per_gas? as u128, base_fee_params, - )) + ) as u64) } /// Calculate excess blob gas for the next block according to the EIP-4844 spec. diff --git a/crates/rpc/rpc/src/eth/api/fee_history.rs b/crates/rpc/rpc/src/eth/api/fee_history.rs index 1d62a4aa1..4029dc7f9 100644 --- a/crates/rpc/rpc/src/eth/api/fee_history.rs +++ b/crates/rpc/rpc/src/eth/api/fee_history.rs @@ -7,7 +7,7 @@ use futures::{ }; use metrics::atomics::AtomicU64; use reth_primitives::{ - basefee::calculate_next_block_base_fee, + basefee::calc_next_block_base_fee, eip4844::{calc_blob_gasprice, calculate_excess_blob_gas}, ChainSpec, Receipt, SealedBlock, TransactionSigned, B256, }; @@ -370,12 +370,12 @@ impl FeeHistoryEntry { /// Returns the base fee for the next block according to the EIP-1559 spec. pub fn next_block_base_fee(&self, chain_spec: &ChainSpec) -> u64 { - calculate_next_block_base_fee( - self.gas_used, - self.gas_limit, - self.base_fee_per_gas, + calc_next_block_base_fee( + self.gas_used as u128, + self.gas_limit as u128, + self.base_fee_per_gas as u128, chain_spec.base_fee_params(self.timestamp), - ) + ) as u64 } /// Returns the blob fee for the next block according to the EIP-4844 spec. diff --git a/crates/rpc/rpc/src/eth/api/fees.rs b/crates/rpc/rpc/src/eth/api/fees.rs index 9b7445a2f..d93b83d89 100644 --- a/crates/rpc/rpc/src/eth/api/fees.rs +++ b/crates/rpc/rpc/src/eth/api/fees.rs @@ -9,7 +9,7 @@ use crate::{ }; use reth_evm::ConfigureEvm; use reth_network_api::NetworkInfo; -use reth_primitives::{basefee::calculate_next_block_base_fee, BlockNumberOrTag, U256}; +use reth_primitives::{BlockNumberOrTag, U256}; use reth_provider::{BlockReaderIdExt, ChainSpecProvider, EvmEnvProvider, StateProviderFactory}; use reth_rpc_types::FeeHistory; use reth_transaction_pool::TransactionPool; @@ -187,12 +187,12 @@ where // // The unwrap is safe since we checked earlier that we got at least 1 header. let last_header = headers.last().expect("is present"); - base_fee_per_gas.push(calculate_next_block_base_fee( - last_header.gas_used, - last_header.gas_limit, - last_header.base_fee_per_gas.unwrap_or_default(), - self.provider().chain_spec().base_fee_params(last_header.timestamp), - ) as u128); + base_fee_per_gas.push( + self.provider().chain_spec().base_fee_params(last_header.timestamp).next_block_base_fee( + last_header.gas_used as u128, + last_header.gas_limit as u128, + last_header.base_fee_per_gas.unwrap_or_default() as u128, + )); // Same goes for the `base_fee_per_blob_gas`: // > "[..] includes the next block after the newest of the returned range, because this value can be derived from the newest block. diff --git a/crates/rpc/rpc/src/eth/api/server.rs b/crates/rpc/rpc/src/eth/api/server.rs index d51c2bf94..6be1a88af 100644 --- a/crates/rpc/rpc/src/eth/api/server.rs +++ b/crates/rpc/rpc/src/eth/api/server.rs @@ -1,16 +1,10 @@ //! Implementation of the [`jsonrpsee`] generated [`reth_rpc_api::EthApiServer`] trait //! Handles RPC requests for the `eth_` namespace. -use super::EthApiSpec; -use crate::{ - eth::{ - api::{EthApi, EthTransactions}, - error::EthApiError, - revm_utils::EvmOverrides, - }, - result::{internal_rpc_err, ToRpcResult}, -}; use jsonrpsee::core::RpcResult as Result; +use serde_json::Value; +use tracing::trace; + use reth_evm::ConfigureEvm; use reth_network_api::NetworkInfo; use reth_primitives::{ @@ -28,8 +22,17 @@ use reth_rpc_types::{ StateContext, SyncStatus, TransactionRequest, Work, }; use reth_transaction_pool::TransactionPool; -use serde_json::Value; -use tracing::trace; + +use crate::{ + eth::{ + api::{EthApi, EthTransactions}, + error::EthApiError, + revm_utils::EvmOverrides, + }, + result::{internal_rpc_err, ToRpcResult}, +}; + +use super::EthApiSpec; #[async_trait::async_trait] impl EthApiServer for EthApi @@ -435,6 +438,8 @@ where #[cfg(test)] mod tests { + use jsonrpsee::types::error::INVALID_PARAMS_CODE; + use crate::{ eth::{ cache::EthStateCache, gas_oracle::GasPriceOracle, FeeHistoryCache, @@ -442,13 +447,12 @@ mod tests { }, EthApi, }; - use jsonrpsee::types::error::INVALID_PARAMS_CODE; use reth_evm_ethereum::EthEvmConfig; use reth_interfaces::test_utils::{generators, generators::Rng}; use reth_network_api::noop::NoopNetwork; use reth_primitives::{ - basefee::calculate_next_block_base_fee, constants::ETHEREUM_BLOCK_GAS_LIMIT, BaseFeeParams, - Block, BlockNumberOrTag, Header, TransactionSigned, B256, + constants::ETHEREUM_BLOCK_GAS_LIMIT, BaseFeeParams, Block, BlockNumberOrTag, Header, + TransactionSigned, B256, }; use reth_provider::{ test_utils::{MockEthProvider, NoopProvider}, @@ -565,12 +569,11 @@ mod tests { // Add final base fee (for the next block outside of the request) let last_header = last_header.unwrap(); - base_fees_per_gas.push(calculate_next_block_base_fee( - last_header.gas_used, - last_header.gas_limit, - last_header.base_fee_per_gas.unwrap_or_default(), - BaseFeeParams::ethereum(), - ) as u128); + base_fees_per_gas.push(BaseFeeParams::ethereum().next_block_base_fee( + last_header.gas_used as u128, + last_header.gas_limit as u128, + last_header.base_fee_per_gas.unwrap_or_default() as u128, + )); let eth_api = build_test_eth_api(mock_provider);