From 85de2260edddbf94dd1be44d2a822fda52019637 Mon Sep 17 00:00:00 2001 From: Jonas Bostoen Date: Fri, 29 Nov 2024 14:49:01 +0100 Subject: [PATCH] feat(cli): add operator deregistration commands --- bolt-cli/src/cli.rs | 21 ++++++++ bolt-cli/src/commands/operators.rs | 81 +++++++++++++++++++++++++++++- bolt-cli/src/contracts/bolt.rs | 9 ++++ 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/bolt-cli/src/cli.rs b/bolt-cli/src/cli.rs index ffdeb11a2..1e2cf60f7 100644 --- a/bolt-cli/src/cli.rs +++ b/bolt-cli/src/cli.rs @@ -228,6 +228,16 @@ pub enum EigenLayerSubcommand { expiry: U256, }, + /// Deregister an EigenLayer operator from the bolt AVS. + Deregister { + /// The URL of the RPC to broadcast the transaction. + #[clap(long, env = "RPC_URL")] + rpc_url: Url, + /// The private key of the operator. + #[clap(long, env = "OPERATOR_PRIVATE_KEY")] + operator_private_key: B256, + }, + /// Step 3: Check your operation registration in bolt Status { /// The URL of the RPC to broadcast the transaction. @@ -253,6 +263,17 @@ pub enum SymbioticSubcommand { #[clap(long, env = "OPERATOR_RPC")] operator_rpc: Url, }, + + /// Deregister a Symbiotic operator from bolt. + Deregister { + /// The URL of the RPC to broadcast the transaction. + #[clap(long, env = "RPC_URL")] + rpc_url: Url, + /// The private key of the operator. + #[clap(long, env = "OPERATOR_PRIVATE_KEY")] + operator_private_key: B256, + }, + /// Check the status of a Symbiotic operator. Status { /// The URL of the RPC to broadcast the transaction. diff --git a/bolt-cli/src/commands/operators.rs b/bolt-cli/src/commands/operators.rs index b72ee7dd5..a66e9d96b 100644 --- a/bolt-cli/src/commands/operators.rs +++ b/bolt-cli/src/commands/operators.rs @@ -164,7 +164,46 @@ impl OperatorsCommand { eyre::bail!("Transaction failed: {:?}", receipt) } - info!("Succesfully registered Symbiotic operator"); + info!("Succesfully registered EigenLayer operator"); + + Ok(()) + } + EigenLayerSubcommand::Deregister { rpc_url, operator_private_key } => { + let signer = PrivateKeySigner::from_bytes(&operator_private_key) + .wrap_err("valid private key")?; + + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .wallet(EthereumWallet::from(signer.clone())) + .on_http(rpc_url.clone()); + + let chain_id = provider.get_chain_id().await?; + let chain = Chain::from_id(chain_id) + .unwrap_or_else(|| panic!("chain id {} not supported", chain_id)); + + info!(operator = %signer.address(), ?chain, "Deregistering EigenLayer operator"); + + request_confirmation(); + + let deployments = deployments_for_chain(chain); + + let bolt_avs_address = deployments.bolt.eigenlayer_middleware; + let bolt_eigenlayer_middleware = + BoltEigenLayerMiddleware::new(bolt_avs_address, provider.clone()); + + let result = bolt_eigenlayer_middleware.deregisterOperator().send().await?; + + info!( + hash = ?result.tx_hash(), + "deregisterOperator transaction sent, awaiting receipt..." + ); + + let receipt = result.get_receipt().await?; + if !receipt.status() { + eyre::bail!("Transaction failed: {:?}", receipt) + } + + info!("Succesfully deregistered EigenLayer operator"); Ok(()) } @@ -245,6 +284,46 @@ impl OperatorsCommand { Ok(()) } + SymbioticSubcommand::Deregister { rpc_url, operator_private_key } => { + let signer = PrivateKeySigner::from_bytes(&operator_private_key) + .wrap_err("valid private key")?; + + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .wallet(EthereumWallet::from(signer.clone())) + .on_http(rpc_url); + + let chain_id = provider.get_chain_id().await?; + let chain = Chain::from_id(chain_id) + .unwrap_or_else(|| panic!("chain id {} not supported", chain_id)); + + let deployments = deployments_for_chain(chain); + + info!(operator = %signer.address(), ?chain, "Deregistering Symbiotic operator"); + + request_confirmation(); + + let middleware = BoltSymbioticMiddleware::new( + deployments.bolt.symbiotic_middleware, + provider.clone(), + ); + + let pending = middleware.deregisterOperator().send().await?; + + info!( + hash = ?pending.tx_hash(), + "deregisterOperator transaction sent, awaiting receipt..." + ); + + let receipt = pending.get_receipt().await?; + if !receipt.status() { + eyre::bail!("Transaction failed: {:?}", receipt) + } + + info!("Succesfully deregistered Symbiotic operator"); + + Ok(()) + } SymbioticSubcommand::Status { rpc_url, address } => { let provider = ProviderBuilder::new().on_http(rpc_url.clone()); let chain_id = provider.get_chain_id().await?; diff --git a/bolt-cli/src/contracts/bolt.rs b/bolt-cli/src/contracts/bolt.rs index a07e226df..97d1988d1 100644 --- a/bolt-cli/src/contracts/bolt.rs +++ b/bolt-cli/src/contracts/bolt.rs @@ -36,6 +36,11 @@ sol! { /// EigenLayer internally contains a mapping from `msg.sender` (our AVS contract) to the operator. /// The msg.sender of this call will be the operator address. function registerOperator(string calldata rpc, SignatureWithSaltAndExpiry calldata operatorSignature) public; + + /// @notice Deregister an EigenLayer operator from working in Bolt Protocol. + /// @dev This requires calling the EigenLayer AVS Directory contract to deregister the operator. + /// EigenLayer internally contains a mapping from `msg.sender` (our AVS contract) to the operator. + function deregisterOperator() public; } #[allow(missing_docs)] @@ -45,6 +50,10 @@ sol! { /// msg.sender must be an operator in the Symbiotic network. function registerOperator(string calldata rpc) public; + /// @notice Deregister a Symbiotic operator from working in Bolt Protocol. + /// @dev This does NOT deregister the operator from the Symbiotic network. + function deregisterOperator() public; + /// @notice Get the collaterals and amounts staked by an operator across the supported strategies. /// /// @param operator The operator address to get the collaterals and amounts staked for.