Skip to content

Commit a59990a

Browse files
authored
feat: new method eject_operator in avsregistry/writer (#328)
### What Changed? Add new method `eject_operator` to `avsregistry/writer`. Related issue #310 ### Reviewer Checklist - [ ] New features are tested and documented - [ ] PR updates the changelog with a description of changes - [ ] PR has one of the `changelog-X` labels (if applies) - [ ] Code deprecates any old functionality before removing it
1 parent dfefaee commit a59990a

File tree

3 files changed

+114
-1
lines changed

3 files changed

+114
-1
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@ Those changes in added, changed or breaking changes, should include usage exampl
8282
.unwrap();
8383
```
8484

85+
* Added new method `eject_operator` in `avsregistry/writer` in [#328](https://github.com/Layr-Labs/eigensdk-rs/pull/328).
86+
87+
```rust
88+
let register_operator_address = address!("f39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
89+
let quorum_nums = Bytes::from([0]);
90+
91+
let tx_hash = avs_writer
92+
.eject_operator(register_operator_address, quorum_nums)
93+
.await
94+
.unwrap();
95+
```
96+
8597
* Added new method `is_operator_set_quorum` in `avsregistry/writer` in [#296](https://github.com/Layr-Labs/eigensdk-rs/pull/296).
8698

8799
```rust

crates/chainio/clients/avsregistry/src/lib.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ pub(crate) mod test_utils {
2626
sol_types::SolCall,
2727
};
2828
use eigen_common::get_signer;
29+
use eigen_logging::get_test_logger;
2930
use eigen_testing_utils::anvil_constants::{
30-
get_allocation_manager_address, get_erc20_mock_strategy, get_registry_coordinator_address,
31+
get_allocation_manager_address, get_erc20_mock_strategy,
32+
get_operator_state_retriever_address, get_registry_coordinator_address,
3133
get_service_manager_address, FIRST_PRIVATE_KEY,
3234
};
3335
use eigen_utils::slashing::{
@@ -39,6 +41,11 @@ pub(crate) mod test_utils {
3941
sdk::mockavsservicemanager::MockAvsServiceManager,
4042
};
4143

44+
use crate::reader::AvsRegistryChainReader;
45+
46+
pub(crate) const OPERATOR_BLS_KEY: &str =
47+
"1371012690269088913462269866874713266643928125698382731338806296762673180359922";
48+
4249
pub(crate) async fn create_operator_set(http_endpoint: &str, avs_address: Address) {
4350
let allocation_manager_addr =
4451
get_allocation_manager_address(http_endpoint.to_string()).await;
@@ -106,4 +113,22 @@ pub(crate) mod test_utils {
106113
.await
107114
.unwrap();
108115
}
116+
117+
pub(crate) async fn build_avs_registry_chain_reader(
118+
http_endpoint: String,
119+
) -> AvsRegistryChainReader {
120+
let registry_coordinator_addr =
121+
get_registry_coordinator_address(http_endpoint.clone()).await;
122+
let operator_state_retriever_address =
123+
get_operator_state_retriever_address(http_endpoint.clone()).await;
124+
125+
AvsRegistryChainReader::new(
126+
get_test_logger(),
127+
registry_coordinator_addr,
128+
operator_state_retriever_address,
129+
http_endpoint.to_string(),
130+
)
131+
.await
132+
.unwrap()
133+
}
109134
}

crates/chainio/clients/avsregistry/src/writer.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,35 @@ impl AvsRegistryChainWriter {
375375
Ok(*tx.tx_hash())
376376
}
377377

378+
/// Force a deregistration of an operator from one or more quorums
379+
///
380+
/// # Arguments
381+
///
382+
/// * `operator_address` - The address of the operator to be ejected
383+
/// * `quorum_numbers` - The quorum numbers to eject the operator from
384+
///
385+
/// # Returns
386+
///
387+
/// * `TxHash` - The transaction hash of the eject operator transaction
388+
pub async fn eject_operator(
389+
&self,
390+
operator_address: Address,
391+
quorum_numbers: Bytes,
392+
) -> Result<TxHash, AvsRegistryError> {
393+
info!("ejecting operator from quorum with the AVS's registry coordinator");
394+
let provider = get_signer(&self.signer.clone(), &self.provider);
395+
396+
let contract_registry_coordinator =
397+
RegistryCoordinator::new(self.registry_coordinator_addr, provider);
398+
399+
contract_registry_coordinator.ejectOperator(operator_address, quorum_numbers)
400+
.send()
401+
.await
402+
.map_err(AvsRegistryError::AlloyContractError)
403+
.inspect(|tx| info!(tx_hash = ?tx, "successfully ejected operator from quorum with the AVS's registry coordinator"))
404+
.map(|tx| *tx.tx_hash())
405+
}
406+
378407
/// This function is used to update the account identifier of the AVS's RegistryCoordinator.
379408
///
380409
/// # Arguments
@@ -435,7 +464,9 @@ impl AvsRegistryChainWriter {
435464
mod tests {
436465

437466
use super::AvsRegistryChainWriter;
467+
use crate::test_utils::build_avs_registry_chain_reader;
438468
use crate::test_utils::create_operator_set;
469+
use crate::test_utils::OPERATOR_BLS_KEY;
439470
use alloy::primitives::{Address, Bytes, FixedBytes, U256};
440471
use eigen_common::{get_provider, get_signer};
441472
use eigen_crypto_bls::BlsKeyPair;
@@ -773,4 +804,49 @@ mod tests {
773804
operator_set_params.kickBIPsOfTotalStake
774805
);
775806
}
807+
808+
#[tokio::test]
809+
async fn test_eject_operator() {
810+
let (_container, http_endpoint, _ws_endpoint) = start_m2_anvil_container().await;
811+
let bls_key = OPERATOR_BLS_KEY.to_string();
812+
let register_operator_address = FIRST_ADDRESS;
813+
let private_key = FIRST_PRIVATE_KEY.to_string();
814+
let quorum_nums = Bytes::from([0]);
815+
816+
let avs_writer =
817+
build_avs_registry_chain_writer(http_endpoint.clone(), private_key.clone()).await;
818+
819+
test_register_operator(
820+
&avs_writer,
821+
bls_key,
822+
quorum_nums.clone(),
823+
http_endpoint.clone(),
824+
)
825+
.await;
826+
827+
let avs_reader = build_avs_registry_chain_reader(http_endpoint.clone()).await;
828+
let is_registered = avs_reader
829+
.is_operator_registered(register_operator_address)
830+
.await
831+
.unwrap();
832+
assert!(is_registered);
833+
834+
let tx_hash = avs_writer
835+
.eject_operator(register_operator_address, quorum_nums)
836+
.await
837+
.unwrap();
838+
839+
let tx_status = wait_transaction(&http_endpoint, tx_hash)
840+
.await
841+
.unwrap()
842+
.status();
843+
844+
assert!(tx_status);
845+
846+
let is_registered = avs_reader
847+
.is_operator_registered(register_operator_address)
848+
.await
849+
.unwrap();
850+
assert!(!is_registered);
851+
}
776852
}

0 commit comments

Comments
 (0)