1mod error;
2mod gas_constraint;
3mod model;
4mod multi_gas_constraint;
5mod multi_gas_fees;
6
7use alloy_primitives::U256;
8use arb_primitives::multigas::NUM_RESOURCE_KIND;
9use arb_storage::{
10 Storage, StorageBackedBigUint, StorageBackedUint64, StorageBackend, SubStorageVector,
11 SystemStateBackend, open_sub_storage_vector,
12};
13pub use error::L2PricingError;
14pub use gas_constraint::{GasConstraint, open_gas_constraint};
15pub use model::*;
16pub use multi_gas_constraint::{MultiGasConstraint, open_multi_gas_constraint};
17pub use multi_gas_fees::MultiGasFees;
18
19pub const SPEED_LIMIT_PER_SECOND_OFFSET: u64 = 0;
21pub const PER_BLOCK_GAS_LIMIT_OFFSET: u64 = 1;
22pub const BASE_FEE_WEI_OFFSET: u64 = 2;
23pub const MIN_BASE_FEE_WEI_OFFSET: u64 = 3;
24pub const GAS_BACKLOG_OFFSET: u64 = 4;
25pub const PRICING_INERTIA_OFFSET: u64 = 5;
26pub const BACKLOG_TOLERANCE_OFFSET: u64 = 6;
27pub const PER_TX_GAS_LIMIT_OFFSET: u64 = 7;
28
29const GAS_CONSTRAINTS_KEY: &[u8] = &[0];
31const MULTI_GAS_CONSTRAINTS_KEY: &[u8] = &[1];
32const MULTI_GAS_BASE_FEES_KEY: &[u8] = &[2];
33
34pub const GETH_BLOCK_GAS_LIMIT: u64 = 1 << 50;
36pub const GAS_CONSTRAINTS_MAX_NUM: u64 = 20;
37pub const MAX_PRICING_EXPONENT_BIPS: u64 = 85_000;
38
39pub const STORAGE_READ_COST: u64 = 800; pub const STORAGE_WRITE_COST: u64 = 20_000; pub const INITIAL_SPEED_LIMIT_PER_SECOND_V0: u64 = 1_000_000;
45pub const INITIAL_SPEED_LIMIT_PER_SECOND_V6: u64 = 7_000_000;
46pub const INITIAL_PER_BLOCK_GAS_LIMIT_V0: u64 = 20_000_000;
47pub const INITIAL_PER_BLOCK_GAS_LIMIT_V6: u64 = 32_000_000;
48pub const INITIAL_MINIMUM_BASE_FEE_WEI: u64 = 100_000_000; pub const INITIAL_BASE_FEE_WEI: u64 = INITIAL_MINIMUM_BASE_FEE_WEI;
50pub const INITIAL_PRICING_INERTIA: u64 = 102;
51pub const INITIAL_BACKLOG_TOLERANCE: u64 = 10;
52pub const INITIAL_PER_TX_GAS_LIMIT_V50: u64 = 32_000_000;
53
54pub struct L2PricingState<'a, D> {
56 pub backing_storage: Storage<'a, D>,
57 pub arbos_version: u64,
58 speed_limit_per_second: StorageBackedUint64,
59 per_block_gas_limit: StorageBackedUint64,
60 base_fee_wei: StorageBackedBigUint,
61 min_base_fee_wei: StorageBackedBigUint,
62 gas_backlog: StorageBackedUint64,
63 pricing_inertia: StorageBackedUint64,
64 backlog_tolerance: StorageBackedUint64,
65 per_tx_gas_limit: StorageBackedUint64,
66 gas_constraints: SubStorageVector,
67 multi_gas_constraints: SubStorageVector,
68 multi_gas_base_fees: Storage<'a, D>,
69}
70
71pub fn initialize_l2_pricing_state<D, B: StorageBackend>(
72 sto: &Storage<'_, D>,
73 backend: &mut B,
74) -> Result<(), L2PricingError> {
75 let base_key = sto.base_key();
76
77 StorageBackedUint64::new(base_key, SPEED_LIMIT_PER_SECOND_OFFSET)
78 .set(backend, INITIAL_SPEED_LIMIT_PER_SECOND_V0)?;
79 StorageBackedUint64::new(base_key, PER_BLOCK_GAS_LIMIT_OFFSET)
80 .set(backend, INITIAL_PER_BLOCK_GAS_LIMIT_V0)?;
81 StorageBackedUint64::new(base_key, BASE_FEE_WEI_OFFSET).set(backend, INITIAL_BASE_FEE_WEI)?;
82 StorageBackedBigUint::new(base_key, MIN_BASE_FEE_WEI_OFFSET)
83 .set(backend, U256::from(INITIAL_MINIMUM_BASE_FEE_WEI))?;
84 StorageBackedUint64::new(base_key, GAS_BACKLOG_OFFSET).set(backend, 0)?;
85 StorageBackedUint64::new(base_key, PRICING_INERTIA_OFFSET)
86 .set(backend, INITIAL_PRICING_INERTIA)?;
87 StorageBackedUint64::new(base_key, BACKLOG_TOLERANCE_OFFSET)
88 .set(backend, INITIAL_BACKLOG_TOLERANCE)?;
89 Ok(())
90}
91
92pub fn open_l2_pricing_state<D>(sto: Storage<'_, D>, arbos_version: u64) -> L2PricingState<'_, D> {
93 let base_key = sto.base_key();
94
95 let gc_sto = sto.open_sub_storage(GAS_CONSTRAINTS_KEY);
96 let mgc_sto = sto.open_sub_storage(MULTI_GAS_CONSTRAINTS_KEY);
97 let mgf_sto = sto.open_sub_storage(MULTI_GAS_BASE_FEES_KEY);
98
99 L2PricingState {
100 arbos_version,
101 speed_limit_per_second: StorageBackedUint64::new(base_key, SPEED_LIMIT_PER_SECOND_OFFSET),
102 per_block_gas_limit: StorageBackedUint64::new(base_key, PER_BLOCK_GAS_LIMIT_OFFSET),
103 base_fee_wei: StorageBackedBigUint::new(base_key, BASE_FEE_WEI_OFFSET),
104 min_base_fee_wei: StorageBackedBigUint::new(base_key, MIN_BASE_FEE_WEI_OFFSET),
105 gas_backlog: StorageBackedUint64::new(base_key, GAS_BACKLOG_OFFSET),
106 pricing_inertia: StorageBackedUint64::new(base_key, PRICING_INERTIA_OFFSET),
107 backlog_tolerance: StorageBackedUint64::new(base_key, BACKLOG_TOLERANCE_OFFSET),
108 per_tx_gas_limit: StorageBackedUint64::new(base_key, PER_TX_GAS_LIMIT_OFFSET),
109 gas_constraints: open_sub_storage_vector(gc_sto),
110 multi_gas_constraints: open_sub_storage_vector(mgc_sto),
111 multi_gas_base_fees: mgf_sto,
112 backing_storage: sto,
113 }
114}
115
116impl<'a, D> L2PricingState<'a, D> {
117 pub fn open(sto: Storage<'a, D>, arbos_version: u64) -> Self {
118 open_l2_pricing_state(sto, arbos_version)
119 }
120
121 pub fn initialize<B: StorageBackend>(
122 sto: &Storage<'_, D>,
123 backend: &mut B,
124 ) -> Result<(), L2PricingError> {
125 initialize_l2_pricing_state(sto, backend)
126 }
127
128 pub fn base_fee_wei<B: SystemStateBackend>(
131 &self,
132 backend: &mut B,
133 ) -> Result<U256, L2PricingError> {
134 Ok(self.base_fee_wei.get(backend)?)
135 }
136
137 pub fn set_base_fee_wei<B: StorageBackend>(
138 &self,
139 backend: &mut B,
140 val: U256,
141 ) -> Result<(), L2PricingError> {
142 Ok(self.base_fee_wei.set(backend, val)?)
143 }
144
145 pub fn min_base_fee_wei<B: SystemStateBackend>(
146 &self,
147 backend: &mut B,
148 ) -> Result<U256, L2PricingError> {
149 Ok(self.min_base_fee_wei.get(backend)?)
150 }
151
152 pub fn set_min_base_fee_wei<B: StorageBackend>(
153 &self,
154 backend: &mut B,
155 val: U256,
156 ) -> Result<(), L2PricingError> {
157 Ok(self.min_base_fee_wei.set(backend, val)?)
158 }
159
160 pub fn speed_limit_per_second<B: SystemStateBackend>(
161 &self,
162 backend: &mut B,
163 ) -> Result<u64, L2PricingError> {
164 Ok(self.speed_limit_per_second.get(backend)?)
165 }
166
167 pub fn set_speed_limit_per_second<B: StorageBackend>(
168 &self,
169 backend: &mut B,
170 limit: u64,
171 ) -> Result<(), L2PricingError> {
172 Ok(self.speed_limit_per_second.set(backend, limit)?)
173 }
174
175 pub fn per_block_gas_limit<B: SystemStateBackend>(
176 &self,
177 backend: &mut B,
178 ) -> Result<u64, L2PricingError> {
179 Ok(self.per_block_gas_limit.get(backend)?)
180 }
181
182 pub fn set_max_per_block_gas_limit<B: StorageBackend>(
183 &self,
184 backend: &mut B,
185 limit: u64,
186 ) -> Result<(), L2PricingError> {
187 Ok(self.per_block_gas_limit.set(backend, limit)?)
188 }
189
190 pub fn per_tx_gas_limit<B: SystemStateBackend>(
191 &self,
192 backend: &mut B,
193 ) -> Result<u64, L2PricingError> {
194 Ok(self.per_tx_gas_limit.get(backend)?)
195 }
196
197 pub fn set_max_per_tx_gas_limit<B: StorageBackend>(
198 &self,
199 backend: &mut B,
200 limit: u64,
201 ) -> Result<(), L2PricingError> {
202 Ok(self.per_tx_gas_limit.set(backend, limit)?)
203 }
204
205 pub fn gas_backlog<B: SystemStateBackend>(
206 &self,
207 backend: &mut B,
208 ) -> Result<u64, L2PricingError> {
209 Ok(self.gas_backlog.get(backend)?)
210 }
211
212 pub fn set_gas_backlog<B: StorageBackend>(
213 &self,
214 backend: &mut B,
215 backlog: u64,
216 ) -> Result<(), L2PricingError> {
217 Ok(self.gas_backlog.set(backend, backlog)?)
218 }
219
220 pub fn pricing_inertia<B: SystemStateBackend>(
221 &self,
222 backend: &mut B,
223 ) -> Result<u64, L2PricingError> {
224 Ok(self.pricing_inertia.get(backend)?)
225 }
226
227 pub fn set_pricing_inertia<B: StorageBackend>(
228 &self,
229 backend: &mut B,
230 val: u64,
231 ) -> Result<(), L2PricingError> {
232 Ok(self.pricing_inertia.set(backend, val)?)
233 }
234
235 pub fn backlog_tolerance<B: SystemStateBackend>(
236 &self,
237 backend: &mut B,
238 ) -> Result<u64, L2PricingError> {
239 Ok(self.backlog_tolerance.get(backend)?)
240 }
241
242 pub fn set_backlog_tolerance<B: StorageBackend>(
243 &self,
244 backend: &mut B,
245 val: u64,
246 ) -> Result<(), L2PricingError> {
247 Ok(self.backlog_tolerance.set(backend, val)?)
248 }
249
250 pub fn gas_constraints_length<B: SystemStateBackend>(
253 &self,
254 backend: &mut B,
255 ) -> Result<u64, L2PricingError> {
256 Ok(self.gas_constraints.length(backend)?)
257 }
258
259 pub fn open_gas_constraint_at(&self, index: u64) -> GasConstraint {
260 open_gas_constraint(self.gas_constraints.at(index))
261 }
262
263 pub fn add_gas_constraint<B: StorageBackend>(
264 &self,
265 backend: &mut B,
266 target: u64,
267 adjustment_window: u64,
268 backlog: u64,
269 ) -> Result<(), L2PricingError> {
270 let key = self.gas_constraints.push(backend)?;
271 let c = open_gas_constraint(key);
272 c.set_target(backend, target)?;
273 c.set_adjustment_window(backend, adjustment_window)?;
274 c.set_backlog(backend, backlog)?;
275 Ok(())
276 }
277
278 pub fn clear_gas_constraints<B: StorageBackend>(
279 &self,
280 backend: &mut B,
281 ) -> Result<(), L2PricingError> {
282 let len = self.gas_constraints.length(backend)?;
283 for i in 0..len {
284 let c = self.open_gas_constraint_at(i);
285 c.clear(backend)?;
286 }
287 for _ in 0..len {
288 self.gas_constraints.pop(backend)?;
289 }
290 Ok(())
291 }
292
293 pub fn multi_gas_constraints_length<B: SystemStateBackend>(
296 &self,
297 backend: &mut B,
298 ) -> Result<u64, L2PricingError> {
299 Ok(self.multi_gas_constraints.length(backend)?)
300 }
301
302 pub fn open_multi_gas_constraint_at(&self, index: u64) -> MultiGasConstraint {
303 open_multi_gas_constraint(self.multi_gas_constraints.at(index))
304 }
305
306 pub fn add_multi_gas_constraint<B: StorageBackend>(
307 &self,
308 backend: &mut B,
309 target: u64,
310 adjustment_window: u32,
311 backlog: u64,
312 weights: &[u64; NUM_RESOURCE_KIND],
313 ) -> Result<(), L2PricingError> {
314 let key = self.multi_gas_constraints.push(backend)?;
315 let c = open_multi_gas_constraint(key);
316 c.set_target(backend, target)?;
317 c.set_adjustment_window(backend, adjustment_window)?;
318 c.set_backlog(backend, backlog)?;
319 c.set_resource_weights(backend, weights)?;
320 Ok(())
321 }
322
323 pub fn clear_multi_gas_constraints<B: StorageBackend>(
324 &self,
325 backend: &mut B,
326 ) -> Result<(), L2PricingError> {
327 let len = self.multi_gas_constraints.length(backend)?;
328 for i in 0..len {
329 let c = self.open_multi_gas_constraint_at(i);
330 c.clear(backend)?;
331 }
332 for _ in 0..len {
333 self.multi_gas_constraints.pop(backend)?;
334 }
335 Ok(())
336 }
337
338 pub fn restrict(&self, _err: ()) {
339 }
341
342 pub fn multi_gas_fees(&self) -> MultiGasFees<'a, D> {
344 multi_gas_fees::open_multi_gas_fees(self.multi_gas_base_fees.clone())
345 }
346}