1mod gas_constraint;
2mod model;
3mod multi_gas_constraint;
4mod multi_gas_fees;
5
6pub use gas_constraint::{open_gas_constraint, GasConstraint};
7pub use model::*;
8pub use multi_gas_constraint::{open_multi_gas_constraint, MultiGasConstraint};
9pub use multi_gas_fees::MultiGasFees;
10
11use alloy_primitives::U256;
12use revm::Database;
13
14use arb_primitives::multigas::NUM_RESOURCE_KIND;
15use arb_storage::{
16 open_sub_storage_vector, Storage, StorageBackedBigUint, StorageBackedUint64, SubStorageVector,
17};
18
19const SPEED_LIMIT_PER_SECOND_OFFSET: u64 = 0;
21const PER_BLOCK_GAS_LIMIT_OFFSET: u64 = 1;
22const BASE_FEE_WEI_OFFSET: u64 = 2;
23const MIN_BASE_FEE_WEI_OFFSET: u64 = 3;
24const GAS_BACKLOG_OFFSET: u64 = 4;
25const PRICING_INERTIA_OFFSET: u64 = 5;
26const BACKLOG_TOLERANCE_OFFSET: u64 = 6;
27const 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<D> {
56 pub backing_storage: Storage<D>,
57 pub arbos_version: u64,
58 speed_limit_per_second: StorageBackedUint64<D>,
59 per_block_gas_limit: StorageBackedUint64<D>,
60 base_fee_wei: StorageBackedBigUint<D>,
61 min_base_fee_wei: StorageBackedBigUint<D>,
62 gas_backlog: StorageBackedUint64<D>,
63 pricing_inertia: StorageBackedUint64<D>,
64 backlog_tolerance: StorageBackedUint64<D>,
65 per_tx_gas_limit: StorageBackedUint64<D>,
66 gas_constraints: SubStorageVector<D>,
67 multi_gas_constraints: SubStorageVector<D>,
68 multi_gas_base_fees: Storage<D>,
69}
70
71pub fn initialize_l2_pricing_state<D: Database>(sto: &Storage<D>) {
72 let state = sto.state_ptr();
73 let base_key = sto.base_key();
74
75 let _ = StorageBackedUint64::new(state, base_key, SPEED_LIMIT_PER_SECOND_OFFSET)
76 .set(INITIAL_SPEED_LIMIT_PER_SECOND_V0);
77 let _ = StorageBackedUint64::new(state, base_key, PER_BLOCK_GAS_LIMIT_OFFSET)
78 .set(INITIAL_PER_BLOCK_GAS_LIMIT_V0);
79 let _ =
80 StorageBackedUint64::new(state, base_key, BASE_FEE_WEI_OFFSET).set(INITIAL_BASE_FEE_WEI);
81 let _ = StorageBackedBigUint::new(state, base_key, MIN_BASE_FEE_WEI_OFFSET)
82 .set(U256::from(INITIAL_MINIMUM_BASE_FEE_WEI));
83 let _ = StorageBackedUint64::new(state, base_key, GAS_BACKLOG_OFFSET).set(0);
84 let _ = StorageBackedUint64::new(state, base_key, PRICING_INERTIA_OFFSET)
85 .set(INITIAL_PRICING_INERTIA);
86 let _ = StorageBackedUint64::new(state, base_key, BACKLOG_TOLERANCE_OFFSET)
87 .set(INITIAL_BACKLOG_TOLERANCE);
88}
89
90pub fn open_l2_pricing_state<D: Database>(
91 sto: Storage<D>,
92 arbos_version: u64,
93) -> L2PricingState<D> {
94 let state = sto.state_ptr();
95 let base_key = sto.base_key();
96
97 let gc_sto = sto.open_sub_storage(GAS_CONSTRAINTS_KEY);
98 let mgc_sto = sto.open_sub_storage(MULTI_GAS_CONSTRAINTS_KEY);
99 let mgf_sto = sto.open_sub_storage(MULTI_GAS_BASE_FEES_KEY);
100
101 L2PricingState {
102 arbos_version,
103 speed_limit_per_second: StorageBackedUint64::new(
104 state,
105 base_key,
106 SPEED_LIMIT_PER_SECOND_OFFSET,
107 ),
108 per_block_gas_limit: StorageBackedUint64::new(state, base_key, PER_BLOCK_GAS_LIMIT_OFFSET),
109 base_fee_wei: StorageBackedBigUint::new(state, base_key, BASE_FEE_WEI_OFFSET),
110 min_base_fee_wei: StorageBackedBigUint::new(state, base_key, MIN_BASE_FEE_WEI_OFFSET),
111 gas_backlog: StorageBackedUint64::new(state, base_key, GAS_BACKLOG_OFFSET),
112 pricing_inertia: StorageBackedUint64::new(state, base_key, PRICING_INERTIA_OFFSET),
113 backlog_tolerance: StorageBackedUint64::new(state, base_key, BACKLOG_TOLERANCE_OFFSET),
114 per_tx_gas_limit: StorageBackedUint64::new(state, base_key, PER_TX_GAS_LIMIT_OFFSET),
115 gas_constraints: open_sub_storage_vector(gc_sto),
116 multi_gas_constraints: open_sub_storage_vector(mgc_sto),
117 multi_gas_base_fees: mgf_sto,
118 backing_storage: sto,
119 }
120}
121
122impl<D: Database> L2PricingState<D> {
123 pub fn open(sto: Storage<D>, arbos_version: u64) -> Self {
124 open_l2_pricing_state(sto, arbos_version)
125 }
126
127 pub fn initialize(sto: &Storage<D>) {
128 initialize_l2_pricing_state(sto);
129 }
130
131 pub fn base_fee_wei(&self) -> Result<U256, ()> {
134 self.base_fee_wei.get()
135 }
136
137 pub fn set_base_fee_wei(&self, val: U256) -> Result<(), ()> {
138 self.base_fee_wei.set(val)
139 }
140
141 pub fn min_base_fee_wei(&self) -> Result<U256, ()> {
142 self.min_base_fee_wei.get()
143 }
144
145 pub fn set_min_base_fee_wei(&self, val: U256) -> Result<(), ()> {
146 self.min_base_fee_wei.set(val)
147 }
148
149 pub fn speed_limit_per_second(&self) -> Result<u64, ()> {
150 self.speed_limit_per_second.get()
151 }
152
153 pub fn set_speed_limit_per_second(&self, limit: u64) -> Result<(), ()> {
154 self.speed_limit_per_second.set(limit)
155 }
156
157 pub fn per_block_gas_limit(&self) -> Result<u64, ()> {
158 self.per_block_gas_limit.get()
159 }
160
161 pub fn set_max_per_block_gas_limit(&self, limit: u64) -> Result<(), ()> {
162 self.per_block_gas_limit.set(limit)
163 }
164
165 pub fn per_tx_gas_limit(&self) -> Result<u64, ()> {
166 self.per_tx_gas_limit.get()
167 }
168
169 pub fn set_max_per_tx_gas_limit(&self, limit: u64) -> Result<(), ()> {
170 self.per_tx_gas_limit.set(limit)
171 }
172
173 pub fn gas_backlog(&self) -> Result<u64, ()> {
174 self.gas_backlog.get()
175 }
176
177 pub fn set_gas_backlog(&self, backlog: u64) -> Result<(), ()> {
178 self.gas_backlog.set(backlog)
179 }
180
181 pub fn pricing_inertia(&self) -> Result<u64, ()> {
182 self.pricing_inertia.get()
183 }
184
185 pub fn set_pricing_inertia(&self, val: u64) -> Result<(), ()> {
186 self.pricing_inertia.set(val)
187 }
188
189 pub fn backlog_tolerance(&self) -> Result<u64, ()> {
190 self.backlog_tolerance.get()
191 }
192
193 pub fn set_backlog_tolerance(&self, val: u64) -> Result<(), ()> {
194 self.backlog_tolerance.set(val)
195 }
196
197 pub fn gas_constraints_length(&self) -> Result<u64, ()> {
200 self.gas_constraints.length()
201 }
202
203 pub fn open_gas_constraint_at(&self, index: u64) -> GasConstraint<D> {
204 open_gas_constraint(self.gas_constraints.at(index))
205 }
206
207 pub fn add_gas_constraint(
208 &self,
209 target: u64,
210 adjustment_window: u64,
211 backlog: u64,
212 ) -> Result<(), ()> {
213 let sto = self.gas_constraints.push()?;
214 let c = open_gas_constraint(sto);
215 c.set_target(target)?;
216 c.set_adjustment_window(adjustment_window)?;
217 c.set_backlog(backlog)?;
218 Ok(())
219 }
220
221 pub fn clear_gas_constraints(&self) -> Result<(), ()> {
222 let len = self.gas_constraints.length()?;
223 for i in 0..len {
224 let c = self.open_gas_constraint_at(i);
225 c.clear()?;
226 }
227 for _ in 0..len {
229 self.gas_constraints.pop()?;
230 }
231 Ok(())
232 }
233
234 pub fn multi_gas_constraints_length(&self) -> Result<u64, ()> {
237 self.multi_gas_constraints.length()
238 }
239
240 pub fn open_multi_gas_constraint_at(&self, index: u64) -> MultiGasConstraint<D> {
241 open_multi_gas_constraint(self.multi_gas_constraints.at(index))
242 }
243
244 pub fn add_multi_gas_constraint(
245 &self,
246 target: u64,
247 adjustment_window: u32,
248 backlog: u64,
249 weights: &[u64; NUM_RESOURCE_KIND],
250 ) -> Result<(), ()> {
251 let sto = self.multi_gas_constraints.push()?;
252 let c = open_multi_gas_constraint(sto);
253 c.set_target(target)?;
254 c.set_adjustment_window(adjustment_window)?;
255 c.set_backlog(backlog)?;
256 c.set_resource_weights(weights)?;
257 Ok(())
258 }
259
260 pub fn clear_multi_gas_constraints(&self) -> Result<(), ()> {
261 let len = self.multi_gas_constraints.length()?;
262 for i in 0..len {
263 let c = self.open_multi_gas_constraint_at(i);
264 c.clear()?;
265 }
266 for _ in 0..len {
267 self.multi_gas_constraints.pop()?;
268 }
269 Ok(())
270 }
271
272 pub fn restrict(&self, _err: ()) {
273 }
275}