1mod error;
2pub mod initialize;
3
4use std::sync::OnceLock;
5
6use alloy_primitives::{Address, B256, Bytes, U256, keccak256};
7use arb_primitives::arbos_versions::{
8 HISTORY_STORAGE_ADDRESS, HISTORY_STORAGE_CODE_ARBITRUM, PRECOMPILE_MIN_ARBOS_VERSIONS,
9};
10use arb_storage::layout::{
13 ADDRESS_TABLE_SUBSPACE, BLOCKHASHES_SUBSPACE, CHAIN_CONFIG_SUBSPACE, CHAIN_OWNER_SUBSPACE,
14 FEATURES_SUBSPACE, L1_PRICING_SUBSPACE, L2_PRICING_SUBSPACE, NATIVE_TOKEN_SUBSPACE,
15 PROGRAMS_SUBSPACE, RETRYABLES_SUBSPACE, SEND_MERKLE_SUBSPACE, TRANSACTION_FILTERER_SUBSPACE,
16};
17pub use arb_storage::layout::{
18 BROTLI_COMPRESSION_LEVEL_OFFSET, CHAIN_ID_OFFSET, COLLECT_TIPS_OFFSET,
19 FILTERED_FUNDS_RECIPIENT_OFFSET, GENESIS_BLOCK_NUM_OFFSET, INFRA_FEE_ACCOUNT_OFFSET,
20 NATIVE_TOKEN_ENABLED_FROM_TIME_OFFSET, NETWORK_FEE_ACCOUNT_OFFSET,
21 TRANSACTION_FILTERING_ENABLED_FROM_TIME_OFFSET, UPGRADE_TIMESTAMP_OFFSET,
22 UPGRADE_VERSION_OFFSET, VERSION_OFFSET,
23};
24use arb_storage::{
25 ARBOS_STATE_ADDRESS, Detached, FILTERED_TX_STATE_ADDRESS, Storage, StorageBackedAddress,
26 StorageBackedBigUint, StorageBackedBytes, StorageBackedUint64, StorageBackend,
27 SystemStateBackend, get_account_balance, set_account_code, set_account_nonce, storage_key_map,
28};
29pub use error::ArbosStateError;
30use revm::Database;
31
32use crate::{
33 address_set::{self, AddressSet},
34 address_table::{self, AddressTable},
35 blockhash::{self, Blockhashes},
36 burn::Burner,
37 features::{self, Features},
38 filtered_transactions::FilteredTransactionsState,
39 l1_pricing::{self, L1PricingState},
40 l2_pricing::{self, L2PricingState},
41 merkle_accumulator::{self, MerkleAccumulator},
42 programs::Programs,
43 retryables::RetryableState,
44};
45
46macro_rules! cached_root_key {
48 ($name:ident, $sub:expr_2021) => {
49 fn $name() -> B256 {
50 static KEY: OnceLock<B256> = OnceLock::new();
51 *KEY.get_or_init(|| keccak256($sub))
52 }
53 };
54}
55
56cached_root_key!(l1_pricing_root_key, L1_PRICING_SUBSPACE);
57cached_root_key!(l2_pricing_root_key, L2_PRICING_SUBSPACE);
58cached_root_key!(retryables_root_key, RETRYABLES_SUBSPACE);
59cached_root_key!(address_table_root_key, ADDRESS_TABLE_SUBSPACE);
60cached_root_key!(chain_owner_root_key, CHAIN_OWNER_SUBSPACE);
61cached_root_key!(send_merkle_root_key, SEND_MERKLE_SUBSPACE);
62cached_root_key!(blockhashes_root_key, BLOCKHASHES_SUBSPACE);
63cached_root_key!(chain_config_root_key, CHAIN_CONFIG_SUBSPACE);
64cached_root_key!(programs_root_key, PROGRAMS_SUBSPACE);
65cached_root_key!(features_root_key, FEATURES_SUBSPACE);
66cached_root_key!(native_token_owner_root_key, NATIVE_TOKEN_SUBSPACE);
67cached_root_key!(
68 transaction_filtering_root_key,
69 TRANSACTION_FILTERER_SUBSPACE
70);
71
72pub const MAX_ARBOS_VERSION_SUPPORTED: u64 = 60;
74
75pub struct ArbosState<'a, D, B: Burner> {
77 pub arbos_version: u64,
78 pub max_arbos_version_supported: u64,
79 pub upgrade_version: StorageBackedUint64,
80 pub upgrade_timestamp: StorageBackedUint64,
81 pub network_fee_account: StorageBackedAddress,
82 pub l1_pricing_state: L1PricingState<'a, D>,
83 pub l2_pricing_state: L2PricingState<'a, D>,
84 pub retryable_state: RetryableState<'a, D>,
85 pub address_table: AddressTable<'a, D>,
86 pub chain_owners: AddressSet<'a, D>,
87 pub send_merkle_accumulator: MerkleAccumulator<'a, D>,
88 pub programs: Programs<'a, D>,
89 pub blockhashes: Blockhashes<'a, D>,
90 pub chain_id: StorageBackedBigUint,
91 pub chain_config: StorageBackedBytes,
92 pub genesis_block_num: StorageBackedUint64,
93 pub infra_fee_account: StorageBackedAddress,
94 pub brotli_compression_level: StorageBackedUint64,
95 pub backing_storage: Storage<'a, D>,
96 pub burner: B,
97 pub native_token_enabled_from_time: StorageBackedUint64,
98 pub native_token_owners: AddressSet<'a, D>,
99 pub transaction_filtering_enabled_from_time: StorageBackedUint64,
100 pub transaction_filterers: AddressSet<'a, D>,
101 pub features: Features<'a, D>,
102 pub filtered_funds_recipient: StorageBackedAddress,
103 pub filtered_transactions: FilteredTransactionsState<'a, D>,
104 pub collect_tips: StorageBackedUint64,
105}
106
107impl<'a, D, B: Burner> ArbosState<'a, D, B> {
108 pub fn arbos_version(&self) -> u64 {
111 self.arbos_version
112 }
113
114 pub fn backing_storage(&self) -> &Storage<'a, D> {
115 &self.backing_storage
116 }
117
118 pub fn brotli_compression_level<C: SystemStateBackend>(
119 &self,
120 backend: &mut C,
121 ) -> Result<u64, ArbosStateError> {
122 Ok(self.brotli_compression_level.get(backend)?)
123 }
124
125 pub fn set_brotli_compression_level<C: StorageBackend>(
126 &self,
127 backend: &mut C,
128 level: u64,
129 ) -> Result<(), ArbosStateError> {
130 const LEVEL_WELL: u64 = 11;
131 if level > LEVEL_WELL {
132 return Err(ArbosStateError::InvalidBrotliCompressionLevel);
133 }
134 Ok(self.brotli_compression_level.set(backend, level)?)
135 }
136
137 pub fn collect_tips<C: SystemStateBackend>(
139 &self,
140 backend: &mut C,
141 ) -> Result<bool, ArbosStateError> {
142 if self.arbos_version < 60 {
143 return Ok(false);
144 }
145 Ok(self.collect_tips.get(backend)? != 0)
146 }
147
148 pub fn set_collect_tips<C: StorageBackend>(
149 &self,
150 backend: &mut C,
151 enabled: bool,
152 ) -> Result<(), ArbosStateError> {
153 Ok(self.collect_tips.set(backend, u64::from(enabled))?)
154 }
155
156 pub fn chain_id<C: SystemStateBackend>(
157 &self,
158 backend: &mut C,
159 ) -> Result<U256, ArbosStateError> {
160 Ok(self.chain_id.get(backend)?)
161 }
162
163 pub fn chain_config<C: SystemStateBackend>(
164 &self,
165 backend: &mut C,
166 ) -> Result<Vec<u8>, ArbosStateError> {
167 Ok(self.chain_config.get(backend)?)
168 }
169
170 pub fn set_chain_config<C: StorageBackend>(
171 &self,
172 backend: &mut C,
173 config: &[u8],
174 ) -> Result<(), ArbosStateError> {
175 Ok(self.chain_config.set(backend, config)?)
176 }
177
178 pub fn genesis_block_num<C: SystemStateBackend>(
179 &self,
180 backend: &mut C,
181 ) -> Result<u64, ArbosStateError> {
182 Ok(self.genesis_block_num.get(backend)?)
183 }
184
185 pub fn network_fee_account<C: SystemStateBackend>(
186 &self,
187 backend: &mut C,
188 ) -> Result<Address, ArbosStateError> {
189 Ok(self.network_fee_account.get(backend)?)
190 }
191
192 pub fn set_network_fee_account<C: StorageBackend>(
193 &self,
194 backend: &mut C,
195 account: Address,
196 ) -> Result<(), ArbosStateError> {
197 Ok(self.network_fee_account.set(backend, account)?)
198 }
199
200 pub fn infra_fee_account<C: SystemStateBackend>(
201 &self,
202 backend: &mut C,
203 ) -> Result<Address, ArbosStateError> {
204 Ok(self.infra_fee_account.get(backend)?)
205 }
206
207 pub fn set_infra_fee_account<C: StorageBackend>(
208 &self,
209 backend: &mut C,
210 account: Address,
211 ) -> Result<(), ArbosStateError> {
212 Ok(self.infra_fee_account.set(backend, account)?)
213 }
214
215 pub fn filtered_funds_recipient<C: SystemStateBackend>(
216 &self,
217 backend: &mut C,
218 ) -> Result<Address, ArbosStateError> {
219 Ok(self.filtered_funds_recipient.get(backend)?)
220 }
221
222 pub fn filtered_funds_recipient_or_default<C: SystemStateBackend>(
223 &self,
224 backend: &mut C,
225 ) -> Result<Address, ArbosStateError> {
226 let addr = self.filtered_funds_recipient.get(backend)?;
227 if addr == Address::ZERO {
228 self.network_fee_account(backend)
229 } else {
230 Ok(addr)
231 }
232 }
233
234 pub fn set_filtered_funds_recipient<C: StorageBackend>(
235 &self,
236 backend: &mut C,
237 addr: Address,
238 ) -> Result<(), ArbosStateError> {
239 Ok(self.filtered_funds_recipient.set(backend, addr)?)
240 }
241
242 pub fn native_token_management_from_time<C: SystemStateBackend>(
243 &self,
244 backend: &mut C,
245 ) -> Result<u64, ArbosStateError> {
246 Ok(self.native_token_enabled_from_time.get(backend)?)
247 }
248
249 pub fn set_native_token_management_from_time<C: StorageBackend>(
250 &self,
251 backend: &mut C,
252 time: u64,
253 ) -> Result<(), ArbosStateError> {
254 Ok(self.native_token_enabled_from_time.set(backend, time)?)
255 }
256
257 pub fn transaction_filtering_from_time<C: SystemStateBackend>(
258 &self,
259 backend: &mut C,
260 ) -> Result<u64, ArbosStateError> {
261 Ok(self.transaction_filtering_enabled_from_time.get(backend)?)
262 }
263
264 pub fn set_transaction_filtering_from_time<C: StorageBackend>(
265 &self,
266 backend: &mut C,
267 time: u64,
268 ) -> Result<(), ArbosStateError> {
269 Ok(self
270 .transaction_filtering_enabled_from_time
271 .set(backend, time)?)
272 }
273
274 pub fn get_scheduled_upgrade<C: SystemStateBackend>(
275 &self,
276 backend: &mut C,
277 ) -> Result<(u64, u64), ArbosStateError> {
278 let version = self.upgrade_version.get(backend)?;
279 let timestamp = self.upgrade_timestamp.get(backend)?;
280 Ok((version, timestamp))
281 }
282
283 pub fn schedule_arbos_upgrade<C: StorageBackend>(
284 &self,
285 backend: &mut C,
286 version: u64,
287 timestamp: u64,
288 ) -> Result<(), ArbosStateError> {
289 self.upgrade_version.set(backend, version)?;
290 Ok(self.upgrade_timestamp.set(backend, timestamp)?)
291 }
292}
293
294impl<'a, D: Database, B: Burner> ArbosState<'a, D, B> {
295 pub fn set_format_version(&mut self, version: u64) -> Result<(), ArbosStateError> {
296 self.arbos_version = version;
297 Ok(self
298 .backing_storage
299 .set_by_uint64(VERSION_OFFSET, B256::from(U256::from(version)))?)
300 }
301
302 pub fn open(
310 state: &'a mut revm::database::State<D>,
311 burner: B,
312 ) -> Result<Self, ArbosStateError> {
313 let backing_storage = Storage::new(state, B256::ZERO);
314
315 let arbos_version = backing_storage.get_uint64_by_uint64(VERSION_OFFSET)?;
316 if arbos_version == 0 {
317 return Err(ArbosStateError::Uninitialised);
318 }
319 if arbos_version > MAX_ARBOS_VERSION_SUPPORTED {
320 return Err(ArbosStateError::UnsupportedVersion(arbos_version));
321 }
322
323 if arbos_version >= 60 {
324 let state_ref = unsafe { backing_storage.state_mut() };
329 set_account_nonce(state_ref, FILTERED_TX_STATE_ADDRESS, 1);
330 }
331
332 let chain_config_key = chain_config_root_key();
333 let features_sto = backing_storage.open_sub_storage_with_key(features_root_key());
334
335 Ok(Self {
336 arbos_version,
337 max_arbos_version_supported: MAX_ARBOS_VERSION_SUPPORTED,
338 upgrade_version: StorageBackedUint64::new(B256::ZERO, UPGRADE_VERSION_OFFSET),
339 upgrade_timestamp: StorageBackedUint64::new(B256::ZERO, UPGRADE_TIMESTAMP_OFFSET),
340 network_fee_account: StorageBackedAddress::new(B256::ZERO, NETWORK_FEE_ACCOUNT_OFFSET),
341 l1_pricing_state: L1PricingState::open(
342 backing_storage.open_sub_storage_with_key(l1_pricing_root_key()),
343 arbos_version,
344 ),
345 l2_pricing_state: L2PricingState::open(
346 backing_storage.open_sub_storage_with_key(l2_pricing_root_key()),
347 arbos_version,
348 ),
349 retryable_state: RetryableState::open(
350 backing_storage.open_sub_storage_with_key(retryables_root_key()),
351 arbos_version,
352 ),
353 address_table: address_table::open_address_table(
354 backing_storage.open_sub_storage_with_key(address_table_root_key()),
355 ),
356 chain_owners: address_set::open_address_set(
357 backing_storage.open_sub_storage_with_key(chain_owner_root_key()),
358 ),
359 send_merkle_accumulator: merkle_accumulator::open_merkle_accumulator(
360 backing_storage.open_sub_storage_with_key(send_merkle_root_key()),
361 ),
362 programs: Programs::open(
363 arbos_version,
364 backing_storage.open_sub_storage_with_key(programs_root_key()),
365 ),
366 blockhashes: blockhash::open_blockhashes(
367 backing_storage.open_sub_storage_with_key(blockhashes_root_key()),
368 ),
369 chain_id: StorageBackedBigUint::new(B256::ZERO, CHAIN_ID_OFFSET),
370 chain_config: StorageBackedBytes::new(chain_config_key),
371 genesis_block_num: StorageBackedUint64::new(B256::ZERO, GENESIS_BLOCK_NUM_OFFSET),
372 infra_fee_account: StorageBackedAddress::new(B256::ZERO, INFRA_FEE_ACCOUNT_OFFSET),
373 brotli_compression_level: StorageBackedUint64::new(
374 B256::ZERO,
375 BROTLI_COMPRESSION_LEVEL_OFFSET,
376 ),
377 native_token_enabled_from_time: StorageBackedUint64::new(
378 B256::ZERO,
379 NATIVE_TOKEN_ENABLED_FROM_TIME_OFFSET,
380 ),
381 native_token_owners: address_set::open_address_set(
382 backing_storage.open_sub_storage_with_key(native_token_owner_root_key()),
383 ),
384 transaction_filtering_enabled_from_time: StorageBackedUint64::new(
385 B256::ZERO,
386 TRANSACTION_FILTERING_ENABLED_FROM_TIME_OFFSET,
387 ),
388 transaction_filterers: address_set::open_address_set(
389 backing_storage.open_sub_storage_with_key(transaction_filtering_root_key()),
390 ),
391 features: features::open_features(features_sto.base_key(), 0),
392 filtered_funds_recipient: StorageBackedAddress::new(
393 B256::ZERO,
394 FILTERED_FUNDS_RECIPIENT_OFFSET,
395 ),
396 filtered_transactions: FilteredTransactionsState::open(
397 backing_storage.open_account(FILTERED_TX_STATE_ADDRESS, B256::ZERO),
398 ),
399 collect_tips: StorageBackedUint64::new(B256::ZERO, COLLECT_TIPS_OFFSET),
400 backing_storage,
401 burner,
402 })
403 }
404
405 pub fn upgrade_arbos_version_if_necessary<C: StorageBackend>(
407 &mut self,
408 backend: &mut C,
409 current_timestamp: u64,
410 ) -> Result<(), ArbosStateError> {
411 let scheduled_version = self.upgrade_version.get(backend)?;
412 let scheduled_timestamp = self.upgrade_timestamp.get(backend)?;
413
414 if scheduled_version == 0
415 || self.arbos_version >= scheduled_version
416 || current_timestamp < scheduled_timestamp
417 {
418 return Ok(());
419 }
420
421 if scheduled_version > MAX_ARBOS_VERSION_SUPPORTED {
422 return Err(ArbosStateError::UnsupportedScheduledVersion {
423 version: scheduled_version,
424 max: MAX_ARBOS_VERSION_SUPPORTED,
425 });
426 }
427
428 let old_version = self.arbos_version;
429 self.upgrade_arbos_version(backend, scheduled_version, false)?;
430
431 if old_version != self.arbos_version {
432 tracing::info!(
433 old_version,
434 new_version = self.arbos_version,
435 "ArbOS version upgraded"
436 );
437 }
438
439 Ok(())
440 }
441
442 pub fn upgrade_arbos_version<C: StorageBackend>(
444 &mut self,
445 backend: &mut C,
446 upgrade_to: u64,
447 first_time: bool,
448 ) -> Result<(), ArbosStateError> {
449 while self.arbos_version < upgrade_to {
450 let next = self.arbos_version + 1;
451
452 match next {
453 2 => {
454 self.l1_pricing_state
455 .set_last_surplus(backend, U256::ZERO, false)?;
456 }
457 3 => {
458 self.l1_pricing_state.set_per_batch_gas_cost(backend, 0)?;
459 self.l1_pricing_state
460 .set_amortized_cost_cap_bips(backend, u64::MAX)?;
461 }
462 4..=9 => {}
463 10 => {
464 let state = unsafe { self.backing_storage.state_mut() };
466 let pool_balance =
467 get_account_balance(state, l1_pricing::L1_PRICER_FUNDS_POOL_ADDRESS);
468 self.l1_pricing_state
469 .set_l1_fees_available(backend, pool_balance)?;
470 }
471 11 => {
472 self.l1_pricing_state.set_per_batch_gas_cost(
473 backend,
474 l1_pricing::INITIAL_PER_BATCH_GAS_COST_V12,
475 )?;
476
477 let old_cap = self.l1_pricing_state.amortized_cost_cap_bips(backend)?;
478 if old_cap == u64::MAX {
479 self.l1_pricing_state
480 .set_amortized_cost_cap_bips(backend, 0)?;
481 }
482
483 if !first_time {
484 self.chain_owners.clear_list(backend)?;
485 }
486 }
487 12..=19 => {}
488 20 => {
489 self.set_brotli_compression_level(backend, 1)?;
490 }
491 21..=29 => {}
492 30 => {
493 Programs::initialize(
494 next,
495 &self.backing_storage.open_sub_storage(PROGRAMS_SUBSPACE),
496 backend,
497 )?;
498 }
499 31 => {
500 let mut params = self.programs.params(backend)?;
501 params.upgrade_to_version(2)?;
502 params.save(
503 &self.programs.backing_storage.open_sub_storage(&[0]),
504 backend,
505 )?;
506 }
507 32 => {}
508 33..=39 => {}
509 40 => {
510 let state = unsafe { self.backing_storage.state_mut() };
512 set_account_nonce(state, HISTORY_STORAGE_ADDRESS, 1);
513 set_account_code(
514 state,
515 HISTORY_STORAGE_ADDRESS,
516 HISTORY_STORAGE_CODE_ARBITRUM.clone(),
517 );
518 let mut params = self.programs.params(backend)?;
519 params.upgrade_to_arbos_version(next)?;
520 params.save(
521 &self.programs.backing_storage.open_sub_storage(&[0]),
522 backend,
523 )?;
524 }
525 41 => {}
526 42..=49 => {}
527 50 => {
528 let mut params = self.programs.params(backend)?;
529 params.upgrade_to_arbos_version(next)?;
530 params.save(
531 &self.programs.backing_storage.open_sub_storage(&[0]),
532 backend,
533 )?;
534 self.l2_pricing_state.set_max_per_tx_gas_limit(
535 backend,
536 l2_pricing::INITIAL_PER_TX_GAS_LIMIT_V50,
537 )?;
538 }
539 51 => {}
540 52..=58 => {}
541 59 => {
542 let mut params = self.programs.params(backend)?;
543 params.upgrade_to_version(3)?;
544 params.save(
545 &self.programs.backing_storage.open_sub_storage(&[0]),
546 backend,
547 )?;
548 }
549 60 => {
550 let mut params = self.programs.params(backend)?;
551 params.upgrade_to_arbos_version(next)?;
552 params.save(
553 &self.programs.backing_storage.open_sub_storage(&[0]),
554 backend,
555 )?;
556 crate::address_set::initialize_address_set(
557 &self
558 .backing_storage
559 .open_sub_storage(TRANSACTION_FILTERER_SUBSPACE),
560 )?;
561 }
562 _ => {
563 tracing::error!(version = next, "unsupported ArbOS version");
564 return Err(ArbosStateError::UnsupportedRunningVersion(next));
565 }
566 }
567
568 for &(addr, version) in PRECOMPILE_MIN_ARBOS_VERSIONS {
569 if version == next {
570 let state = unsafe { self.backing_storage.state_mut() };
572 set_account_code(state, addr, Bytes::from_static(&[0xFE]));
573 }
574 }
575
576 self.arbos_version = next;
577 self.programs.arbos_version = next;
578 self.l1_pricing_state.arbos_version = next;
579 self.l2_pricing_state.arbos_version = next;
580 self.retryable_state.arbos_version = next;
581 }
582
583 if first_time && upgrade_to >= 6 {
584 if upgrade_to < 11 {
585 self.l1_pricing_state
586 .set_per_batch_gas_cost(backend, l1_pricing::INITIAL_PER_BATCH_GAS_COST_V6)?;
587 }
588 self.l1_pricing_state.set_equilibration_units(
589 backend,
590 U256::from(l1_pricing::INITIAL_EQUILIBRATION_UNITS_V6),
591 )?;
592 self.l2_pricing_state.set_speed_limit_per_second(
593 backend,
594 l2_pricing::INITIAL_SPEED_LIMIT_PER_SECOND_V6,
595 )?;
596 self.l2_pricing_state
597 .set_max_per_block_gas_limit(backend, l2_pricing::INITIAL_PER_BLOCK_GAS_LIMIT_V6)?;
598 }
599
600 self.set_format_version(self.arbos_version)?;
601
602 Ok(())
603 }
604}
605
606pub fn arbos_from_input<S: StorageBackend, B: Burner>(
616 backend: &mut S,
617 burner: B,
618) -> Result<ArbosState<'static, Detached, B>, ArbosStateError> {
619 let version_slot = storage_key_map(&[], VERSION_OFFSET);
620 let raw_version =
621 StorageBackend::sload(backend, ARBOS_STATE_ADDRESS, version_slot).map_err(Into::into)?;
622 open_detached(raw_version, burner)
623}
624
625pub fn arbos_from_input_system<S: SystemStateBackend, B: Burner>(
632 backend: &mut S,
633 burner: B,
634) -> Result<ArbosState<'static, Detached, B>, ArbosStateError> {
635 let version_slot = storage_key_map(&[], VERSION_OFFSET);
636 let raw_version = SystemStateBackend::sload_system(backend, ARBOS_STATE_ADDRESS, version_slot)
637 .map_err(Into::into)?;
638 open_detached(raw_version, burner)
639}
640
641fn open_detached<B: Burner>(
642 raw_version: U256,
643 burner: B,
644) -> Result<ArbosState<'static, Detached, B>, ArbosStateError> {
645 let arbos_version = u64::try_from(raw_version).unwrap_or(0);
646 if arbos_version == 0 {
647 return Err(ArbosStateError::Uninitialised);
648 }
649 if arbos_version > MAX_ARBOS_VERSION_SUPPORTED {
650 return Err(ArbosStateError::UnsupportedVersion(arbos_version));
651 }
652
653 let backing_storage = Storage::<Detached>::detached(ARBOS_STATE_ADDRESS, B256::ZERO);
654 let chain_config_key = chain_config_root_key();
655 let features_sto = backing_storage.open_sub_storage_with_key(features_root_key());
656
657 Ok(ArbosState {
658 arbos_version,
659 max_arbos_version_supported: MAX_ARBOS_VERSION_SUPPORTED,
660 upgrade_version: StorageBackedUint64::new(B256::ZERO, UPGRADE_VERSION_OFFSET),
661 upgrade_timestamp: StorageBackedUint64::new(B256::ZERO, UPGRADE_TIMESTAMP_OFFSET),
662 network_fee_account: StorageBackedAddress::new(B256::ZERO, NETWORK_FEE_ACCOUNT_OFFSET),
663 l1_pricing_state: L1PricingState::open(
664 backing_storage.open_sub_storage_with_key(l1_pricing_root_key()),
665 arbos_version,
666 ),
667 l2_pricing_state: L2PricingState::open(
668 backing_storage.open_sub_storage_with_key(l2_pricing_root_key()),
669 arbos_version,
670 ),
671 retryable_state: RetryableState::open(
672 backing_storage.open_sub_storage_with_key(retryables_root_key()),
673 arbos_version,
674 ),
675 address_table: address_table::open_address_table(
676 backing_storage.open_sub_storage_with_key(address_table_root_key()),
677 ),
678 chain_owners: address_set::open_address_set(
679 backing_storage.open_sub_storage_with_key(chain_owner_root_key()),
680 ),
681 send_merkle_accumulator: merkle_accumulator::open_merkle_accumulator(
682 backing_storage.open_sub_storage_with_key(send_merkle_root_key()),
683 ),
684 programs: Programs::open(
685 arbos_version,
686 backing_storage.open_sub_storage_with_key(programs_root_key()),
687 ),
688 blockhashes: blockhash::open_blockhashes(
689 backing_storage.open_sub_storage_with_key(blockhashes_root_key()),
690 ),
691 chain_id: StorageBackedBigUint::new(B256::ZERO, CHAIN_ID_OFFSET),
692 chain_config: StorageBackedBytes::new(chain_config_key),
693 genesis_block_num: StorageBackedUint64::new(B256::ZERO, GENESIS_BLOCK_NUM_OFFSET),
694 infra_fee_account: StorageBackedAddress::new(B256::ZERO, INFRA_FEE_ACCOUNT_OFFSET),
695 brotli_compression_level: StorageBackedUint64::new(
696 B256::ZERO,
697 BROTLI_COMPRESSION_LEVEL_OFFSET,
698 ),
699 native_token_enabled_from_time: StorageBackedUint64::new(
700 B256::ZERO,
701 NATIVE_TOKEN_ENABLED_FROM_TIME_OFFSET,
702 ),
703 native_token_owners: address_set::open_address_set(
704 backing_storage.open_sub_storage_with_key(native_token_owner_root_key()),
705 ),
706 transaction_filtering_enabled_from_time: StorageBackedUint64::new(
707 B256::ZERO,
708 TRANSACTION_FILTERING_ENABLED_FROM_TIME_OFFSET,
709 ),
710 transaction_filterers: address_set::open_address_set(
711 backing_storage.open_sub_storage_with_key(transaction_filtering_root_key()),
712 ),
713 features: features::open_features(features_sto.base_key(), 0),
714 filtered_funds_recipient: StorageBackedAddress::new(
715 B256::ZERO,
716 FILTERED_FUNDS_RECIPIENT_OFFSET,
717 ),
718 filtered_transactions: FilteredTransactionsState::open(Storage::<Detached>::detached(
719 FILTERED_TX_STATE_ADDRESS,
720 B256::ZERO,
721 )),
722 collect_tips: StorageBackedUint64::new(B256::ZERO, COLLECT_TIPS_OFFSET),
723 backing_storage,
724 burner,
725 })
726}