eigenlayer_contract_deployer/
deploy.rs

1use alloy_primitives::{Address, U256};
2use alloy_sol_types::SolCall;
3use color_eyre::eyre::eyre;
4use eigensdk::utils::slashing::sdk::mockerc20::MockERC20;
5use serde::{Deserialize, Serialize};
6use tracing::info;
7
8use crate::bindings::core::islashingregistrycoordinator::ISlashingRegistryCoordinatorTypes::OperatorSetParam;
9use crate::bindings::core::slashingregistrycoordinator::IStakeRegistryTypes::StrategyParams;
10use crate::bindings::{
11    BLSApkRegistry, IStrategy, IndexRegistry, InstantSlasher, OperatorStateRetriever,
12    PauserRegistry, ProxyAdmin, SlashingRegistryCoordinator, SocketRegistry,
13    SquaringServiceManager, SquaringTask, StakeRegistry, StrategyFactory,
14};
15use crate::helpers::{deploy_empty_proxy, get_provider_from_signer, get_receipt, upgrade_proxy};
16
17/// Data structure to hold deployed contract addresses
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct DeployedContracts {
20    /// Proxy admin address
21    pub proxy_admin: Address,
22    /// Squaring service manager address
23    pub squaring_service_manager: Address,
24    /// Squaring service manager implementation address
25    pub squaring_service_manager_impl: Address,
26    /// Squaring task manager address
27    pub squaring_task_manager: Address,
28    /// Registry coordinator address
29    pub registry_coordinator: Address,
30    /// BLS APK registry address
31    pub bls_apk_registry: Address,
32    /// Index registry address
33    pub index_registry: Address,
34    /// Stake registry address
35    pub stake_registry: Address,
36    /// Operator state retriever address
37    pub operator_state_retriever: Address,
38    /// Strategy address
39    pub strategy: Address,
40    /// Pauser registry address
41    pub pauser_registry: Address,
42    /// Token address
43    pub token: Address,
44    /// Instant slasher address
45    pub instant_slasher: Address,
46    /// Socket registry address
47    pub socket_registry: Address,
48}
49
50/// Deploys the EigenLayer AVS contracts
51///
52/// This function deploys all the necessary contracts for the EigenLayer AVS
53/// following the logic from the provided Solidity script.
54///
55/// # Arguments
56///
57/// * `http_endpoint` - HTTP endpoint for the RPC provider
58/// * `private_key` - Private key for the deployer account
59/// * `num_quorums` - Number of quorums
60/// * `permission_controller_address` - Address of the permission controller
61/// * `allocation_manager_address` - Address of the allocation manager
62/// * `avs_directory_addr` - Address of the AVS directory
63/// * `delegation_manager_addr` - Address of the delegation manager
64/// * `eigen_layer_pauser_reg_addr` - Address of the EigenLayer pauser registry
65/// * `rewards_coordinator_addr` - Address of the rewards coordinator
66/// * `task_generator_addr` - Address of the task generator
67/// * `aggregator_addr` - Address of the aggregator
68/// * `task_response_window_block` - Task response window in blocks
69///
70/// # Returns
71///
72/// * `Result<DeployedContracts>` - The deployed contract addresses
73///
74/// # Errors
75///
76/// * `color_eyre::eyre::Error` - If any deployment or transaction fails
77#[allow(clippy::too_many_arguments, clippy::too_many_lines)]
78pub async fn deploy_avs_contracts(
79    http_endpoint: &str,
80    private_key: &str,
81    deployer_address: Address,
82    num_quorums: u32,
83    permission_controller_address: Address,
84    allocation_manager_address: Address,
85    avs_directory_addr: Address,
86    delegation_manager_addr: Address,
87    pauser_registry_addr: Address,
88    rewards_coordinator_addr: Address,
89    strategy_factory_addr: Address,
90    task_generator_addr: Address,
91    aggregator_addr: Address,
92    task_response_window_block: u32,
93) -> color_eyre::eyre::Result<DeployedContracts> {
94    info!("Starting AVS deployment...");
95
96    let wallet = get_provider_from_signer(private_key, http_endpoint);
97
98    info!("Deployer address: {}", deployer_address);
99
100    info!("Initializing token...");
101    let mock_erc20 = MockERC20::deploy(wallet.clone()).await?;
102    // let &mock_erc20_addr = mock_erc20.address();
103    let token = mock_erc20;
104    // let token = MockERC20::new(TOKEN_ADDR, wallet.clone());
105
106    let mint_call = token.mint(
107        deployer_address,
108        U256::from(15_000_000_000_000_000_000_000_u128),
109    );
110    let mint_receipt = get_receipt(mint_call).await?;
111    info!("Token mint receipt: {:?}", mint_receipt);
112    if !mint_receipt.status() {
113        return Err(eyre!("Failed to mint tokens to deployer"));
114    }
115    info!("Minted tokens to deployer: {}", deployer_address);
116
117    let mint_call = token.mint(
118        task_generator_addr,
119        U256::from(30_000_000_000_000_000_000_000_u128),
120    );
121    let mint_receipt = get_receipt(mint_call).await?;
122    info!("Token mint receipt: {:?}", mint_receipt);
123    if !mint_receipt.status() {
124        return Err(eyre!("Failed to mint tokens to task generator"));
125    }
126    info!("Minted tokens to task generator: {}", task_generator_addr);
127
128    let balance = token.balanceOf(deployer_address).call().await?._0;
129    info!("Deployer token balance: {}", balance);
130    let balance = token.balanceOf(task_generator_addr).call().await?._0;
131    info!("Task generator token balance: {}", balance);
132
133    let token_total_supply = token.totalSupply().call().await?._0;
134    info!("Token total supply: {}", token_total_supply);
135
136    let strategy_factory = StrategyFactory::new(strategy_factory_addr, wallet.clone());
137
138    let new_strategy_call = strategy_factory.deployNewStrategy(*token.address());
139    let new_strategy_receipt = get_receipt(new_strategy_call).await?;
140    let strategy_addr = if let Some(last_log) = new_strategy_receipt.logs().last() {
141        let data = last_log.data().data.clone();
142        if data.len() >= 32 {
143            // The address is in the last 20 bytes of the 32-byte data field
144            let mut addr_bytes = [0u8; 20];
145            addr_bytes.copy_from_slice(&data[12..32]);
146            Address::from_slice(&addr_bytes)
147        } else {
148            return Err(color_eyre::eyre::eyre!("Invalid log data format"));
149        }
150    } else {
151        return Err(eyre!("Failed to get strategy address from receipt"));
152    };
153    info!("Strategy deployed at: {}", strategy_addr);
154    let squaring_strategy = IStrategy::new(strategy_addr, wallet.clone());
155
156    // Deploy ProxyAdmin
157    info!("Deploying ProxyAdmin...");
158    let proxy_admin = ProxyAdmin::deploy(&wallet).await?;
159    let &proxy_admin_addr = proxy_admin.address();
160    info!("ProxyAdmin deployed at: {}", proxy_admin_addr);
161
162    // First, deploy all empty proxies
163    info!("Deploying empty proxies...");
164    let squaring_service_manager_proxy = deploy_empty_proxy(&wallet, proxy_admin_addr).await?;
165    let stake_registry_proxy = deploy_empty_proxy(&wallet, proxy_admin_addr).await?;
166    let squaring_task_manager_proxy = deploy_empty_proxy(&wallet, proxy_admin_addr).await?;
167    let slashing_registry_coordinator_proxy = deploy_empty_proxy(&wallet, proxy_admin_addr).await?;
168    let bls_apk_registry_proxy = deploy_empty_proxy(&wallet, proxy_admin_addr).await?;
169    let index_registry_proxy = deploy_empty_proxy(&wallet, proxy_admin_addr).await?;
170    let socket_registry_proxy = deploy_empty_proxy(&wallet, proxy_admin_addr).await?;
171    let instant_slasher_proxy = deploy_empty_proxy(&wallet, proxy_admin_addr).await?;
172
173    // Deploy OperatorStateRetriever
174    info!("Deploying OperatorStateRetriever...");
175    let operator_state_retriever = OperatorStateRetriever::deploy(&wallet).await?;
176    let &operator_state_retriever_addr = operator_state_retriever.address();
177    info!(
178        "OperatorStateRetriever deployed at: {}",
179        operator_state_retriever_addr
180    );
181
182    // Deploy implementation contracts
183    info!("Deploying implementation contracts...");
184
185    // Deploy StakeRegistry implementation
186    let stake_registry_impl = StakeRegistry::deploy(
187        &wallet,
188        slashing_registry_coordinator_proxy,
189        delegation_manager_addr,
190        avs_directory_addr,
191        allocation_manager_address,
192    )
193    .await?;
194    let &stake_registry_impl_addr = stake_registry_impl.address();
195    info!(
196        "StakeRegistry implementation deployed at: {}",
197        stake_registry_impl_addr
198    );
199
200    // Deploy BLSApkRegistry implementation
201    let bls_apk_registry_impl =
202        BLSApkRegistry::deploy(&wallet, slashing_registry_coordinator_proxy).await?;
203    let &bls_apk_registry_impl_addr = bls_apk_registry_impl.address();
204    info!(
205        "BLSApkRegistry implementation deployed at: {}",
206        bls_apk_registry_impl_addr
207    );
208
209    // Deploy IndexRegistry implementation
210    let index_registry_impl =
211        IndexRegistry::deploy(&wallet, slashing_registry_coordinator_proxy).await?;
212    let &index_registry_impl_addr = index_registry_impl.address();
213    info!(
214        "IndexRegistry implementation deployed at: {}",
215        index_registry_impl_addr
216    );
217
218    // Deploy InstantSlasher implementation
219    let instant_slasher_impl = InstantSlasher::deploy(
220        &wallet,
221        allocation_manager_address,
222        slashing_registry_coordinator_proxy,
223        squaring_task_manager_proxy,
224    )
225    .await?;
226    let &instant_slasher_impl_addr = instant_slasher_impl.address();
227    info!(
228        "InstantSlasher implementation deployed at: {}",
229        instant_slasher_impl_addr
230    );
231
232    // Deploy RegistryCoordinator implementation
233    let registry_coordinator_impl = SlashingRegistryCoordinator::deploy(
234        &wallet,
235        stake_registry_proxy,
236        bls_apk_registry_proxy,
237        index_registry_proxy,
238        socket_registry_proxy,
239        allocation_manager_address,
240        pauser_registry_addr,
241        "v1.4.0-testnet-holesky".to_string(),
242    )
243    .await?;
244    let &registry_coordinator_impl_addr = registry_coordinator_impl.address();
245    info!(
246        "Registry Coordinator implementation deployed at: {}",
247        registry_coordinator_impl_addr
248    );
249
250    let pausers = vec![deployer_address, deployer_address];
251    let pauser_registry = PauserRegistry::deploy(&wallet, pausers, deployer_address).await?;
252    let &pauser_registry_addr = pauser_registry.address();
253    info!("Pauser Registry deployed at: {}", pauser_registry_addr);
254
255    let mut quorums_operator_set_params = Vec::with_capacity(num_quorums as usize);
256
257    let mut quorums_strategy_params = Vec::with_capacity(num_quorums as usize);
258    let deployed_strategies = [squaring_strategy];
259    let num_strategies = deployed_strategies.len();
260
261    for _i in 0..num_quorums {
262        let quorum_operator_set_param = OperatorSetParam {
263            maxOperatorCount: 10000u32,
264            kickBIPsOfOperatorStake: 15000u16,
265            kickBIPsOfTotalStake: 100u16,
266        };
267        quorums_operator_set_params.push(quorum_operator_set_param);
268
269        let mut quorum_strategy_param = Vec::with_capacity(num_strategies);
270        let multiplier = alloy_primitives::Uint::<96, 2>::from(1u64);
271        for j in deployed_strategies.iter().take(num_strategies) {
272            let strategy_param = StrategyParams {
273                strategy: *j.address(),
274                multiplier,
275            };
276            quorum_strategy_param.push(strategy_param);
277        }
278        quorums_strategy_params.push(quorum_strategy_param);
279    }
280
281    // Initialize RegistryCoordinator
282    let registry_coordinator_init_data = SlashingRegistryCoordinator::initializeCall {
283        initialOwner: deployer_address,
284        churnApprover: deployer_address,
285        ejector: deployer_address,
286        initialPausedStatus: U256::from(0),
287        avs: squaring_service_manager_proxy,
288    }
289    .abi_encode()
290    .into();
291
292    // Upgrade proxies with implementations
293    info!("Upgrading proxies with implementations...");
294
295    // Upgrade StakeRegistry
296    upgrade_proxy(
297        &wallet,
298        proxy_admin_addr,
299        stake_registry_proxy,
300        stake_registry_impl_addr,
301        alloy_primitives::Bytes::new(),
302    )
303    .await?;
304    info!("StakeRegistry proxy upgraded");
305
306    // Upgrade BLSApkRegistry
307    upgrade_proxy(
308        &wallet,
309        proxy_admin_addr,
310        bls_apk_registry_proxy,
311        bls_apk_registry_impl_addr,
312        alloy_primitives::Bytes::new(),
313    )
314    .await?;
315    info!("BLSApkRegistry proxy upgraded");
316
317    // Upgrade IndexRegistry
318    upgrade_proxy(
319        &wallet,
320        proxy_admin_addr,
321        index_registry_proxy,
322        index_registry_impl_addr,
323        alloy_primitives::Bytes::new(),
324    )
325    .await?;
326    info!("IndexRegistry proxy upgraded");
327
328    // Upgrade RegistryCoordinator with initialization
329    upgrade_proxy(
330        &wallet,
331        proxy_admin_addr,
332        slashing_registry_coordinator_proxy,
333        registry_coordinator_impl_addr,
334        registry_coordinator_init_data,
335    )
336    .await?;
337    info!("RegistryCoordinator proxy upgraded and initialized");
338
339    // Deploy SquaringServiceManager implementation
340    let squaring_service_manager_impl = SquaringServiceManager::deploy(
341        &wallet,
342        avs_directory_addr,
343        slashing_registry_coordinator_proxy,
344        stake_registry_proxy,
345        rewards_coordinator_addr,
346        squaring_task_manager_proxy,
347        permission_controller_address,
348        allocation_manager_address,
349    )
350    .await?;
351    let &squaring_service_manager_impl_addr = squaring_service_manager_impl.address();
352    info!(
353        "SquaringServiceManager implementation deployed at: {}",
354        squaring_service_manager_impl_addr
355    );
356
357    // Deploy SquaringTask implementation
358    let squaring_task_impl = SquaringTask::deploy(
359        &wallet,
360        slashing_registry_coordinator_proxy,
361        task_response_window_block,
362    )
363    .await?;
364    let &squaring_task_impl_addr = squaring_task_impl.address();
365    info!(
366        "SquaringTask implementation deployed at: {}",
367        squaring_task_impl_addr
368    );
369
370    // Initialize SquaringServiceManager
371    let service_manager_init_data = SquaringServiceManager::initializeCall {
372        initialOwner: deployer_address,
373        rewardsInitiator: deployer_address,
374    }
375    .abi_encode()
376    .into();
377
378    // Upgrade SquaringServiceManager with initialization
379    upgrade_proxy(
380        &wallet,
381        proxy_admin_addr,
382        squaring_service_manager_proxy,
383        squaring_service_manager_impl_addr,
384        service_manager_init_data,
385    )
386    .await?;
387    info!("SquaringServiceManager proxy upgraded and initialized");
388
389    // Initialize SquaringTask
390    let task_manager_init_data = SquaringTask::initializeCall {
391        _aggregator: aggregator_addr,
392        _generator: task_generator_addr,
393        initialOwner: deployer_address,
394    }
395    .abi_encode()
396    .into();
397
398    // Upgrade SquaringTask with initialization
399    upgrade_proxy(
400        &wallet,
401        proxy_admin_addr,
402        squaring_task_manager_proxy,
403        squaring_task_impl_addr,
404        task_manager_init_data,
405    )
406    .await?;
407    info!("SquaringTask proxy upgraded and initialized");
408
409    // Upgrade InstantSlasher
410    upgrade_proxy(
411        &wallet,
412        proxy_admin_addr,
413        instant_slasher_proxy,
414        instant_slasher_impl_addr,
415        alloy_primitives::Bytes::new(),
416    )
417    .await?;
418    info!("InstantSlasher proxy upgraded");
419
420    // Deploy SocketRegistry implementation
421    let socket_registry_impl =
422        SocketRegistry::deploy(&wallet, slashing_registry_coordinator_proxy).await?;
423    let &socket_registry_impl_addr = socket_registry_impl.address();
424    info!(
425        "SocketRegistry implementation deployed at: {}",
426        socket_registry_impl_addr
427    );
428
429    // Upgrade SocketRegistry
430    upgrade_proxy(
431        &wallet,
432        proxy_admin_addr,
433        socket_registry_proxy,
434        socket_registry_impl_addr,
435        alloy_primitives::Bytes::new(),
436    )
437    .await?;
438    info!("SocketRegistry proxy upgraded");
439
440    info!("AVS deployment completed successfully!");
441
442    // Return deployed contract addresses
443    let deployed_contracts = DeployedContracts {
444        proxy_admin: proxy_admin_addr,
445        squaring_service_manager: squaring_service_manager_proxy,
446        squaring_service_manager_impl: squaring_service_manager_impl_addr,
447        squaring_task_manager: squaring_task_manager_proxy,
448        registry_coordinator: slashing_registry_coordinator_proxy,
449        bls_apk_registry: bls_apk_registry_proxy,
450        index_registry: index_registry_proxy,
451        stake_registry: stake_registry_proxy,
452        operator_state_retriever: operator_state_retriever_addr,
453        strategy: *deployed_strategies[0].address(),
454        pauser_registry: pauser_registry_addr,
455        token: *token.address(),
456        instant_slasher: instant_slasher_proxy,
457        socket_registry: socket_registry_proxy,
458    };
459
460    Ok(deployed_contracts)
461}