use primitives::{
eip4844::{
BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN, BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE,
MIN_BLOB_GASPRICE,
},
hardfork::SpecId,
};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BlobExcessGasAndPrice {
pub excess_blob_gas: u64,
pub blob_gasprice: u128,
}
impl BlobExcessGasAndPrice {
pub fn new(excess_blob_gas: u64, blob_base_fee_update_fraction: u64) -> Self {
let blob_gasprice = calc_blob_gasprice(excess_blob_gas, blob_base_fee_update_fraction);
Self {
excess_blob_gas,
blob_gasprice,
}
}
pub fn new_with_spec(excess_blob_gas: u64, spec: SpecId) -> Self {
Self::new(
excess_blob_gas,
if spec.is_enabled_in(SpecId::PRAGUE) {
BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE
} else {
BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN
},
)
}
}
#[inline]
pub fn calc_blob_gasprice(excess_blob_gas: u64, blob_base_fee_update_fraction: u64) -> u128 {
fake_exponential(
MIN_BLOB_GASPRICE,
excess_blob_gas,
blob_base_fee_update_fraction,
)
}
pub fn get_base_fee_per_blob_gas(excess_blob_gas: u64, blob_base_fee_update_fraction: u64) -> u128 {
calc_blob_gasprice(excess_blob_gas, blob_base_fee_update_fraction)
}
#[inline]
pub fn fake_exponential(factor: u64, numerator: u64, denominator: u64) -> u128 {
assert_ne!(denominator, 0, "attempt to divide by zero");
let factor = factor as u128;
let numerator = numerator as u128;
let denominator = denominator as u128;
let mut i = 1;
let mut output = 0;
let mut numerator_accum = factor * denominator;
while numerator_accum > 0 {
output += numerator_accum;
numerator_accum = (numerator_accum * numerator) / (denominator * i);
i += 1;
}
output / denominator
}
#[cfg(test)]
mod tests {
use super::*;
use primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN;
#[test]
fn fake_exp() {
for t @ &(factor, numerator, denominator, expected) in &[
(1u64, 0u64, 1u64, 1u128),
(38493, 0, 1000, 38493),
(0, 1234, 2345, 0),
(1, 2, 1, 6), (1, 4, 2, 6),
(1, 3, 1, 16), (1, 6, 2, 18),
(1, 4, 1, 49), (1, 8, 2, 50),
(10, 8, 2, 542), (11, 8, 2, 596), (1, 5, 1, 136), (1, 5, 2, 11), (2, 5, 2, 23), (1, 50000000, 2225652, 5709098764),
(1, 380928, BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN, 1),
] {
let actual = fake_exponential(factor, numerator, denominator);
assert_eq!(actual, expected, "test: {t:?}");
}
}
}