1use alloy_primitives::{Address, Bytes, U256, address};
9use revm::state::Bytecode;
10use tempo_contracts::{
11 ARACHNID_CREATE2_FACTORY_ADDRESS, CREATEX_ADDRESS, CreateX, MULTICALL3_ADDRESS, Multicall3,
12 PERMIT2_ADDRESS, Permit2, SAFE_DEPLOYER_ADDRESS, SafeDeployer,
13 contracts::ARACHNID_CREATE2_FACTORY_BYTECODE,
14};
15use tempo_precompiles::{
16 ACCOUNT_KEYCHAIN_ADDRESS, NONCE_PRECOMPILE_ADDRESS, STABLECOIN_DEX_ADDRESS,
17 TIP_FEE_MANAGER_ADDRESS, TIP20_FACTORY_ADDRESS, TIP403_REGISTRY_ADDRESS,
18 VALIDATOR_CONFIG_ADDRESS, VALIDATOR_CONFIG_V2_ADDRESS,
19 error::TempoPrecompileError,
20 storage::{PrecompileStorageProvider, StorageCtx},
21 tip20::{ISSUER_ROLE, ITIP20, TIP20Token},
22 tip20_factory::TIP20Factory,
23 validator_config,
24};
25
26pub use tempo_contracts::precompiles::{
27 ALPHA_USD_ADDRESS, BETA_USD_ADDRESS, PATH_USD_ADDRESS, THETA_USD_ADDRESS,
28};
29
30pub const SIGNATURE_VERIFIER_ADDRESS: Address =
32 address!("0x5165300000000000000000000000000000000000");
33pub const ADDRESS_REGISTRY_ADDRESS: Address =
34 address!("0xFDC0000000000000000000000000000000000000");
35
36pub const TEMPO_PRECOMPILE_ADDRESSES: &[Address] = &[
38 NONCE_PRECOMPILE_ADDRESS,
39 STABLECOIN_DEX_ADDRESS,
40 TIP20_FACTORY_ADDRESS,
41 TIP403_REGISTRY_ADDRESS,
42 TIP_FEE_MANAGER_ADDRESS,
43 VALIDATOR_CONFIG_ADDRESS,
44 VALIDATOR_CONFIG_V2_ADDRESS,
45 ACCOUNT_KEYCHAIN_ADDRESS,
46 SIGNATURE_VERIFIER_ADDRESS,
47 ADDRESS_REGISTRY_ADDRESS,
48];
49
50pub const TEMPO_TIP20_TOKENS: &[Address] =
52 &[PATH_USD_ADDRESS, ALPHA_USD_ADDRESS, BETA_USD_ADDRESS, THETA_USD_ADDRESS];
53
54pub fn initialize_tempo_genesis(
70 storage: &mut impl PrecompileStorageProvider,
71 admin: Address,
72 recipient: Address,
73) -> Result<(), TempoPrecompileError> {
74 StorageCtx::enter(storage, || initialize_tempo_genesis_inner(admin, recipient))
75}
76
77pub fn initialize_tempo_genesis_inner(
80 admin: Address,
81 recipient: Address,
82) -> Result<(), TempoPrecompileError> {
83 let mut ctx = StorageCtx;
84
85 let sentinel = Bytecode::new_legacy(Bytes::from_static(&[0xef]));
87 for precompile in TEMPO_PRECOMPILE_ADDRESSES {
88 ctx.set_code(*precompile, sentinel.clone())?;
89 }
90
91 let path_usd_token_address = create_and_mint_token(
93 address!("20C0000000000000000000000000000000000000"),
94 "PathUSD",
95 "PathUSD",
96 "USD",
97 Address::ZERO,
98 admin,
99 recipient,
100 U256::from(u64::MAX),
101 )?;
102
103 let _alpha_usd_token_address = create_and_mint_token(
105 address!("20C0000000000000000000000000000000000001"),
106 "AlphaUSD",
107 "AlphaUSD",
108 "USD",
109 path_usd_token_address,
110 admin,
111 recipient,
112 U256::from(u64::MAX),
113 )?;
114
115 let _beta_usd_token_address = create_and_mint_token(
117 address!("20C0000000000000000000000000000000000002"),
118 "BetaUSD",
119 "BetaUSD",
120 "USD",
121 path_usd_token_address,
122 admin,
123 recipient,
124 U256::from(u64::MAX),
125 )?;
126
127 let _theta_usd_token_address = create_and_mint_token(
129 address!("20C0000000000000000000000000000000000003"),
130 "ThetaUSD",
131 "ThetaUSD",
132 "USD",
133 path_usd_token_address,
134 admin,
135 recipient,
136 U256::from(u64::MAX),
137 )?;
138
139 ctx.sstore(VALIDATOR_CONFIG_ADDRESS, validator_config::slots::OWNER, admin.into_word().into())?;
141
142 ctx.set_code(
144 MULTICALL3_ADDRESS,
145 Bytecode::new_legacy(Bytes::from_static(&Multicall3::DEPLOYED_BYTECODE)),
146 )?;
147 ctx.set_code(
148 CREATEX_ADDRESS,
149 Bytecode::new_legacy(Bytes::from_static(&CreateX::DEPLOYED_BYTECODE)),
150 )?;
151 ctx.set_code(
152 SAFE_DEPLOYER_ADDRESS,
153 Bytecode::new_legacy(Bytes::from_static(&SafeDeployer::DEPLOYED_BYTECODE)),
154 )?;
155 ctx.set_code(
156 PERMIT2_ADDRESS,
157 Bytecode::new_legacy(Bytes::from_static(&Permit2::DEPLOYED_BYTECODE)),
158 )?;
159 ctx.set_code(
160 ARACHNID_CREATE2_FACTORY_ADDRESS,
161 Bytecode::new_legacy(ARACHNID_CREATE2_FACTORY_BYTECODE),
162 )?;
163
164 Ok(())
165}
166
167#[allow(clippy::too_many_arguments)]
169fn create_and_mint_token(
170 address: Address,
171 symbol: &str,
172 name: &str,
173 currency: &str,
174 quote_token: Address,
175 admin: Address,
176 recipient: Address,
177 mint_amount: U256,
178) -> Result<Address, TempoPrecompileError> {
179 let mut tip20_factory = TIP20Factory::new();
180
181 let token_address = tip20_factory.create_token_reserved_address(
182 address,
183 name,
184 symbol,
185 currency,
186 quote_token,
187 admin,
188 )?;
189
190 let mut token = TIP20Token::from_address(token_address)?;
191 token.grant_role_internal(admin, *ISSUER_ROLE)?;
192 token.mint(admin, ITIP20::mintCall { to: recipient, amount: mint_amount })?;
193 if admin != recipient {
194 token.mint(admin, ITIP20::mintCall { to: admin, amount: mint_amount })?;
195 }
196
197 Ok(token_address)
198}