diff --git a/Cargo.lock b/Cargo.lock index e680381c..37fad852 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2036,6 +2036,7 @@ version = "0.0.1-alpha" dependencies = [ "alloy-contract", "alloy-network", + "alloy-node-bindings", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -2047,6 +2048,7 @@ dependencies = [ "eigen-client-elcontracts", "eigen-crypto-bls", "eigen-logging", + "eigen-testing-utils", "eigen-types", "eigen-utils", "hex", @@ -2312,6 +2314,7 @@ dependencies = [ "alloy-transport-http", "eigen-utils", "once_cell", + "tokio", ] [[package]] diff --git a/crates/chainio/clients/avsregistry/Cargo.toml b/crates/chainio/clients/avsregistry/Cargo.toml index 658bd6fa..b4c84efc 100644 --- a/crates/chainio/clients/avsregistry/Cargo.toml +++ b/crates/chainio/clients/avsregistry/Cargo.toml @@ -15,6 +15,7 @@ alloy-primitives.workspace = true alloy-provider.workspace = true alloy-rpc-types.workspace = true alloy-signer.workspace = true +alloy-signer-local.workspace = true async-trait.workspace = true alloy-transport-http.workspace = true num-bigint = "0.4.4" @@ -27,9 +28,13 @@ eigen-utils.workspace = true eigen-logging.workspace = true thiserror.workspace = true tracing.workspace = true -alloy-signer-local.workspace = true + +[lints] +workspace = true [dev-dependencies] +alloy-node-bindings.workspace = true +eigen-testing-utils.workspace = true hex = "0.4.3" once_cell.workspace = true -tokio = {version = "1.37.0" , features = ["test-util", "full","sync"] } +tokio = { version = "1.37.0", features = ["test-util", "full", "sync"] } diff --git a/crates/chainio/clients/avsregistry/README.md b/crates/chainio/clients/avsregistry/README.md index 4cd70939..f16d14bc 100644 --- a/crates/chainio/clients/avsregistry/README.md +++ b/crates/chainio/clients/avsregistry/README.md @@ -1,12 +1,12 @@ # AvsRegistry -Reader , writer and subscribing methods to interact with avs registry contracts +Reader , writer and subscribing methods to interact with avs registry contracts -## Example +## Example - [get_operator_from_id](https://github.com/Layr-Labs/eigensdk-rs/blob/main/examples/avsregistry-read/examples/get_operator_from_id.rs) - [get_operator_id](https://github.com/Layr-Labs/eigensdk-rs/blob/main/examples/avsregistry-read/examples/get_operator_id.rs) - [get_operator_stake_in_quorums_of_operator_at_current_block](https://github.com/Layr-Labs/eigensdk-rs/blob/main/examples/avsregistry-read/examples/get_operator_stake_in_quorums_of_operator_at_current_block.rs) - [get_operators_stake_in_quorums_at_block](https://github.com/Layr-Labs/eigensdk-rs/blob/main/examples/avsregistry-read/examples/get_operators_stake_in_quorums_at_block.rs) - [get_quorum_count](https://github.com/Layr-Labs/eigensdk-rs/blob/main/examples/avsregistry-read/examples/get_quorum_count.rs) -- [query_existing_registered_operator_pub_keys](https://github.com/Layr-Labs/eigensdk-rs/blob/main/examples/avsregistry-read/examples/query_existing_registered_operator_pub_keys.rs) \ No newline at end of file +- [query_existing_registered_operator_pub_keys](https://github.com/Layr-Labs/eigensdk-rs/blob/main/examples/avsregistry-read/examples/query_existing_registered_operator_pub_keys.rs) diff --git a/crates/chainio/clients/avsregistry/src/reader.rs b/crates/chainio/clients/avsregistry/src/reader.rs index 19658ea3..78447161 100644 --- a/crates/chainio/clients/avsregistry/src/reader.rs +++ b/crates/chainio/clients/avsregistry/src/reader.rs @@ -44,6 +44,7 @@ impl Default for AvsRegistryChainReader { } #[async_trait] +/// Common methods for AvsRegistryChainReader pub trait AvsRegistryReader { /// Get operators stake in quorums at a particular block /// @@ -186,38 +187,34 @@ impl AvsRegistryChainReader { let contract_registry_coordinator = RegistryCoordinator::new(registry_coordinator_addr, &provider); - let bls_apk_registry_addr_result = - contract_registry_coordinator.blsApkRegistry().call().await; - match bls_apk_registry_addr_result { - Ok(bls_apk_registry_return) => { - let RegistryCoordinator::blsApkRegistryReturn { - _0: bls_apk_registry_addr, - } = bls_apk_registry_return; - - let stake_registry_addr_result = - contract_registry_coordinator.stakeRegistry().call().await; - - match stake_registry_addr_result { - Ok(stake_registry_return) => { - let RegistryCoordinator::stakeRegistryReturn { - _0: stake_registry_addr, - } = stake_registry_return; - - Ok(AvsRegistryChainReader { - logger, - bls_apk_registry_addr, - registry_coordinator_addr, - operator_state_retriever: operator_state_retriever_addr, - stake_registry_addr, - provider: http_provider_url.clone(), - }) - } - Err(_) => Err(AvsRegistryError::GetStakeRegistry), - } - } + let bls_apk_registry_return = contract_registry_coordinator + .blsApkRegistry() + .call() + .await + .map_err(|_| AvsRegistryError::GetBlsApkRegistry)?; - Err(_) => Err(AvsRegistryError::GetBlsApkRegistry), - } + let RegistryCoordinator::blsApkRegistryReturn { + _0: bls_apk_registry_addr, + } = bls_apk_registry_return; + + let stake_registry_return = contract_registry_coordinator + .stakeRegistry() + .call() + .await + .map_err(|_| AvsRegistryError::GetStakeRegistry)?; + + let RegistryCoordinator::stakeRegistryReturn { + _0: stake_registry_addr, + } = stake_registry_return; + + Ok(AvsRegistryChainReader { + logger, + bls_apk_registry_addr, + registry_coordinator_addr, + operator_state_retriever: operator_state_retriever_addr, + stake_registry_addr, + provider: http_provider_url.clone(), + }) } /// Get quorum count @@ -231,16 +228,14 @@ impl AvsRegistryChainReader { let contract_registry_coordinator = RegistryCoordinator::new(self.registry_coordinator_addr, provider); - let quorum_count_result = contract_registry_coordinator.quorumCount().call().await; - - match quorum_count_result { - Ok(quorum_count) => { - let RegistryCoordinator::quorumCountReturn { _0: quorum } = quorum_count; - Ok(quorum) - } + let quorum_count = contract_registry_coordinator + .quorumCount() + .call() + .await + .map_err(|_| AvsRegistryError::GetQuorumCount)?; - Err(_) => Err(AvsRegistryError::GetQuorumCount), - } + let RegistryCoordinator::quorumCountReturn { _0: quorum } = quorum_count; + Ok(quorum) } /// Get operators stake in quorums at block operator id @@ -264,22 +259,21 @@ impl AvsRegistryChainReader { let contract_operator_state_retriever = OperatorStateRetriever::new(self.operator_state_retriever, provider); - let operator_state_with_registry_coordinator_and_operator_id_result = + + let operator_state_with_registry_coordinator_and_operator_id = contract_operator_state_retriever .getOperatorState_1(self.registry_coordinator_addr, operator_id, block_number) .call() - .await; - - match operator_state_with_registry_coordinator_and_operator_id_result { - Ok(operator_state_with_registry_coordinator_and_oeprator_id) => { - let OperatorStateRetriever::getOperatorState_1Return { - _0: quorum_bitmaps, - _1: operator_state, - } = operator_state_with_registry_coordinator_and_oeprator_id; - Ok((quorum_bitmaps, operator_state)) - } - Err(_) => Err(AvsRegistryError::GetOperatorStateWithRegistryCoordinatorAndOperatorId), - } + .await + .map_err(|_| { + AvsRegistryError::GetOperatorStateWithRegistryCoordinatorAndOperatorId + })?; + + let OperatorStateRetriever::getOperatorState_1Return { + _0: stake, + _1: operator_state, + } = operator_state_with_registry_coordinator_and_operator_id; + Ok((stake, operator_state)) } /// Get operators stake in quorums at current block @@ -298,30 +292,18 @@ impl AvsRegistryChainReader { ) -> Result>, AvsRegistryError> { let provider = get_provider(&self.provider); - let current_block_number_result = provider.get_block_number().await; - - match current_block_number_result { - Ok(current_block_number) => { - if current_block_number > u32::MAX.into() { - return Err(AvsRegistryError::BlockNumberOverflow); - } + let current_block_number = provider + .get_block_number() + .await + .map_err(|_| AvsRegistryError::GetBlockNumber)?; - let operators_stake_in_quorums_at_block_result = self - .get_operators_stake_in_quorums_at_block( - current_block_number as u32, - quorum_numbers, - ) - .await; - - match operators_stake_in_quorums_at_block_result { - Ok(operators_stake_in_quorums_at_block) => { - Ok(operators_stake_in_quorums_at_block) - } - Err(_) => Err(AvsRegistryError::GetOperatorStakeInQuorumAtBlockNumber), - } - } - Err(_) => Err(AvsRegistryError::GetBlockNumber), + if current_block_number > u32::MAX.into() { + return Err(AvsRegistryError::BlockNumberOverflow); } + + self.get_operators_stake_in_quorums_at_block(current_block_number as u32, quorum_numbers) + .await + .map_err(|_| AvsRegistryError::GetOperatorStakeInQuorumAtBlockNumber) } /// Get operators stake in quorums of operator at block @@ -342,19 +324,14 @@ impl AvsRegistryChainReader { operator_id: B256, block_number: u32, ) -> Result<(Vec, Vec>), AvsRegistryError> { - let result_ = self + let (quorum_bitmaps, operator_stakes) = self .get_operators_stake_in_quorums_at_block_operator_id(block_number, operator_id) - .await; - - match result_ { - Ok((quorum_bitmaps, operator_stakes)) => { - let quorums = bitmap_to_quorum_ids(quorum_bitmaps); + .await + .map_err(|_| AvsRegistryError::GetOperatorStakeInQuorumAtBlockOperatorId)?; - let s = (quorums, operator_stakes); - Ok(s) - } - Err(_) => Err(AvsRegistryError::GetOperatorStakeInQuorumAtBlockOperatorId), - } + let quorums = bitmap_to_quorum_ids(quorum_bitmaps); + let s = (quorums, operator_stakes); + Ok(s) } /// Get operators stake in quorums of operator at current block @@ -374,32 +351,19 @@ impl AvsRegistryChainReader { ) -> Result<(Vec, Vec>), AvsRegistryError> { let provider = get_provider(&self.provider); - let current_block_number_result = provider.get_block_number().await; + let current_block_number = provider.get_block_number().await.map_err(|e| { + AvsRegistryError::AlloyContractError(alloy_contract::Error::TransportError(e)) + })?; - match current_block_number_result { - Ok(current_block_number) => { - if current_block_number > u32::MAX.into() { - return Err(AvsRegistryError::BlockNumberOverflow); - } - - let operator_stake_in_quorum_of_operaotr_at_block_result = self - .get_operators_stake_in_quorums_of_operator_at_block( - operator_id, - current_block_number as u32, - ) - .await; - - match operator_stake_in_quorum_of_operaotr_at_block_result { - Ok(operator_stake_in_quorum_of_operaotr_at_block) => { - Ok(operator_stake_in_quorum_of_operaotr_at_block) - } - Err(e) => Err(e), - } - } - Err(e) => Err(AvsRegistryError::AlloyContractError( - alloy_contract::Error::TransportError(e), - )), + if current_block_number > u32::MAX.into() { + return Err(AvsRegistryError::BlockNumberOverflow); } + + self.get_operators_stake_in_quorums_of_operator_at_block( + operator_id, + current_block_number as u32, + ) + .await } /// Get operator's stake in quorums at current block @@ -501,103 +465,76 @@ impl AvsRegistryChainReader { Ok(operator_status == 1) } - /// Queries existing operators from for a particular block range + /// Queries existing operators from for a particular block range. /// /// # Arguments /// - /// * `start_block` - The starting block number. - /// * `stop_block` - The final block number. - /// * `ws_url` - The websocket url. + /// * `start_block` - The block number to start querying from. + /// * `stop_block` - The block number to stop querying at. + /// * `ws_url` - The websocket url to use for querying. /// /// # Returns /// - /// - a vector of the operators addresses registered at the block range - /// - a vector with those operators public keys. + /// * (`Vec
`, `Vec`) - A vector of operator addresses and its + /// corresponding operator pub keys. pub async fn query_existing_registered_operator_pub_keys( &self, start_block: u64, mut stop_block: u64, ws_url: String, ) -> Result<(Vec
, Vec), AvsRegistryError> { - let provider_ws_result = get_ws_provider(&ws_url).await; - - match provider_ws_result { - Ok(provider) => { - let query_block_range = 1024; - let current_block_number_result = provider.get_block_number().await; - - match current_block_number_result { - Ok(current_block_number) => { - if stop_block.is_zero() { - stop_block = current_block_number; - } - let mut i = start_block; - let mut operator_addresses: Vec
= vec![]; - let mut operator_pub_keys: Vec = vec![]; - while i <= stop_block { - let to_block = std::cmp::min(i + (query_block_range - 1), stop_block); - let filter = Filter::new() - .select(i..to_block) - .event(NEW_PUBKEY_REGISTRATION_EVENT) - .address(self.bls_apk_registry_addr); - - let logs_result = provider.get_logs(&filter).await; - - match logs_result { - Ok(logs) => { - self.logger.debug( - &format!( - "numTransactionLogs: {}, fromBlock: {}, toBlock: {}", - logs.len(), - i, - to_block - ), - "eigen-client-avsregistry.reader.query_existing_registered_operator_pub_keys" - ); - - for pub_key_reg in logs - .iter() - .map(|v| { - v.log_decode::() - }) - .filter_map(Result::ok) - { - let data = pub_key_reg.data(); - let operator_addr = data.operator; - operator_addresses.push(operator_addr); - let g1_pub_key = data.pubkeyG1.clone(); - let g2_pub_key = data.pubkeyG2.clone(); - let operator_pub_key = OperatorPubKeys { - g1_pub_key: BlsG1Point::new( - alloy_registry_g1_point_to_g1_affine(g1_pub_key), - ), - g2_pub_key: BlsG2Point::new( - alloy_registry_g2_point_to_g2_affine(g2_pub_key), - ), - }; - operator_pub_keys.push(operator_pub_key); - } - } - Err(e) => { - return Err(AvsRegistryError::AlloyContractError( - alloy_contract::Error::TransportError(e), - )) - } - } - i += query_block_range; - } - - Ok((operator_addresses, operator_pub_keys)) - } - Err(e) => Err(AvsRegistryError::AlloyContractError( - alloy_contract::Error::TransportError(e), - )), - } + let provider = get_ws_provider(&ws_url).await.map_err(|e| { + AvsRegistryError::AlloyContractError(alloy_contract::Error::TransportError(e)) + })?; + + let query_block_range = 1024; + let current_block_number = provider.get_block_number().await.map_err(|e| { + AvsRegistryError::AlloyContractError(alloy_contract::Error::TransportError(e)) + })?; + if stop_block.is_zero() { + stop_block = current_block_number; + } + let mut i = start_block; + let mut operator_addresses: Vec
= vec![]; + let mut operator_pub_keys: Vec = vec![]; + + while i <= stop_block { + let to_block = std::cmp::min(i + (query_block_range - 1), stop_block); + let filter = Filter::new() + .select(i..to_block) + .event(NEW_PUBKEY_REGISTRATION_EVENT) + .address(self.bls_apk_registry_addr); + + let logs = provider.get_logs(&filter).await.map_err(|e| { + AvsRegistryError::AlloyContractError(alloy_contract::Error::TransportError(e)) + })?; + + let len = logs.len(); + self.logger.debug( + &format!("numTransactionLogs: {len}, fromBlock: {i}, toBlock: {to_block}",), + "eigen-client-avsregistry.reader.query_existing_registered_operator_pub_keys", + ); + + for pub_key_reg in logs + .iter() + .map(|v| v.log_decode::()) + .filter_map(Result::ok) + { + let data = pub_key_reg.data(); + let operator_addr = data.operator; + operator_addresses.push(operator_addr); + let g1_pub_key = data.pubkeyG1.clone(); + let g2_pub_key = data.pubkeyG2.clone(); + let operator_pub_key = OperatorPubKeys { + g1_pub_key: BlsG1Point::new(alloy_registry_g1_point_to_g1_affine(g1_pub_key)), + g2_pub_key: BlsG2Point::new(alloy_registry_g2_point_to_g2_affine(g2_pub_key)), + }; + operator_pub_keys.push(operator_pub_key); } - Err(e) => Err(AvsRegistryError::AlloyContractError( - alloy_contract::Error::TransportError(e), - )), + i += query_block_range; } + + Ok((operator_addresses, operator_pub_keys)) } /// TODO: Update bindings and then update this function @@ -605,13 +542,13 @@ impl AvsRegistryChainReader { /// /// # Arguments /// - /// * `start_block` - The starting block number. - /// * `stop_block` - The final block number. + /// * `start_block` - Start block number + /// * `stop_block` - Stop block number /// /// # Returns /// - /// A hashmap containing the ids of the operators registered at the block range - /// and their sockets. + /// * `HashMap, String>` - Operator Id to socket mapping containing all the operator + /// sockets registered in the given block range pub async fn query_existing_registered_operator_sockets( &self, start_block: u64, @@ -636,54 +573,34 @@ impl AvsRegistryChainReader { .event("OperatorSocketUpdate(bytes32,string)") .address(self.registry_coordinator_addr); if stop_block == 0 { - let current_block_number_result = provider.get_block_number().await; - - match current_block_number_result { - Ok(current_block_number) => { - filter = filter.clone().select(start_block..current_block_number); - } - - Err(e) => { - return Err(AvsRegistryError::AlloyContractError( - alloy_contract::Error::TransportError(e), - )) - } - } + let current_block_number = provider.get_block_number().await.map_err(|e| { + AvsRegistryError::AlloyContractError(alloy_contract::Error::TransportError(e)) + })?; + filter = filter.clone().select(start_block..current_block_number); }; - let logs_result = provider.get_logs(&filter).await; - - match logs_result { - Ok(logs) => { - for v_log in logs.iter() { - let socket_update_filter_option = v_log - .log_decode::() - .ok(); - if let Some(socket_update_filter) = socket_update_filter_option { - let data = socket_update_filter.data(); - let operator_id = data.operatorId; - let socket = &data.socket; - operator_id_to_socket.insert(operator_id, socket.clone()); - } - } - self.logger.debug( - &format!( - "num_transaction_logs : {} , from_block: {} , to_block: {}", - logs.len(), - i, - to_block - ), - "eigen-client-avsregistry.reader.query_existing_registered_operator_sockets", - ); - - i += query_block_range; - } - Err(e) => { - return Err(AvsRegistryError::AlloyContractError( - alloy_contract::Error::TransportError(e), - )) + let logs = provider.get_logs(&filter).await.map_err(|e| { + AvsRegistryError::AlloyContractError(alloy_contract::Error::TransportError(e)) + })?; + + for v_log in logs.iter() { + let socket_update_filter_option = v_log + .log_decode::() + .ok(); + if let Some(socket_update_filter) = socket_update_filter_option { + let data = socket_update_filter.data(); + let operator_id = data.operatorId; + let socket = &data.socket; + operator_id_to_socket.insert(operator_id, socket.clone()); } } + let len = logs.len(); + self.logger.debug( + &format!("num_transaction_logs : {len} , from_block: {i} , to_block: {to_block}"), + "eigen-client-avsregistry.reader.query_existing_registered_operator_sockets", + ); + + i += query_block_range; } Ok(operator_id_to_socket) } @@ -691,7 +608,6 @@ impl AvsRegistryChainReader { #[cfg(test)] mod tests { - use super::*; use eigen_logging::get_test_logger; use hex::FromHex; diff --git a/crates/chainio/clients/avsregistry/src/writer.rs b/crates/chainio/clients/avsregistry/src/writer.rs index e6beef19..0c94551b 100644 --- a/crates/chainio/clients/avsregistry/src/writer.rs +++ b/crates/chainio/clients/avsregistry/src/writer.rs @@ -1,24 +1,22 @@ +use crate::error::AvsRegistryError; +use alloy_primitives::{Address, Bytes, FixedBytes, TxHash, U256}; use alloy_signer::Signer; use alloy_signer_local::PrivateKeySigner; use eigen_client_elcontracts::reader::ELChainReader; +use eigen_crypto_bls::{ + alloy_g1_point_to_g1_affine, convert_to_g1_point, convert_to_g2_point, BlsKeyPair, +}; use eigen_logging::logger::SharedLogger; use eigen_utils::binding::RegistryCoordinator::{ self, G1Point as RegistryG1Point, G2Point as RegistryG2Point, PubkeyRegistrationParams, }; -use std::str::FromStr; - -use alloy_primitives::{Address, Bytes, FixedBytes, TxHash, U256}; -use eigen_crypto_bls::{ - alloy_g1_point_to_g1_affine, convert_to_g1_point, convert_to_g2_point, BlsKeyPair, -}; -use tracing::info; -use RegistryCoordinator::SignatureWithSaltAndExpiry; - -use crate::error::AvsRegistryError; use eigen_utils::{ binding::{ServiceManagerBase, StakeRegistry}, get_provider, get_signer, }; +use std::str::FromStr; +use tracing::info; +use RegistryCoordinator::SignatureWithSaltAndExpiry; /// Gas limit for registerOperator in [`RegistryCoordinator`] pub const GAS_LIMIT_REGISTER_OPERATOR_REGISTRY_COORDINATOR: u128 = 2000000; @@ -39,6 +37,22 @@ pub struct AvsRegistryChainWriter { impl AvsRegistryChainWriter { /// build avs registry chain writer instance + /// + /// # Arguments + /// + /// * `logger` - SharedLogger used for logging + /// * `provider` - provider string + /// * `signer` - signer string + /// * `registry_coordinator_addr` - registry coordinator address + /// * `operator_state_retriever_addr` - operator state retriever address + /// + /// # Returns + /// + /// * `Result` - a new AvsRegistryChainWriter + /// + /// # Errors + /// + /// * `AvsRegistryError` - if any error occurs pub async fn build_avs_registry_chain_writer( logger: SharedLogger, provider: String, @@ -51,75 +65,75 @@ impl AvsRegistryChainWriter { let contract_registry_coordinator = RegistryCoordinator::new(registry_coordinator_addr, &fill_provider); - let service_manager_addr_result = - contract_registry_coordinator.serviceManager().call().await; - - match service_manager_addr_result { - Ok(service_manager_addr) => { - let RegistryCoordinator::serviceManagerReturn { - _0: service_manager, - } = service_manager_addr; - let contract_service_manager_base = - ServiceManagerBase::new(service_manager, &fill_provider); - - let bls_apk_registry_addr_result = - contract_registry_coordinator.blsApkRegistry().call().await; - - match bls_apk_registry_addr_result { - Ok(bls_apk_registry_addr) => { - let RegistryCoordinator::blsApkRegistryReturn { - _0: bls_apk_registry, - } = bls_apk_registry_addr; - let stake_registry_addr = - contract_registry_coordinator.stakeRegistry().call().await?; - let RegistryCoordinator::stakeRegistryReturn { _0: stake_registry } = - stake_registry_addr; - let contract_stake_registry = - StakeRegistry::new(stake_registry, &fill_provider); - - let delegation_manager_return = - contract_stake_registry.delegation().call().await?; - - let StakeRegistry::delegationReturn { - _0: delegation_manager_addr, - } = delegation_manager_return; - let avs_directory_addr = - contract_service_manager_base.avsDirectory().call().await?; - - let ServiceManagerBase::avsDirectoryReturn { _0: avs_directory } = - avs_directory_addr; - - let el_reader_result = ELChainReader::build( - logger.clone(), - delegation_manager_addr, - avs_directory, - &provider, - ) - .await; - - match el_reader_result { - Ok(el_reader) => Ok(AvsRegistryChainWriter { - logger, - service_manager_addr: service_manager, - registry_coordinator_addr, - operator_state_retriever_addr, - stake_registry_addr: stake_registry, - bls_apk_registry_addr: bls_apk_registry, - el_reader, - provider: provider.clone(), - signer: signer.clone(), - }), - Err(e) => Err(AvsRegistryError::ElContractsError(e.to_string())), - } - } - Err(e) => Err(AvsRegistryError::AlloyContractError(e)), - } - } - Err(e) => Err(AvsRegistryError::AlloyContractError(e)), - } + let service_manager_addr = contract_registry_coordinator + .serviceManager() + .call() + .await + .map_err(AvsRegistryError::AlloyContractError)?; + + let RegistryCoordinator::serviceManagerReturn { + _0: service_manager, + } = service_manager_addr; + let contract_service_manager_base = + ServiceManagerBase::new(service_manager, &fill_provider); + + let bls_apk_registry_addr_result = contract_registry_coordinator + .blsApkRegistry() + .call() + .await + .map_err(AvsRegistryError::AlloyContractError)?; + + let RegistryCoordinator::blsApkRegistryReturn { + _0: bls_apk_registry, + } = bls_apk_registry_addr_result; + let stake_registry_addr = contract_registry_coordinator.stakeRegistry().call().await?; + let RegistryCoordinator::stakeRegistryReturn { _0: stake_registry } = stake_registry_addr; + let contract_stake_registry = StakeRegistry::new(stake_registry, &fill_provider); + + let delegation_manager_return = contract_stake_registry.delegation().call().await?; + + let StakeRegistry::delegationReturn { + _0: delegation_manager_addr, + } = delegation_manager_return; + let avs_directory_addr = contract_service_manager_base.avsDirectory().call().await?; + + let ServiceManagerBase::avsDirectoryReturn { _0: avs_directory } = avs_directory_addr; + + let el_reader = ELChainReader::build( + logger.clone(), + delegation_manager_addr, + avs_directory, + &provider, + ) + .await + .map_err(|e| AvsRegistryError::ElContractsError(e.to_string()))?; + + Ok(AvsRegistryChainWriter { + logger, + service_manager_addr: service_manager, + registry_coordinator_addr, + operator_state_retriever_addr, + stake_registry_addr: stake_registry, + bls_apk_registry_addr: bls_apk_registry, + el_reader, + provider: provider.clone(), + signer: signer.clone(), + }) } /// Register operator in quorum with avs registry coordinator + /// + /// # Arguments + /// + /// * `bls_key_pair` - bls key pair of the operator + /// * `operator_to_avs_registration_sig_salt` - salt for the signature + /// * `operator_to_avs_registration_sig_expiry` - expiry for the signature + /// * `quorum_numbers` - quorum numbers + /// * `socket` - socket used for calling the contract with `registerOperator` function + /// + /// # Returns + /// + /// * `Result` - transaction hash of the register operator transaction pub async fn register_operator_in_quorum_with_avs_registry_coordinator( &self, bls_key_pair: BlsKeyPair, @@ -130,98 +144,102 @@ impl AvsRegistryChainWriter { ) -> Result { let provider = get_signer(self.signer.clone(), &self.provider); let wallet = PrivateKeySigner::from_str(&self.signer).expect("failed to generate wallet "); + // tracing info info!(avs_service_manager = %self.service_manager_addr, operator= %wallet.address(),quorum_numbers = ?quorum_numbers,"quorum_numbers,registering operator with the AVS's registry coordinator"); let contract_registry_coordinator = RegistryCoordinator::new(self.registry_coordinator_addr, provider); - let g1_hashes_msg_to_sign_return_result = contract_registry_coordinator + let g1_hashes_msg_to_sign_return = contract_registry_coordinator .pubkeyRegistrationMessageHash(wallet.address()) .call() - .await; - - match g1_hashes_msg_to_sign_return_result { - Ok(g1_hashes_msg_to_sign_return) => { - let RegistryCoordinator::pubkeyRegistrationMessageHashReturn { - _0: g1_hashes_msg_to_sign, - } = g1_hashes_msg_to_sign_return; - let sig = bls_key_pair - .sign_hashed_to_curve_message(alloy_g1_point_to_g1_affine( - g1_hashes_msg_to_sign, - )) - .g1_point(); - let alloy_g1_point_signed_msg = convert_to_g1_point(sig.g1())?; - - let g1_pub_key_bn254 = convert_to_g1_point(bls_key_pair.public_key().g1())?; - - let g2_pub_key_bn254 = convert_to_g2_point(bls_key_pair.public_key_g2().g2())?; - - let pub_key_reg_params = PubkeyRegistrationParams { - pubkeyRegistrationSignature: alloy_g1_point_signed_msg, - pubkeyG1: g1_pub_key_bn254, - pubkeyG2: g2_pub_key_bn254, - }; - - let msg_to_sign = self - .el_reader - .calculate_operator_avs_registration_digest_hash( - wallet.address(), - self.service_manager_addr, - operator_to_avs_registration_sig_salt, - operator_to_avs_registration_sig_expiry, - ) - .await?; - - let operator_signature = wallet - .sign_hash(&msg_to_sign) - .await - .expect("failed to sign message"); - - let operator_signature_with_salt_and_expiry = SignatureWithSaltAndExpiry { - signature: operator_signature.as_bytes().into(), - salt: operator_to_avs_registration_sig_salt, - expiry: operator_to_avs_registration_sig_expiry, - }; - - let contract_call = contract_registry_coordinator.registerOperator( - quorum_numbers.clone(), - socket, - PubkeyRegistrationParams { - pubkeyRegistrationSignature: RegistryG1Point { - X: pub_key_reg_params.pubkeyRegistrationSignature.X, - Y: pub_key_reg_params.pubkeyRegistrationSignature.Y, - }, - pubkeyG1: RegistryG1Point { - X: pub_key_reg_params.pubkeyG1.X, - Y: pub_key_reg_params.pubkeyG1.Y, - }, - pubkeyG2: RegistryG2Point { - X: pub_key_reg_params.pubkeyG2.X, - Y: pub_key_reg_params.pubkeyG2.Y, - }, - }, - operator_signature_with_salt_and_expiry, - ); - - let tx_call = contract_call.gas(GAS_LIMIT_REGISTER_OPERATOR_REGISTRY_COORDINATOR); - let tx_result = tx_call.send().await; - - match tx_result { - Ok(tx) => { - info!(tx_hash = ?tx,"Succesfully deregistered operator with the AVS's registry coordinator" ); - Ok(*tx.tx_hash()) - } - Err(e) => Err(AvsRegistryError::AlloyContractError(e)), - } - } - Err(_) => Err(AvsRegistryError::PubKeyRegistrationMessageHash), - } + .await + .map_err(|_| AvsRegistryError::PubKeyRegistrationMessageHash)?; + + let RegistryCoordinator::pubkeyRegistrationMessageHashReturn { + _0: g1_hashes_msg_to_sign, + } = g1_hashes_msg_to_sign_return; + let sig = bls_key_pair + .sign_hashed_to_curve_message(alloy_g1_point_to_g1_affine(g1_hashes_msg_to_sign)) + .g1_point(); + let alloy_g1_point_signed_msg = convert_to_g1_point(sig.g1())?; + + let g1_pub_key_bn254 = convert_to_g1_point(bls_key_pair.public_key().g1())?; + + let g2_pub_key_bn254 = convert_to_g2_point(bls_key_pair.public_key_g2().g2())?; + + let pub_key_reg_params = PubkeyRegistrationParams { + pubkeyRegistrationSignature: alloy_g1_point_signed_msg, + pubkeyG1: g1_pub_key_bn254, + pubkeyG2: g2_pub_key_bn254, + }; + + let msg_to_sign = self + .el_reader + .calculate_operator_avs_registration_digest_hash( + wallet.address(), + self.service_manager_addr, + operator_to_avs_registration_sig_salt, + operator_to_avs_registration_sig_expiry, + ) + .await?; + + let operator_signature = wallet + .sign_hash(&msg_to_sign) + .await + .expect("failed to sign message"); + + let operator_signature_with_salt_and_expiry = SignatureWithSaltAndExpiry { + signature: operator_signature.as_bytes().into(), + salt: operator_to_avs_registration_sig_salt, + expiry: operator_to_avs_registration_sig_expiry, + }; + + let contract_call = contract_registry_coordinator.registerOperator( + quorum_numbers.clone(), + socket, + PubkeyRegistrationParams { + pubkeyRegistrationSignature: RegistryG1Point { + X: pub_key_reg_params.pubkeyRegistrationSignature.X, + Y: pub_key_reg_params.pubkeyRegistrationSignature.Y, + }, + pubkeyG1: RegistryG1Point { + X: pub_key_reg_params.pubkeyG1.X, + Y: pub_key_reg_params.pubkeyG1.Y, + }, + pubkeyG2: RegistryG2Point { + X: pub_key_reg_params.pubkeyG2.X, + Y: pub_key_reg_params.pubkeyG2.Y, + }, + }, + operator_signature_with_salt_and_expiry, + ); + + let tx_call = contract_call.gas(GAS_LIMIT_REGISTER_OPERATOR_REGISTRY_COORDINATOR); + let tx = tx_call + .send() + .await + .map_err(AvsRegistryError::AlloyContractError)?; + + info!(tx_hash = ?tx,"Succesfully deregistered operator with the AVS's registry coordinator" ); + Ok(*tx.tx_hash()) } - /// update_stakes_of_entire_operator_set_for_quorums is used by avs teams running https://github.com/Layr-Labs/avs-sync - /// to updates the stake of their entire operator set. - /// Because of high gas costs of this operation, it typically needs to be called for every quorum, or perhaps for a - /// small grouping of quorums - /// (highly dependent on number of operators per quorum) + /// Updates the stake of their entire operator set + /// + /// Is used by avs teams running https://github.com/Layr-Labs/avs-sync to updates + /// the stake of their entire operator set. + /// Because of high gas costs of this operation, it typically needs to be called + /// for every quorum, or perhaps for a small grouping of quorums + /// (highly dependent on number of operators per quorum). + /// + /// # Arguments + /// + /// * `operators_per_quorum` - A vector of vectors of addresses, where each inner vector represents the operators in a quorum + /// * `quorum_number` - The quorum number to update the stakes for + /// + /// # Returns + /// + /// * `TxHash` - The transaction hash of the transaction that was sent to update the stakes pub async fn update_stakes_of_entire_operator_set_for_quorums( &self, operators_per_quorum: Vec>, @@ -231,22 +249,29 @@ impl AvsRegistryChainWriter { let provider = get_signer(self.signer.clone(), &self.provider); let contract_registry_coordinator = RegistryCoordinator::new(self.registry_coordinator_addr, provider); - let contract_call = contract_registry_coordinator .updateOperatorsForQuorum(operators_per_quorum, quorum_number.clone()); - let tx_result = contract_call.send().await; + let tx = contract_call + .send() + .await + .map_err(AvsRegistryError::AlloyContractError)?; - match tx_result { - Ok(tx) => { - info!(tx_hash = ?tx, quorum_numbers = %quorum_number," update stakes for entire operator set tx" ); - return Ok(*tx.tx_hash()); - } - Err(e) => Err(AvsRegistryError::AlloyContractError(e)), - } + info!(tx_hash = ?tx, quorum_numbers = %quorum_number," update stakes for entire operator set tx" ); + Ok(*tx.tx_hash()) } /// Update stakes of operator subset for all quorums + /// + /// This function is used to update the stakes of a subset of operators for all quorums. + /// + /// # Arguments + /// + /// * `operators` - The list of operators to update the stakes for. + /// + /// # Returns + /// + /// * `TxHash` - The transaction hash of the update stakes of operator subset for all quorums transaction. pub async fn update_stakes_of_operator_subset_for_all_quorums( &self, operators: Vec
, @@ -260,18 +285,26 @@ impl AvsRegistryChainWriter { let contract_call = contract_registry_coordinator.updateOperators(operators); - let tx_result = contract_call.send().await; + let tx = contract_call + .send() + .await + .map_err(AvsRegistryError::AlloyContractError)?; - match tx_result { - Ok(tx) => { - info!(tx_hash = ?tx,"succesfully updated stakes of operator subset for all quorums" ); - Ok(*tx.tx_hash()) - } - Err(e) => Err(AvsRegistryError::AlloyContractError(e)), - } + info!(tx_hash = ?tx,"succesfully updated stakes of operator subset for all quorums" ); + Ok(*tx.tx_hash()) } /// Deregister operator + /// + /// This function is used to deregister an operator from the AVS's registry coordinator. + /// + /// # Arguments + /// + /// * `quorum_numbers` - The quorum numbers of the operator to be deregistered. + /// + /// # Returns + /// + /// * `TxHash` - The transaction hash of the deregister operator transaction. pub async fn deregister_operator( &self, quorum_numbers: Bytes, @@ -284,13 +317,120 @@ impl AvsRegistryChainWriter { let contract_call = contract_registry_coordinator.deregisterOperator(quorum_numbers); - let tx_result = contract_call.send().await; - match tx_result { - Ok(tx) => { - info!(tx_hash = ?tx,"succesfully deregistered operator with the AVS's registry coordinator" ); - Ok(*tx.tx_hash()) - } - Err(e) => Err(AvsRegistryError::AlloyContractError(e)), - } + let tx = contract_call + .send() + .await + .map_err(AvsRegistryError::AlloyContractError)?; + info!(tx_hash = ?tx,"succesfully deregistered operator with the AVS's registry coordinator" ); + Ok(*tx.tx_hash()) + } +} + +#[cfg(test)] +mod tests { + use super::AvsRegistryChainWriter; + use alloy_node_bindings::Anvil; + use alloy_primitives::{Address, Bytes, FixedBytes, U256}; + use eigen_crypto_bls::BlsKeyPair; + use eigen_logging::get_test_logger; + use eigen_testing_utils::anvil_constants::{ + get_operator_state_retriever_address, get_registry_coordinator_address, + get_transaction_status, ANVIL_HTTP_URL, + }; + + async fn build_avs_registry_chain_writer(private_key: String) -> AvsRegistryChainWriter { + let registry_coordinator_address = get_registry_coordinator_address().await; + let operator_state_retriever_address = get_operator_state_retriever_address().await; + + AvsRegistryChainWriter::build_avs_registry_chain_writer( + get_test_logger(), + ANVIL_HTTP_URL.to_string(), + private_key, + registry_coordinator_address, + operator_state_retriever_address, + ) + .await + .unwrap() + } + + #[tokio::test] + async fn test_avs_writer_methods() { + let account_idx = 5; + let anvil = Anvil::new().try_spawn().unwrap(); + let private_key = anvil.keys().get(account_idx).unwrap(); + let private_key_hex = hex::encode(private_key.to_bytes()); + let private_key_decimal = U256::from_be_bytes(private_key.to_bytes().into()).to_string(); + let avs_writer = build_avs_registry_chain_writer(private_key_hex).await; + let operator_id = anvil.addresses().get(account_idx).unwrap(); + + let quorum_nums = Bytes::from([0]); + test_register_operator(&avs_writer, private_key_decimal, quorum_nums.clone()).await; + test_update_stake_of_operator_subset(&avs_writer, *operator_id).await; + test_update_stake_of_entire_operator_set(&avs_writer, *operator_id, quorum_nums.clone()) + .await; + test_deregister_operator(&avs_writer, quorum_nums).await; + } + + // this function is caller from test_avs_writer_methods + async fn test_update_stake_of_operator_subset( + avs_writer: &AvsRegistryChainWriter, + operator_id: Address, + ) { + let tx_hash = avs_writer + .update_stakes_of_operator_subset_for_all_quorums(vec![operator_id]) + .await + .unwrap(); + + let tx_status = get_transaction_status(tx_hash).await; + assert!(tx_status); + } + + // this function is caller from test_avs_writer_methods + async fn test_update_stake_of_entire_operator_set( + avs_writer: &AvsRegistryChainWriter, + operator_id: Address, + quorum_nums: Bytes, + ) { + let tx_hash = avs_writer + .update_stakes_of_entire_operator_set_for_quorums(vec![vec![operator_id]], quorum_nums) + .await + .unwrap(); + + let tx_status = get_transaction_status(tx_hash).await; + assert!(tx_status); + } + + // this function is caller from test_avs_writer_methods + async fn test_register_operator( + avs_writer: &AvsRegistryChainWriter, + private_key_decimal: String, + quorum_nums: Bytes, + ) { + let bls_key_pair = BlsKeyPair::new(private_key_decimal).unwrap(); + let digest_hash: FixedBytes<32> = FixedBytes::from([0x02; 32]); + + // this is set to U256::MAX so that the registry does not take the signature as expired. + let signature_expiry = U256::MAX; + let tx_hash = avs_writer + .register_operator_in_quorum_with_avs_registry_coordinator( + bls_key_pair, + digest_hash, + signature_expiry, + quorum_nums.clone(), + "".into(), + ) + .await + .unwrap(); + + let tx_status = get_transaction_status(tx_hash).await; + assert!(tx_status); + } + + // this function is caller from test_avs_writer_methods + async fn test_deregister_operator(avs_writer: &AvsRegistryChainWriter, quorum_nums: Bytes) { + let tx_hash = avs_writer.deregister_operator(quorum_nums).await.unwrap(); + + let tx_status = get_transaction_status(tx_hash).await; + assert!(tx_status); } } diff --git a/crates/chainio/clients/elcontracts/src/reader.rs b/crates/chainio/clients/elcontracts/src/reader.rs index 0ab0169b..01a5ca6d 100644 --- a/crates/chainio/clients/elcontracts/src/reader.rs +++ b/crates/chainio/clients/elcontracts/src/reader.rs @@ -301,7 +301,7 @@ mod tests { use alloy_primitives::{address, keccak256, Address, FixedBytes, U256}; use alloy_provider::Provider; use eigen_logging::get_test_logger; - use eigen_testing_utils::anvil_constants::{self, ANVIL_RPC_URL}; + use eigen_testing_utils::anvil_constants::{self, ANVIL_HTTP_URL, ANVIL_RPC_URL}; use eigen_utils::binding::{ mockAvsServiceManager, AVSDirectory, AVSDirectory::calculateOperatorAVSRegistrationDigestHashReturn, DelegationManager, @@ -339,7 +339,7 @@ mod tests { slasher_address, delegation_manager_address, avs_directory_address, - "http://localhost:8545".to_string(), + ANVIL_HTTP_URL.to_string(), ) } diff --git a/crates/chainio/clients/elcontracts/src/writer.rs b/crates/chainio/clients/elcontracts/src/writer.rs index 30a316cc..23250777 100644 --- a/crates/chainio/clients/elcontracts/src/writer.rs +++ b/crates/chainio/clients/elcontracts/src/writer.rs @@ -65,7 +65,7 @@ impl ELChainWriter { let binding_tx = binding .send() .await - .map_err(|e| ElContractsError::AlloyContractError(e))?; + .map_err(ElContractsError::AlloyContractError)?; let receipt = binding_tx.get_receipt().await.map_err(|e| { ElContractsError::AlloyContractError(alloy_contract::Error::TransportError(e)) @@ -104,7 +104,7 @@ impl ELChainWriter { let modify_operator_tx = contract_call_modify_operator_details .send() .await - .map_err(|e| ElContractsError::AlloyContractError(e))?; + .map_err(ElContractsError::AlloyContractError)?; info!(tx_hash = %modify_operator_tx.tx_hash(), operator = %operator.has_address(), "updated operator details tx"); @@ -174,13 +174,13 @@ mod tests { use eigen_logging::get_test_logger; use eigen_testing_utils::anvil_constants::{ self, get_delegation_manager_address, get_erc20_mock_strategy, get_service_manager_address, - get_strategy_manager_address, + get_strategy_manager_address, ANVIL_HTTP_URL, }; use eigen_types::operator::Operator; - use eigen_utils::binding::DelegationManager; use eigen_utils::binding::{ mockAvsServiceManager, ContractsRegistry::{self, get_test_valuesReturn}, + DelegationManager, }; use std::str::FromStr; @@ -221,7 +221,7 @@ mod tests { slasher_address, delegation_manager_address, avs_directory_address, - "http://localhost:8545".to_string(), + ANVIL_HTTP_URL.to_string(), ), delegation_manager_address, ) diff --git a/crates/chainio/clients/eth/src/instrumented_client.rs b/crates/chainio/clients/eth/src/instrumented_client.rs index b76aaaaa..920f6446 100644 --- a/crates/chainio/clients/eth/src/instrumented_client.rs +++ b/crates/chainio/clients/eth/src/instrumented_client.rs @@ -824,14 +824,11 @@ mod tests { pubsub::SubscriptionResult, BlockId, BlockNumberOrTag, BlockTransactionsKind, }; use eigen_signer::signer::Config; - use eigen_testing_utils::anvil_constants::ANVIL_RPC_URL; + use eigen_testing_utils::anvil_constants::{ANVIL_HTTP_URL, ANVIL_RPC_URL, ANVIL_WS_URL}; use serial_test::serial; use std::{thread, time}; use tokio; - const ANVIL_HTTP_URL: &str = "http://localhost:8545"; - const ANVIL_WS_URL: &str = "ws://localhost:8545"; - #[tokio::test] #[serial] async fn test_suggest_gas_tip_cap() { diff --git a/crates/eigen-cli/src/args.rs b/crates/eigen-cli/src/args.rs index 79f3a9da..73bac04a 100644 --- a/crates/eigen-cli/src/args.rs +++ b/crates/eigen-cli/src/args.rs @@ -1,6 +1,6 @@ -use crate::ANVIL_RPC_URL; use alloy_primitives::Address; use clap::{ArgGroup, Parser, Subcommand}; +use eigen_testing_utils::anvil_constants::ANVIL_HTTP_URL; use rust_bls_bn254::{ CHINESE_SIMPLIFIED_WORD_LIST, CHINESE_TRADITIONAL_WORD_LIST, CZECH_WORD_LIST, ENGLISH_WORD_LIST, ITALIAN_WORD_LIST, KOREAN_WORD_LIST, PORTUGUESE_WORD_LIST, @@ -19,7 +19,7 @@ pub struct Args { #[derive(Subcommand, Debug)] pub enum Commands { #[command( - about = "Given an initial contract address, which can be either a registry coordinator or service manager address, + about = "Given an initial contract address, which can be either a registry coordinator or service manager address, outputs addresses for all relevant Eigenlayer and AVS contracts within the network", name = "egnaddrs", group( @@ -43,7 +43,7 @@ outputs addresses for all relevant Eigenlayer and AVS contracts within the netwo )] registry_coordinator: Option
, - #[arg(long, help = "rpc url", default_value = ANVIL_RPC_URL)] + #[arg(long, help = "rpc url", default_value = ANVIL_HTTP_URL)] rpc_url: String, }, @@ -59,7 +59,7 @@ pub enum EigenKeyCommand { #[command( about = "Generate keys for testing purpose. This command creates ecdsa or bls key pair for testing purposes. It generates -all the relevant files for reading the key and decrypts it and also gets +all the relevant files for reading the key and decrypts it and also gets you the private keys in plaintext. It creates the following artifacts based on arguments diff --git a/crates/eigen-cli/src/lib.rs b/crates/eigen-cli/src/lib.rs index a129679d..d23197b8 100644 --- a/crates/eigen-cli/src/lib.rs +++ b/crates/eigen-cli/src/lib.rs @@ -27,8 +27,6 @@ use operator_id::derive_operator_id; use rust_bls_bn254::{errors::KeystoreError as BlsKeystoreError, mnemonics::Mnemonic}; use thiserror::Error; -pub const ANVIL_RPC_URL: &str = "http://localhost:8545"; - /// Possible errors raised while executing a CLI command #[derive(Error, Debug)] pub enum EigenCliError { @@ -187,7 +185,6 @@ pub fn execute_command(command: Commands) -> Result<(), EigenCliError> { #[cfg(test)] mod test { - use super::ANVIL_RPC_URL; use crate::args::{BlsKeystoreType, EigenKeyCommand, MnemonicLanguage}; use crate::convert::store; use crate::eigen_address::ContractAddresses; @@ -198,7 +195,7 @@ mod test { operator_id::derive_operator_id, }; use eigen_testing_utils::anvil_constants::{ - get_registry_coordinator_address, get_service_manager_address, + get_registry_coordinator_address, get_service_manager_address, ANVIL_HTTP_URL, }; use eth_keystore::decrypt_key; use k256::SecretKey; @@ -303,7 +300,7 @@ mod test { let addresses = ContractAddresses::get_addresses( Some(service_manager_address), None, - ANVIL_RPC_URL.into(), + ANVIL_HTTP_URL.into(), ) .await .unwrap(); @@ -340,7 +337,7 @@ mod test { let addresses = ContractAddresses::get_addresses( None, Some(registry_coordinator_address), - ANVIL_RPC_URL.into(), + ANVIL_HTTP_URL.into(), ) .await .unwrap(); diff --git a/crates/types/Cargo.toml b/crates/types/Cargo.toml index a9a1bd14..c7afb843 100644 --- a/crates/types/Cargo.toml +++ b/crates/types/Cargo.toml @@ -9,11 +9,11 @@ repository.workspace = true license-file.workspace = true [dependencies] +alloy-primitives.workspace = true ark-serialize.workspace = true +eigen-crypto-bls.workspace = true ethers.workspace = true num-bigint = "0.4.4" -eigen-crypto-bls.workspace = true -alloy-primitives.workspace = true thiserror.workspace = true tokio.workspace = true diff --git a/testing/testing-utils/Cargo.toml b/testing/testing-utils/Cargo.toml index 26592cae..591798dc 100644 --- a/testing/testing-utils/Cargo.toml +++ b/testing/testing-utils/Cargo.toml @@ -18,3 +18,4 @@ alloy-provider.workspace = true alloy-transport-http.workspace = true eigen-utils.workspace = true once_cell.workspace = true +tokio.workspace = true diff --git a/testing/testing-utils/src/anvil_constants.rs b/testing/testing-utils/src/anvil_constants.rs index 5e6d06cb..77a2b0e9 100644 --- a/testing/testing-utils/src/anvil_constants.rs +++ b/testing/testing-utils/src/anvil_constants.rs @@ -1,9 +1,9 @@ //! Anvil utilities use alloy_network::Ethereum; -use alloy_primitives::{address, Address}; +use alloy_primitives::{address, Address, FixedBytes}; use alloy_provider::{ fillers::{ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller}, - RootProvider, + Provider, RootProvider, }; use alloy_transport_http::{Client, Http}; use eigen_utils::{ @@ -11,10 +11,17 @@ use eigen_utils::{ get_provider, }; use once_cell::sync::Lazy; +use tokio::time::{sleep, Duration}; /// Local anvil ContractsRegistry which contains a mapping of all locally deployed EL contracts. pub const CONTRACTS_REGISTRY: Address = address!("5FbDB2315678afecb367f032d93F642f64180aa3"); +/// Local anvil rpc http url +pub const ANVIL_HTTP_URL: &str = "http://localhost:8545"; + +/// Local anvil rpc WS url +pub const ANVIL_WS_URL: &str = "ws://localhost:8545"; + #[allow(clippy::type_complexity)] /// Local anvil rpc url alloy instance pub static ANVIL_RPC_URL: Lazy< @@ -27,7 +34,7 @@ pub static ANVIL_RPC_URL: Lazy< Http, Ethereum, >, -> = Lazy::new(|| get_provider("http://localhost:8545")); +> = Lazy::new(|| get_provider(ANVIL_HTTP_URL)); /// Service Manager contract address pub async fn get_service_manager_address() -> Address { @@ -132,3 +139,24 @@ pub async fn get_proxy_admin() -> Address { address } + +/// Retrieves the status of a transaction from its hash. +/// +/// # Arguments +/// +/// `tx_hash` - The hash of the transaction. +/// +/// # Returns +/// +/// A bool indicating wether the transaction was successful or not. +pub async fn get_transaction_status(tx_hash: FixedBytes<32>) -> bool { + // this sleep is needed so that we wait for the tx to be processed + sleep(Duration::from_millis(500)).await; + ANVIL_RPC_URL + .clone() + .get_transaction_receipt(tx_hash) + .await + .unwrap() + .unwrap() + .status() +}