Skip to content

Commit

Permalink
Merge pull request #550 from chainbound/operator-info
Browse files Browse the repository at this point in the history
feat(bolt-cli): log if operators have collateral
  • Loading branch information
thedevbirb authored Dec 12, 2024
2 parents 16152bd + ae97493 commit 67f5922
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 44 deletions.
3 changes: 2 additions & 1 deletion bolt-cli/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bolt-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ tracing = "0.1.40"
tracing-subscriber = "0.3.18"
reqwest = { version = "0.12.9", features = ["rustls-tls"] }
rand = "0.8.5"
lazy_static = "1.5.0"

[dev-dependencies]
tempfile = "3.13.0"
Expand Down
68 changes: 65 additions & 3 deletions bolt-cli/src/commands/operators.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use alloy::{
network::EthereumWallet,
node_bindings::WEI_IN_ETHER,
primitives::{utils::format_ether, Bytes},
primitives::{
utils::{format_ether, Unit},
Bytes, Uint,
},
providers::{Provider, ProviderBuilder, WalletProvider},
signers::{local::PrivateKeySigner, SignerSync},
sol_types::SolInterface,
Expand Down Expand Up @@ -65,7 +67,7 @@ impl OperatorsCommand {

let token = strategy_contract.underlyingToken().call().await?.token;

let amount = amount * WEI_IN_ETHER;
let amount = amount * Unit::ETHER.wei();

info!(%strategy, %token, amount = format_ether(amount), ?operator, "Depositing funds into EigenLayer strategy");

Expand Down Expand Up @@ -254,6 +256,36 @@ impl OperatorsCommand {
warn!(?address, "Operator not registered");
}

// Check if operator has collateral
let mut total_collateral = Uint::from(0);
for (name, address) in deployments.collateral {
let stake =
match bolt_manager.getOperatorStake(address, address).call().await {
Ok(stake) => stake._0,
Err(e) => match try_parse_contract_error::<
BoltEigenLayerMiddlewareErrors,
>(e)?
{
BoltEigenLayerMiddlewareErrors::KeyNotFound(_) => Uint::from(0),
other => unreachable!(
"Unexpected error with selector {:?}",
other.selector()
),
},
};
if stake > Uint::from(0) {
total_collateral += stake;
info!(?address, token = %name, amount = ?stake, "Operator has collateral");
}
}
if total_collateral >= Unit::ETHER.wei() {
info!(?address, total_collateral=?total_collateral, "Operator is active");
} else if total_collateral > Uint::from(0) {
info!(?address, total_collateral=?total_collateral, "Total operator collateral");
} else {
warn!(?address, "Operator has no collateral");
}

Ok(())
}
},
Expand Down Expand Up @@ -400,6 +432,36 @@ impl OperatorsCommand {
warn!(?address, "Operator not registered");
}

// Check if operator has collateral
let mut total_collateral = Uint::from(0);
for (name, address) in deployments.collateral {
let stake =
match bolt_manager.getOperatorStake(address, address).call().await {
Ok(stake) => stake._0,
Err(e) => match try_parse_contract_error::<
BoltSymbioticMiddlewareErrors,
>(e)?
{
BoltSymbioticMiddlewareErrors::KeyNotFound(_) => Uint::from(0),
other => unreachable!(
"Unexpected error with selector {:?}",
other.selector()
),
},
};
if stake > Uint::from(0) {
total_collateral += stake;
info!(?address, token = %name, amount = ?stake, "Operator has collateral");
}
}
if total_collateral >= Unit::ETHER.wei() {
info!(?address, total_collateral=?total_collateral, "Operator is active");
} else if total_collateral > Uint::from(0) {
info!(?address, total_collateral=?total_collateral, "Total operator collateral");
} else {
warn!(?address, "Operator has no collateral");
}

