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 buf = [0u8; 64];
62 let sk_len = storage_key.len();
63 buf[..sk_len].copy_from_slice(storage_key);
64 buf[sk_len..sk_len + BOUNDARY].copy_from_slice(&key_bytes[..BOUNDARY]);
65 let h = keccak256(&buf[..sk_len + BOUNDARY]);
66
67 let mut mapped = [0u8; 32];
68 mapped[..BOUNDARY].copy_from_slice(&h.0[..BOUNDARY]);
69 mapped[BOUNDARY] = key_bytes[BOUNDARY];
70 U256::from_be_bytes(mapped)
71}
72
73pub fn map_slot_b256(storage_key: &[u8], key: &B256) -> U256 {
75 const BOUNDARY: usize = 31;
76
77 let mut buf = [0u8; 64];
78 let sk_len = storage_key.len();
79 buf[..sk_len].copy_from_slice(storage_key);
80 buf[sk_len..sk_len + BOUNDARY].copy_from_slice(&key.0[..BOUNDARY]);
81 let h = keccak256(&buf[..sk_len + BOUNDARY]);
82
83 let mut mapped = [0u8; 32];
84 mapped[..BOUNDARY].copy_from_slice(&h.0[..BOUNDARY]);
85 mapped[BOUNDARY] = key.0[BOUNDARY];
86 U256::from_be_bytes(mapped)
87}
88
89pub fn derive_subspace_key(parent_key: &[u8], sub_key: &[u8]) -> B256 {
93 let p_len = parent_key.len();
94 let s_len = sub_key.len();
95 if p_len + s_len <= 64 {
96 let mut buf = [0u8; 64];
97 buf[..p_len].copy_from_slice(parent_key);
98 buf[p_len..p_len + s_len].copy_from_slice(sub_key);
99 keccak256(&buf[..p_len + s_len])
100 } else {
101 let mut v = Vec::with_capacity(p_len + s_len);
102 v.extend_from_slice(parent_key);
103 v.extend_from_slice(sub_key);
104 keccak256(&v)
105 }
106}
107
108pub const ROOT_STORAGE_KEY: &[u8] = &[];
110
111#[inline]
113pub fn root_slot(offset: u64) -> U256 {
114 map_slot(ROOT_STORAGE_KEY, offset)
115}
116
117pub fn subspace_slot(subspace_key: &[u8], offset: u64) -> U256 {
121 let sub_storage_key = derive_subspace_key(ROOT_STORAGE_KEY, subspace_key);
122 map_slot(sub_storage_key.as_slice(), offset)
123}
124
125pub const CURRENT_TX_POSTER_FEE_OFFSET: u64 = 255;
132
133pub fn current_tx_poster_fee_slot() -> U256 {
135 map_slot(ROOT_STORAGE_KEY, CURRENT_TX_POSTER_FEE_OFFSET)
136}
137
138pub const CURRENT_RETRYABLE_OFFSET: u64 = 254;
143
144pub fn current_retryable_slot() -> U256 {
146 map_slot(ROOT_STORAGE_KEY, CURRENT_RETRYABLE_OFFSET)
147}
148
149pub const CURRENT_REDEEMER_OFFSET: u64 = 253;
153
154pub fn current_redeemer_slot() -> U256 {
156 map_slot(ROOT_STORAGE_KEY, CURRENT_REDEEMER_OFFSET)
157}
158
159pub fn l2_pricing_subspace() -> B256 {
163 derive_subspace_key(ROOT_STORAGE_KEY, L2_PRICING_SUBSPACE)
164}
165
166const GAS_CONSTRAINTS_SUBKEY: &[u8] = &[0];
168const MULTI_GAS_CONSTRAINTS_SUBKEY: &[u8] = &[1];
169const MULTI_GAS_BASE_FEES_SUBKEY: &[u8] = &[2];
170
171fn l2_vector_key(sub_key: &[u8]) -> B256 {
173 derive_subspace_key(l2_pricing_subspace().as_slice(), sub_key)
174}
175
176pub fn vector_length_slot(vector_key: &B256) -> U256 {
178 map_slot(vector_key.as_slice(), 0)
179}
180
181pub fn vector_element_key(vector_key: &B256, index: u64) -> B256 {
183 derive_subspace_key(vector_key.as_slice(), &index.to_be_bytes())
184}
185
186pub fn vector_element_field(vector_key: &B256, index: u64, offset: u64) -> U256 {
188 let elem = vector_element_key(vector_key, index);
189 map_slot(elem.as_slice(), offset)
190}
191
192pub fn gas_constraints_vec_key() -> B256 {
194 l2_vector_key(GAS_CONSTRAINTS_SUBKEY)
195}
196
197pub fn multi_gas_constraints_vec_key() -> B256 {
199 l2_vector_key(MULTI_GAS_CONSTRAINTS_SUBKEY)
200}
201
202pub fn multi_gas_base_fees_subspace() -> B256 {
204 l2_vector_key(MULTI_GAS_BASE_FEES_SUBKEY)
205}