1use crate::{
4 eip4844::{self, DATA_GAS_PER_BLOB},
5 eip7594, eip7691,
6};
7
8#[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 pub target_blob_count: u64,
18 pub max_blob_count: u64,
20 pub update_fraction: u128,
22 pub min_blob_fee: u128,
27 pub max_blobs_per_tx: u64,
31}
32
33impl BlobParams {
34 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 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 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 pub const fn max_blob_gas_per_block(&self) -> u64 {
71 self.max_blob_count * DATA_GAS_PER_BLOB
72 }
73
74 pub const fn target_blob_gas_per_block(&self) -> u64 {
78 self.target_blob_count * DATA_GAS_PER_BLOB
79 }
80
81 #[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 #[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}