Ok(())
}
},
Expand Down
1 change: 1 addition & 0 deletions bolt-cli/src/common/bolt_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ sol! {
function getProposerStatus(bytes32 pubkeyHash) external view returns (ProposerStatus memory);

function isOperator(address operator) public view returns (bool);
function getOperatorStake(address operator, address collateral) public view returns (uint256);

error InvalidQuery();
error ValidatorDoesNotExist();
Expand Down
2 changes: 2 additions & 0 deletions bolt-cli/src/contracts/bolt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ sol! {
error AlreadyRegistered();
error NotOperator();
error NotRegistered();
error KeyNotFound();
}

#[allow(missing_docs)]
Expand All @@ -87,5 +88,6 @@ sol! {
error AlreadyRegistered();
error NotOperator();
error NotRegistered();
error KeyNotFound();
}
}
92 changes: 52 additions & 40 deletions bolt-cli/src/contracts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::collections::HashMap;

use alloy::primitives::{address, Address};
use clap::ValueEnum;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};

use crate::cli::Chain;
Expand All @@ -16,6 +17,7 @@ pub struct Contracts {
pub bolt: Bolt,
pub symbiotic: Symbiotic,
pub eigen_layer: EigenLayer,
pub collateral: [(String, Address); 6],
}

#[derive(Clone, Serialize, Deserialize, Debug)]
Expand Down Expand Up @@ -97,7 +99,7 @@ pub fn strategy_to_address(

pub fn deployments() -> HashMap<Chain, Contracts> {
let mut deployments = HashMap::new();
deployments.insert(Chain::Holesky, HOLESKY_DEPLOYMENTS);
deployments.insert(Chain::Holesky, HOLESKY_DEPLOYMENTS.clone());

deployments
}
Expand All @@ -106,43 +108,53 @@ pub fn deployments_for_chain(chain: Chain) -> Contracts {
deployments().get(&chain).cloned().expect("no deployments for chain")
}

const HOLESKY_DEPLOYMENTS: Contracts = Contracts {
bolt: Bolt {
validators: address!("47D2DC1DE1eFEFA5e6944402f2eda3981D36a9c8"),
parameters: address!("20d1cf3A5BD5928dB3118b2CfEF54FDF9fda5c12"),
manager: address!("440202829b493F9FF43E730EB5e8379EEa3678CF"),
eigenlayer_middleware: address!("a632a3e652110Bb2901D5cE390685E6a9838Ca04"),
symbiotic_middleware: address!("04f40d9CaE475E5BaA462acE53E5c58A0DD8D8e8"),
},
symbiotic: Symbiotic {
network: address!("b017002D8024d8c8870A5CECeFCc63887650D2a4"),
operator_registry: address!("6F75a4ffF97326A00e52662d82EA4FdE86a2C548"),
network_opt_in_service: address!("58973d16FFA900D11fC22e5e2B6840d9f7e13401"),
vault_factory: address!("407A039D94948484D356eFB765b3c74382A050B4"),
vault_configurator: address!("D2191FE92987171691d552C219b8caEf186eb9cA"),
network_registry: address!("7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9"),
network_middleware_service: address!("62a1ddfD86b4c1636759d9286D3A0EC722D086e3"),
middleware: address!("04f40d9CaE475E5BaA462acE53E5c58A0DD8D8e8"),
supported_vaults: [
address!("c79c533a77691641d52ebD5e87E51dCbCaeb0D78"),
address!("e5708788c90e971f73D928b7c5A8FD09137010e0"),
address!("11c5b9A9cd8269580aDDbeE38857eE451c1CFacd"),
address!("C56Ba584929c6f381744fA2d7a028fA927817f2b"),
address!("cDdeFfcD2bA579B8801af1d603812fF64c301462"),
address!("91e84e12Bb65576C0a6614c5E6EbbB2eA595E10f"),
],
},
eigen_layer: EigenLayer {
avs_directory: address!("055733000064333CaDDbC92763c58BF0192fFeBf"),
delegation_manager: address!("A44151489861Fe9e3055d95adC98FbD462B948e7"),
strategy_manager: address!("dfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6"),
middleware: address!("a632a3e652110Bb2901D5cE390685E6a9838Ca04"),
supported_strategies: EigenLayerStrategies {
st_eth: address!("7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3"),
r_eth: address!("3A8fBdf9e77DFc25d09741f51d3E181b25d0c4E0"),
w_eth: address!("80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9"),
cb_eth: address!("70EB4D3c164a6B4A5f908D4FBb5a9cAfFb66bAB6"),
m_eth: address!("accc5A86732BE85b5012e8614AF237801636F8e5"),
lazy_static! {
pub static ref HOLESKY_DEPLOYMENTS: Contracts = Contracts {
bolt: Bolt {
validators: address!("47D2DC1DE1eFEFA5e6944402f2eda3981D36a9c8"),
parameters: address!("20d1cf3A5BD5928dB3118b2CfEF54FDF9fda5c12"),
manager: address!("440202829b493F9FF43E730EB5e8379EEa3678CF"),
eigenlayer_middleware: address!("a632a3e652110Bb2901D5cE390685E6a9838Ca04"),
symbiotic_middleware: address!("04f40d9CaE475E5BaA462acE53E5c58A0DD8D8e8"),
},
symbiotic: Symbiotic {
network: address!("b017002D8024d8c8870A5CECeFCc63887650D2a4"),
operator_registry: address!("6F75a4ffF97326A00e52662d82EA4FdE86a2C548"),
network_opt_in_service: address!("58973d16FFA900D11fC22e5e2B6840d9f7e13401"),
vault_factory: address!("407A039D94948484D356eFB765b3c74382A050B4"),
vault_configurator: address!("D2191FE92987171691d552C219b8caEf186eb9cA"),
network_registry: address!("7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9"),
network_middleware_service: address!("62a1ddfD86b4c1636759d9286D3A0EC722D086e3"),
middleware: address!("04f40d9CaE475E5BaA462acE53E5c58A0DD8D8e8"),
supported_vaults: [
address!("c79c533a77691641d52ebD5e87E51dCbCaeb0D78"),
address!("e5708788c90e971f73D928b7c5A8FD09137010e0"),
address!("11c5b9A9cd8269580aDDbeE38857eE451c1CFacd"),
address!("C56Ba584929c6f381744fA2d7a028fA927817f2b"),
address!("cDdeFfcD2bA579B8801af1d603812fF64c301462"),
address!("91e84e12Bb65576C0a6614c5E6EbbB2eA595E10f"),
],
},
eigen_layer: EigenLayer {
avs_directory: address!("055733000064333CaDDbC92763c58BF0192fFeBf"),
delegation_manager: address!("A44151489861Fe9e3055d95adC98FbD462B948e7"),
strategy_manager: address!("dfB5f6CE42aAA7830E94ECFCcAd411beF4d4D5b6"),
middleware: address!("a632a3e652110Bb2901D5cE390685E6a9838Ca04"),
supported_strategies: EigenLayerStrategies {
st_eth: address!("7D704507b76571a51d9caE8AdDAbBFd0ba0e63d3"),
r_eth: address!("3A8fBdf9e77DFc25d09741f51d3E181b25d0c4E0"),
w_eth: address!("80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9"),
cb_eth: address!("70EB4D3c164a6B4A5f908D4FBb5a9cAfFb66bAB6"),
m_eth: address!("accc5A86732BE85b5012e8614AF237801636F8e5"),
},
},
},
};
collateral: [
("wst_eth".to_string(), address!("8d09a4502Cc8Cf1547aD300E066060D043f6982D")),
("r_eth".to_string(), address!("7322c24752f79c05FFD1E2a6FCB97020C1C264F1")),
("st_eth".to_string(), address!("3F1c547b21f65e10480dE3ad8E19fAAC46C95034")),
("w_eth".to_string(), address!("94373a4919B3240D86eA41593D5eBa789FEF3848")),
("cb_eth".to_string(), address!("8720095Fa5739Ab051799211B146a2EEE4Dd8B37")),
("m_eth".to_string(), address!("e3C063B1BEe9de02eb28352b55D49D85514C67FF")),
],
};
}

0 comments on commit 67f5922

Please sign in to comment.