diff --git a/client/rpc/src/eth/fee.rs b/client/rpc/src/eth/fee.rs index e3c20fb20a..5b4b0e4ae6 100644 --- a/client/rpc/src/eth/fee.rs +++ b/client/rpc/src/eth/fee.rs @@ -72,7 +72,9 @@ where .await? { let Ok(number) = self.client.expect_block_number_from_id(&id) else { - return Err(internal_err(format!("Failed to retrieve block number at {id}"))); + return Err(internal_err(format!( + "Failed to retrieve block number at {id}" + ))); }; // Highest and lowest block number within the requested range. let highest = UniqueSaturatedInto::::unique_saturated_into(number); diff --git a/frame/base-fee/src/lib.rs b/frame/base-fee/src/lib.rs index 46df021b78..fd10fc6bd1 100644 --- a/frame/base-fee/src/lib.rs +++ b/frame/base-fee/src/lib.rs @@ -177,7 +177,18 @@ pub mod pallet { let decrease = scaled_basefee .checked_div(U256::from(1_000_000)) .unwrap_or_else(U256::zero); - *bf = bf.saturating_sub(decrease); + let default_base_fee = T::DefaultBaseFeePerGas::get(); + // lowest fee is norm(DefaultBaseFeePerGas * Threshold::ideal()): + let lowest_base_fee = default_base_fee + .checked_mul(U256::from(T::Threshold::ideal().deconstruct())) + .unwrap_or(default_base_fee) + .checked_div(U256::from(1_000_000)) + .unwrap_or(default_base_fee); + if bf.saturating_sub(decrease) >= lowest_base_fee { + *bf = bf.saturating_sub(decrease); + } else { + *bf = lowest_base_fee; + } } else { Self::deposit_event(Event::BaseFeeOverflow); } diff --git a/frame/base-fee/src/tests.rs b/frame/base-fee/src/tests.rs index b204643025..2182543e8b 100644 --- a/frame/base-fee/src/tests.rs +++ b/frame/base-fee/src/tests.rs @@ -33,6 +33,7 @@ use sp_runtime::{ use super::*; use crate as pallet_base_fee; +use crate::BaseFeeThreshold as BaseFeeThresholdT; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -75,7 +76,7 @@ parameter_types! { } pub struct BaseFeeThreshold; -impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold { +impl BaseFeeThresholdT for BaseFeeThreshold { fn lower() -> Permill { Permill::zero() } @@ -132,6 +133,15 @@ pub fn new_test_ext(base_fee: Option, elasticity: Option) -> Test TestExternalities::new(t) } +pub fn get_lowest_base_fee() -> U256 { + let default_base_fee = DefaultBaseFeePerGas::get(); + default_base_fee + .checked_mul(U256::from(BaseFeeThreshold::ideal().deconstruct())) + .unwrap_or(default_base_fee) + .checked_div(U256::from(1_000_000)) + .unwrap_or(default_base_fee) +} + #[test] fn should_default() { new_test_ext(None, None).execute_with(|| { @@ -158,12 +168,11 @@ fn should_not_overflow_u256() { } #[test] -fn should_handle_zero() { +fn should_fallback_to_default_value() { let base_fee = U256::zero(); new_test_ext(Some(base_fee), None).execute_with(|| { - let init = BaseFeePerGas::::get(); BaseFee::on_finalize(System::block_number()); - assert_eq!(BaseFeePerGas::::get(), init); + assert_eq!(BaseFeePerGas::::get(), get_lowest_base_fee()); }); } @@ -175,11 +184,7 @@ fn should_handle_consecutive_empty_blocks() { BaseFee::on_finalize(System::block_number()); System::set_block_number(System::block_number() + 1); } - assert_eq!( - BaseFeePerGas::::get(), - // 8 is the lowest number which's 12.5% is >= 1. - U256::from(7) - ); + assert_eq!(BaseFeePerGas::::get(), get_lowest_base_fee()); }); let zero_elasticity = Permill::zero(); new_test_ext(Some(base_fee), Some(zero_elasticity)).execute_with(|| {