1use alloy_primitives::{Address, B256, U256};
2use revm::Database;
3
4use crate::{
5 burn::Burner,
6 retryables::{self, RetryableState},
7};
8
9use super::ArbosState;
10
11#[derive(Debug, Clone)]
13pub struct InitRetryableData {
14 pub id: B256,
15 pub timeout: u64,
16 pub from: Address,
17 pub to: Option<Address>,
18 pub callvalue: U256,
19 pub beneficiary: Address,
20 pub calldata: Vec<u8>,
21}
22
23#[derive(Debug, Clone)]
25pub struct AccountInitInfo {
26 pub addr: Address,
27 pub nonce: u64,
28 pub balance: U256,
29 pub contract_info: Option<ContractInitInfo>,
30 pub aggregator_info: Option<AggregatorInitInfo>,
31}
32
33#[derive(Debug, Clone)]
35pub struct ContractInitInfo {
36 pub code: Vec<u8>,
37 pub storage: Vec<(U256, U256)>,
38}
39
40#[derive(Debug, Clone)]
42pub struct AggregatorInitInfo {
43 pub fee_collector: Address,
44}
45
46#[derive(Debug, Clone)]
52pub struct GenesisBlockInfo {
53 pub parent_hash: B256,
54 pub block_number: u64,
55 pub timestamp: u64,
56 pub state_root: B256,
57 pub gas_limit: u64,
58 pub base_fee: u64,
59 pub nonce: u64,
60 pub arbos_format_version: u64,
61}
62
63pub fn make_genesis_block(
65 parent_hash: B256,
66 block_number: u64,
67 timestamp: u64,
68 state_root: B256,
69 initial_arbos_version: u64,
70) -> GenesisBlockInfo {
71 use crate::l2_pricing;
72
73 GenesisBlockInfo {
74 parent_hash,
75 block_number,
76 timestamp,
77 state_root,
78 gas_limit: l2_pricing::GETH_BLOCK_GAS_LIMIT,
79 base_fee: l2_pricing::INITIAL_BASE_FEE_WEI,
80 nonce: 1, arbos_format_version: initial_arbos_version,
82 }
83}
84
85pub fn initialize_retryables<D: Database>(
95 rs: &RetryableState<D>,
96 mut retryables_data: Vec<InitRetryableData>,
97 current_timestamp: u64,
98) -> Result<(Vec<(Address, U256)>, Vec<(Address, U256)>), ()> {
99 let mut balance_credits = Vec::new();
100 let mut active_retryables = Vec::new();
101
102 for r in retryables_data.drain(..) {
104 if r.timeout <= current_timestamp {
105 balance_credits.push((r.beneficiary, r.callvalue));
106 continue;
107 }
108 active_retryables.push(r);
109 }
110
111 active_retryables.sort_by(|a, b| a.timeout.cmp(&b.timeout).then_with(|| a.id.cmp(&b.id)));
113
114 let mut escrow_credits = Vec::new();
115
116 for r in &active_retryables {
117 let escrow_addr = retryables::retryable_escrow_address(r.id);
118 escrow_credits.push((escrow_addr, r.callvalue));
119 rs.create_retryable(
120 r.id,
121 r.timeout,
122 r.from,
123 r.to,
124 r.callvalue,
125 r.beneficiary,
126 &r.calldata,
127 )?;
128 }
129
130 Ok((balance_credits, escrow_credits))
131}
132
133pub fn initialize_arbos_account<D: Database, B: Burner>(
138 arbos_state: &ArbosState<D, B>,
139 account: &AccountInitInfo,
140) -> Result<(), ()> {
141 if let Some(ref aggregator) = account.aggregator_info {
142 let poster_table = arbos_state.l1_pricing_state.batch_poster_table();
143 let is_poster = poster_table.contains_poster(account.addr)?;
144 if is_poster {
145 let poster = poster_table.open_poster(account.addr, false)?;
146 poster.set_pay_to(aggregator.fee_collector)?;
147 }
148 }
149 Ok(())
150}
151
152#[derive(Debug)]
165pub struct GenesisInitResult {
166 pub balance_credits: Vec<(Address, U256)>,
168 pub escrow_credits: Vec<(Address, U256)>,
170 pub accounts: Vec<AccountInitInfo>,
172}
173
174pub fn initialize_arbos_in_database<D: Database, B: Burner>(
180 arbos_state: &ArbosState<D, B>,
181 chain_owner: Address,
182 address_table_entries: Vec<Address>,
183 retryable_data: Vec<InitRetryableData>,
184 accounts: Vec<AccountInitInfo>,
185 current_timestamp: u64,
186) -> Result<GenesisInitResult, ()> {
187 if chain_owner != Address::ZERO {
189 arbos_state.chain_owners.add(chain_owner)?;
190 }
191
192 let table_size = arbos_state.address_table.size()?;
194 if table_size != 0 {
195 return Err(());
196 }
197 for (i, addr) in address_table_entries.iter().enumerate() {
198 let slot = arbos_state.address_table.register(*addr)?;
199 if slot != i as u64 {
200 return Err(());
201 }
202 }
203
204 let (balance_credits, escrow_credits) = initialize_retryables(
206 &arbos_state.retryable_state,
207 retryable_data,
208 current_timestamp,
209 )?;
210
211 for account in &accounts {
213 initialize_arbos_account(arbos_state, account)?;
214 }
215
216 Ok(GenesisInitResult {
217 balance_credits,
218 escrow_credits,
219 accounts,
220 })
221}