arb_precompiles/
storage_slot.rs1use alloy_primitives::{keccak256, B256, U256};
2
3pub const ARBOS_STATE_ADDRESS: alloy_primitives::Address = alloy_primitives::Address::new([
5 0xa4, 0xb0, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
6 0xff, 0xff, 0xff, 0xff,
7]);
8
9pub const L1_PRICING_SUBSPACE: &[u8] = &[0];
11pub const L2_PRICING_SUBSPACE: &[u8] = &[1];
12pub const RETRYABLES_SUBSPACE: &[u8] = &[2];
13pub const ADDRESS_TABLE_SUBSPACE: &[u8] = &[3];
14pub const CHAIN_OWNER_SUBSPACE: &[u8] = &[4];
15pub const SEND_MERKLE_SUBSPACE: &[u8] = &[5];
16pub const BLOCKHASHES_SUBSPACE: &[u8] = &[6];
17pub const CHAIN_CONFIG_SUBSPACE: &[u8] = &[7];
18pub const PROGRAMS_SUBSPACE: &[u8] = &[8];
19pub const FEATURES_SUBSPACE: &[u8] = &[9];
20pub const NATIVE_TOKEN_SUBSPACE: &[u8] = &[10];
21pub const TRANSACTION_FILTERER_SUBSPACE: &[u8] = &[11];
22
23pub const PROGRAMS_PARAMS_KEY: &[u8] = &[0];
25pub const PROGRAMS_DATA_KEY: &[u8] = &[1];
26pub const CACHE_MANAGERS_KEY: &[u8] = &[4];
27
28pub const CACHE_MANAGERS_SUBSPACE: &[u8] = CACHE_MANAGERS_KEY;
31
32pub const FILTERED_TX_STATE_ADDRESS: alloy_primitives::Address = alloy_primitives::Address::new([
34 0xa4, 0xb0, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 0x00, 0x00, 0x00, 0x01,
36]);
37
38pub const VERSION_OFFSET: u64 = 0;
40pub const UPGRADE_VERSION_OFFSET: u64 = 1;
41pub const UPGRADE_TIMESTAMP_OFFSET: u64 = 2;
42pub const NETWORK_FEE_ACCOUNT_OFFSET: u64 = 3;
43pub const CHAIN_ID_OFFSET: u64 = 4;
44pub const GENESIS_BLOCK_NUM_OFFSET: u64 = 5;
45pub const INFRA_FEE_ACCOUNT_OFFSET: u64 = 6;
46pub const BROTLI_COMPRESSION_LEVEL_OFFSET: u64 = 7;
47pub const NATIVE_TOKEN_ENABLED_FROM_TIME_OFFSET: u64 = 8;
48pub const TX_FILTERING_ENABLED_FROM_TIME_OFFSET: u64 = 9;
49pub const FILTERED_FUNDS_RECIPIENT_OFFSET: u64 = 10;
50
51pub fn map_slot(storage_key: &[u8], offset: u64) -> U256 {
56 const BOUNDARY: usize = 31;
57
58 let mut key_bytes = [0u8; 32];
59 key_bytes[24..32].copy_from_slice(&offset.to_be_bytes());
60
61 let mut data = Vec::with_capacity(storage_key.len() + BOUNDARY);
62 data.extend_from_slice(storage_key);
63 data.extend_from_slice(&key_bytes[..BOUNDARY]);
64 let h = keccak256(&data);
65
66 let mut mapped = [0u8; 32];
67 mapped[..BOUNDARY].copy_from_slice(&h.0[..BOUNDARY]);
68 mapped[BOUNDARY] = key_bytes[BOUNDARY];
69 U256::from_be_bytes(mapped)
70}
71
72pub fn map_slot_b256(storage_key: &[u8], key: &B256) -> U256 {
74 const BOUNDARY: usize = 31;
75
76 let mut data = Vec::with_capacity(storage_key.len() + BOUNDARY);
77 data.extend_from_slice(storage_key);
78 data.extend_from_slice(&key.0[..BOUNDARY]);
79 let h = keccak256(&data);
80
81 let mut mapped = [0u8; 32];
82 mapped[..BOUNDARY].copy_from_slice(&h.0[..BOUNDARY]);
83 mapped[BOUNDARY] = key.0[BOUNDARY];
84 U256::from_be_bytes(mapped)
85}
86
87pub fn derive_subspace_key(parent_key: &[u8], sub_key: &[u8]) -> B256 {
91 let mut combined = Vec::with_capacity(parent_key.len() + sub_key.len());
92 combined.extend_from_slice(parent_key);
93 combined.extend_from_slice(sub_key);
94 keccak256(&combined)
95}
96
97pub const ROOT_STORAGE_KEY: &[u8] = &[];
99
100#[inline]
102pub fn root_slot(offset: u64) -> U256 {
103 map_slot(ROOT_STORAGE_KEY, offset)
104}
105
106pub fn subspace_slot(subspace_key: &[u8], offset: u64) -> U256 {
110 let sub_storage_key = derive_subspace_key(ROOT_STORAGE_KEY, subspace_key);
111 map_slot(sub_storage_key.as_slice(), offset)
112}
113
114pub const CURRENT_TX_POSTER_FEE_OFFSET: u64 = 255;
121
122pub fn current_tx_poster_fee_slot() -> U256 {
124 map_slot(ROOT_STORAGE_KEY, CURRENT_TX_POSTER_FEE_OFFSET)
125}
126
127pub const CURRENT_RETRYABLE_OFFSET: u64 = 254;
132
133pub fn current_retryable_slot() -> U256 {
135 map_slot(ROOT_STORAGE_KEY, CURRENT_RETRYABLE_OFFSET)
136}
137
138pub const CURRENT_REDEEMER_OFFSET: u64 = 253;
142
143pub fn current_redeemer_slot() -> U256 {
145 map_slot(ROOT_STORAGE_KEY, CURRENT_REDEEMER_OFFSET)
146}
147
148pub fn l2_pricing_subspace() -> B256 {
152 derive_subspace_key(ROOT_STORAGE_KEY, L2_PRICING_SUBSPACE)
153}
154
155const GAS_CONSTRAINTS_SUBKEY: &[u8] = &[0];
157const MULTI_GAS_CONSTRAINTS_SUBKEY: &[u8] = &[1];
158const MULTI_GAS_BASE_FEES_SUBKEY: &[u8] = &[2];
159
160fn l2_vector_key(sub_key: &[u8]) -> B256 {
162 derive_subspace_key(l2_pricing_subspace().as_slice(), sub_key)
163}
164
165pub fn vector_length_slot(vector_key: &B256) -> U256 {
167 map_slot(vector_key.as_slice(), 0)
168}
169
170pub fn vector_element_key(vector_key: &B256, index: u64) -> B256 {
172 derive_subspace_key(vector_key.as_slice(), &index.to_be_bytes())
173}
174
175pub fn vector_element_field(vector_key: &B256, index: u64, offset: u64) -> U256 {
177 let elem = vector_element_key(vector_key, index);
178 map_slot(elem.as_slice(), offset)
179}
180
181pub fn gas_constraints_vec_key() -> B256 {
183 l2_vector_key(GAS_CONSTRAINTS_SUBKEY)
184}
185
186pub fn multi_gas_constraints_vec_key() -> B256 {
188 l2_vector_key(MULTI_GAS_CONSTRAINTS_SUBKEY)
189}
190
191pub fn multi_gas_base_fees_subspace() -> B256 {
193 l2_vector_key(MULTI_GAS_BASE_FEES_SUBKEY)
194}