alloy_eips/
eip7840.rs

1//! Contains constants and utility functions for [EIP-7840](https://github.com/ethereum/EIPs/tree/master/EIPS/eip-7840.md)
2
3use crate::{
4    eip4844::{self, DATA_GAS_PER_BLOB},
5    eip7594, eip7691,
6};
7
8/// Configuration for the blob-related calculations.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[cfg_attr(
12    feature = "serde",
13    serde(from = "serde_impl::SerdeHelper", into = "serde_impl::SerdeHelper")
14)]
15pub struct BlobParams {
16    /// Target blob count for the block.
17    pub target_blob_count: u64,
18    /// Max blob count for the block.
19    pub max_blob_count: u64,
20    /// Update fraction for excess blob gas calculation.
21    pub update_fraction: u128,
22    /// Minimum gas price for a data blob.
23    ///
24    /// Not required per EIP-7840 and assumed to be the default
25    /// [`eip4844::BLOB_TX_MIN_BLOB_GASPRICE`] if not set.
26    pub min_blob_fee: u128,
27    /// Maximum number of blobs per transaction.
28    ///
29    /// If not specified, defaults to `max_blob_count` during deserialization.
30    pub max_blobs_per_tx: u64,
31}
32
33impl BlobParams {
34    /// Returns [`BlobParams`] configuration activated with Cancun hardfork.
35    pub const fn cancun() -> Self {
36        Self {
37            target_blob_count: eip4844::TARGET_BLOBS_PER_BLOCK_DENCUN,
38            max_blob_count: eip4844::MAX_BLOBS_PER_BLOCK_DENCUN as u64,
39            update_fraction: eip4844::BLOB_GASPRICE_UPDATE_FRACTION,
40            min_blob_fee: eip4844::BLOB_TX_MIN_BLOB_GASPRICE,
41            max_blobs_per_tx: eip4844::MAX_BLOBS_PER_BLOCK_DENCUN as u64,
42        }
43    }
44
45    /// Returns [`BlobParams`] configuration activated with Prague hardfork.
46    pub const fn prague() -> Self {
47        Self {
48            target_blob_count: eip7691::TARGET_BLOBS_PER_BLOCK_ELECTRA,
49            max_blob_count: eip7691::MAX_BLOBS_PER_BLOCK_ELECTRA,
50            update_fraction: eip7691::BLOB_GASPRICE_UPDATE_FRACTION_PECTRA,
51            min_blob_fee: eip4844::BLOB_TX_MIN_BLOB_GASPRICE,
52            max_blobs_per_tx: eip7691::MAX_BLOBS_PER_BLOCK_ELECTRA,
53        }
54    }
55
56    /// Returns [`BlobParams`] configuration activated with Osaka hardfork.
57    pub const fn osaka() -> Self {
58        Self {
59            target_blob_count: eip7691::TARGET_BLOBS_PER_BLOCK_ELECTRA,
60            max_blob_count: eip7691::MAX_BLOBS_PER_BLOCK_ELECTRA,
61            update_fraction: eip7691::BLOB_GASPRICE_UPDATE_FRACTION_PECTRA,
62            min_blob_fee: eip4844::BLOB_TX_MIN_BLOB_GASPRICE,
63            max_blobs_per_tx: eip7594::MAX_BLOBS_PER_TX_FUSAKA,
64        }
65    }
66
67    /// Returns the maximum available blob gas in a block.
68    ///
69    /// This is `max blob count * DATA_GAS_PER_BLOB`
70    pub const fn max_blob_gas_per_block(&self) -> u64 {
71        self.max_blob_count * DATA_GAS_PER_BLOB
72    }
73
74    /// Returns the blob gas target per block.
75    ///
76    /// This is `target blob count * DATA_GAS_PER_BLOB`
77    pub const fn target_blob_gas_per_block(&self) -> u64 {
78        self.target_blob_count * DATA_GAS_PER_BLOB
79    }
80
81    /// Calculates the `excess_blob_gas` value for the next block based on the current block
82    /// `excess_blob_gas` and `blob_gas_used`.
83    #[inline]
84    pub const fn next_block_excess_blob_gas(
85        &self,
86        excess_blob_gas: u64,
87        blob_gas_used: u64,
88    ) -> u64 {
89        (excess_blob_gas + blob_gas_used)
90            .saturating_sub(eip4844::DATA_GAS_PER_BLOB * self.target_blob_count)
91    }
92
93    /// Calculates the blob fee for block based on its `excess_blob_gas`.
94    #[inline]
95    pub const fn calc_blob_fee(&self, excess_blob_gas: u64) -> u128 {
96        eip4844::fake_exponential(self.min_blob_fee, excess_blob_gas as u128, self.update_fraction)
97    }
98}
99
100#[cfg(feature = "serde")]
101mod serde_impl {
102    use crate::{eip4844, eip7840::BlobParams};
103
104    #[derive(serde::Serialize, serde::Deserialize, Clone, Copy)]
105    #[serde(rename_all = "camelCase")]
106    pub(crate) struct SerdeHelper {
107        #[serde(rename = "target")]
108        target_blob_count: u64,
109        #[serde(rename = "max")]
110        max_blob_count: u64,
111        #[serde(rename = "baseFeeUpdateFraction")]
112        update_fraction: u128,
113        min_blob_fee: Option<u128>,
114        max_blobs_per_tx: Option<u64>,
115    }
116
117    impl From<BlobParams> for SerdeHelper {
118        fn from(params: BlobParams) -> Self {
119            let BlobParams {
120                target_blob_count,
121                max_blob_count,
122                update_fraction,
123                min_blob_fee,
124                max_blobs_per_tx,
125            } = params;
126
127            Self {
128                target_blob_count,
129                max_blob_count,
130                update_fraction,
131                min_blob_fee: (min_blob_fee != eip4844::BLOB_TX_MIN_BLOB_GASPRICE)
132                    .then_some(min_blob_fee),
133                max_blobs_per_tx: Some(max_blobs_per_tx),
134            }
135        }
136    }
137
138    impl From<SerdeHelper> for BlobParams {
139        fn from(helper: SerdeHelper) -> Self {
140            let SerdeHelper {
141                target_blob_count,
142                max_blob_count,
143                update_fraction,
144                min_blob_fee,
145                max_blobs_per_tx,
146            } = helper;
147
148            Self {
149                target_blob_count,
150                max_blob_count,
151                update_fraction,
152                min_blob_fee: min_blob_fee.unwrap_or(eip4844::BLOB_TX_MIN_BLOB_GASPRICE),
153                max_blobs_per_tx: max_blobs_per_tx.unwrap_or(max_blob_count),
154            }
155        }
156    }
157}