@@ -375,6 +375,35 @@ impl AvsRegistryChainWriter {
375
375
Ok ( * tx. tx_hash ( ) )
376
376
}
377
377
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
+
378
407
/// This function is used to update the account identifier of the AVS's RegistryCoordinator.
379
408
///
380
409
/// # Arguments
@@ -435,7 +464,9 @@ impl AvsRegistryChainWriter {
435
464
mod tests {
436
465
437
466
use super :: AvsRegistryChainWriter ;
467
+ use crate :: test_utils:: build_avs_registry_chain_reader;
438
468
use crate :: test_utils:: create_operator_set;
469
+ use crate :: test_utils:: OPERATOR_BLS_KEY ;
439
470
use alloy:: primitives:: { Address , Bytes , FixedBytes , U256 } ;
440
471
use eigen_common:: { get_provider, get_signer} ;
441
472
use eigen_crypto_bls:: BlsKeyPair ;
@@ -773,4 +804,49 @@ mod tests {
773
804
operator_set_params. kickBIPsOfTotalStake
774
805
) ;
775
806
}
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
+ }
776
852
}
0 commit comments