blueprint_eigenlayer_testing_utils/
harness.rs1use crate::Error;
2use crate::env::setup_eigenlayer_test_environment;
3use alloy_primitives::address;
4use alloy_primitives::{Address, U256};
5use alloy_provider::Provider;
6use blueprint_auth::db::RocksDb;
7use blueprint_chain_setup::anvil::keys::inject_anvil_key;
8use blueprint_chain_setup::anvil::{AnvilTestnet, Container};
9use blueprint_core::{error, info};
10use blueprint_evm_extra::util::get_provider_http;
11use blueprint_manager_bridge::server::{Bridge, BridgeHandle};
12use blueprint_runner::config::{BlueprintEnvironment, ContextConfig, SupportedChains};
13use blueprint_runner::eigenlayer::config::EigenlayerProtocolSettings;
14use eigenlayer_contract_deployer::core::{
15 DelegationManagerConfig, DeployedCoreContracts, DeploymentConfigData, EigenPodManagerConfig,
16 RewardsCoordinatorConfig, StrategyFactoryConfig, StrategyManagerConfig,
17};
18use std::future::Future;
19use std::net::Ipv4Addr;
20use std::path::PathBuf;
21use tempfile::TempDir;
22use tokio::task::JoinHandle;
23use url::Url;
24
25pub struct EigenlayerTestHarness {
27 env: BlueprintEnvironment,
28 _temp_dir: TempDir,
29 _container: Container,
30 _auth_proxy: JoinHandle<Result<(), Error>>,
31 _bridge: BridgeHandle,
32}
33
34impl EigenlayerTestHarness {
35 pub async fn setup(
45 owner_private_key: &str,
46 test_dir: TempDir,
47 testnet: AnvilTestnet,
48 eigenlayer_protocol_settings: Option<EigenlayerProtocolSettings>,
49 ) -> Result<Self, Error> {
50 Self::setup_with_context(
51 owner_private_key,
52 test_dir,
53 testnet,
54 eigenlayer_protocol_settings,
55 )
56 .await
57 }
58}
59
60impl EigenlayerTestHarness {
61 pub async fn setup_with_context(
77 owner_private_key: &str,
78 test_dir: TempDir,
79 testnet: AnvilTestnet,
80 eigenlayer_protocol_settings: Option<EigenlayerProtocolSettings>,
81 ) -> Result<Self, Error> {
82 let keystore_path = test_dir.path().join("keystore");
84 inject_anvil_key(&keystore_path, owner_private_key)?;
85
86 let eigenlayer_protocol_settings = match eigenlayer_protocol_settings {
87 Some(settings) => settings,
88 None => setup_eigenlayer_test_environment(testnet.http_endpoint.clone()).await,
89 };
90
91 let data_dir = test_dir.path().join("data");
92 tokio::fs::create_dir_all(&data_dir).await?;
93
94 const DEFAULT_AUTH_PROXY_PORT: u16 = 50051;
96 let (auth_proxy_db, auth_proxy_task) =
97 run_auth_proxy(test_dir.path().to_path_buf(), DEFAULT_AUTH_PROXY_PORT).await?;
98
99 let auth_proxy = tokio::spawn(auth_proxy_task);
100
101 let runtime_dir = test_dir.path().join("runtime");
103 tokio::fs::create_dir_all(&runtime_dir).await?;
104
105 let bridge = Bridge::new(
106 runtime_dir,
107 String::from("service"),
108 auth_proxy_db,
109 true,
110 None,
111 );
112 let bridge_socket_path = bridge.base_socket_path();
113
114 let (bridge_handle, _alive_rx) = bridge.spawn()?;
115
116 let context_config = ContextConfig::create_eigenlayer_config(
118 testnet.http_endpoint.clone(),
119 testnet.ws_endpoint.clone(),
120 keystore_path.to_string_lossy().into_owned(),
121 None,
122 data_dir,
123 None,
124 SupportedChains::LocalTestnet,
125 eigenlayer_protocol_settings,
126 );
127
128 let mut env = BlueprintEnvironment::load_with_config(context_config)
130 .map_err(|e| Error::Setup(e.to_string()))?;
131
132 env.bridge_socket_path = Some(bridge_socket_path);
133 env.test_mode = true;
134
135 Ok(Self {
136 env,
137 _temp_dir: test_dir,
138 _container: testnet.container,
139 _auth_proxy: auth_proxy,
140 _bridge: bridge_handle,
141 })
142 }
143
144 #[must_use]
145 pub fn env(&self) -> &BlueprintEnvironment {
146 &self.env
147 }
148}
149
150#[must_use]
156pub async fn get_accounts(http_endpoint: Url) -> Vec<Address> {
157 let provider = get_provider_http(http_endpoint.clone());
158 provider.get_accounts().await.unwrap()
159}
160
161#[must_use]
163pub fn get_owner_account(accounts: &[Address]) -> Address {
164 accounts[0]
165}
166
167#[must_use]
169pub fn get_aggregator_account(accounts: &[Address]) -> Address {
170 accounts[9]
171}
172
173#[must_use]
175pub fn get_task_generator_account(accounts: &[Address]) -> Address {
176 accounts[4]
177}
178
179async fn run_auth_proxy(
196 data_dir: PathBuf,
197 auth_proxy_port: u16,
198) -> Result<(RocksDb, impl Future<Output = Result<(), Error>>), Error> {
199 let db_path = data_dir.join("private").join("auth-proxy").join("db");
200 tokio::fs::create_dir_all(&db_path).await?;
201
202 let proxy = blueprint_auth::proxy::AuthenticatedProxy::new(&db_path)?;
203 let db = proxy.db();
204
205 let task = async move {
206 let router = proxy.router();
207 let listener =
208 tokio::net::TcpListener::bind((Ipv4Addr::LOCALHOST, auth_proxy_port)).await?;
209 info!(
210 "Auth proxy listening on {}:{}",
211 Ipv4Addr::LOCALHOST,
212 auth_proxy_port
213 );
214 let result = axum::serve(listener, router).await;
215 if let Err(err) = result {
216 error!("Auth proxy error: {err}");
217 }
218
219 Ok(())
220 };
221
222 Ok((db, task))
223}
224
225pub async fn deploy_eigenlayer_core_contracts(
245 http_endpoint: &str,
246 owner_private_key: &str,
247 owner_account: Address,
248) -> Result<DeployedCoreContracts, Error> {
249 let core_config = DeploymentConfigData {
250 strategy_manager: StrategyManagerConfig {
251 init_paused_status: U256::from(0),
252 init_withdrawal_delay_blocks: 1u32,
253 },
254 delegation_manager: DelegationManagerConfig {
255 init_paused_status: U256::from(0),
256 withdrawal_delay_blocks: 0u32,
257 },
258 eigen_pod_manager: EigenPodManagerConfig {
259 init_paused_status: U256::from(0),
260 },
261 rewards_coordinator: RewardsCoordinatorConfig {
262 init_paused_status: U256::from(0),
263 max_rewards_duration: 864_000u32,
264 max_retroactive_length: 432_000u32,
265 max_future_length: 86_400u32,
266 genesis_rewards_timestamp: 1_672_531_200_u32,
267 updater: owner_account,
268 activation_delay: 0u32,
269 calculation_interval_seconds: 86_400u32,
270 global_operator_commission_bips: 1_000u16,
271 },
272 strategy_factory: StrategyFactoryConfig {
273 init_paused_status: U256::from(0),
274 },
275 };
276
277 Ok(eigenlayer_contract_deployer::core::deploy_core_contracts(
278 http_endpoint,
279 owner_private_key,
280 owner_account,
281 core_config,
282 Some(address!("00000000219ab540356cBB839Cbe05303d7705Fa")),
283 Some(1_564_000),
284 )
285 .await
286 .unwrap())
287}