Skip to content

Commit

Permalink
feat(cli): query EL strategies and Symbiotic vaults via CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Jan 24, 2025
1 parent 639d18e commit 184de4a
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 11 deletions.
16 changes: 15 additions & 1 deletion bolt-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,13 +291,20 @@ pub enum EigenLayerSubcommand {

/// Check the status of an operator in the bolt AVS.
Status {
/// The URL of the RPC to broadcast the transaction.
/// The URL of the RPC to read data from
#[clap(long, env = "RPC_URL")]
rpc_url: Url,
/// The address of the operator to check.
#[clap(long, env = "OPERATOR_ADDRESS")]
address: Address,
},

/// List all whitelisted EigenLayer strategies
ListStrategies {
/// The URL of the RPC to read data from
#[clap(long, env = "RPC_URL")]
rpc_url: Url,
},
}

#[derive(Debug, Clone, Parser)]
Expand Down Expand Up @@ -352,6 +359,13 @@ pub enum SymbioticSubcommand {
#[clap(long, env = "OPERATOR_ADDRESS")]
address: Address,
},

/// List all whitelisted Symbiotic vaults
ListVaults {
/// The URL of the RPC to read data from
#[clap(long, env = "RPC_URL")]
rpc_url: Url,
},
}

#[derive(Debug, Clone, Parser)]
Expand Down
46 changes: 44 additions & 2 deletions bolt-cli/src/commands/operators/eigenlayer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ use crate::{
},
deployments_for_chain,
eigenlayer::{
AVSDirectory, IStrategy::IStrategyInstance, IStrategyManager::IStrategyManagerInstance,
AVSDirectory,
IStrategy::{self, IStrategyInstance},
IStrategyManager::IStrategyManagerInstance,
},
erc20::IERC20::IERC20Instance,
erc20::IERC20::{self, IERC20Instance},
},
};

Expand Down Expand Up @@ -470,6 +472,46 @@ impl EigenLayerSubcommand {

Ok(())
}

Self::ListStrategies { rpc_url } => {
let provider = ProviderBuilder::new().on_http(rpc_url.clone());

let chain = Chain::try_from_provider(&provider).await?;

let deployments = deployments_for_chain(chain);

info!("Listing all EigenLayer whitelisted strategies:");

// TODO(nico): consolidate holesky & mainnet smart contracts
let strategies = if chain == Chain::Mainnet {
let el_middleware = BoltEigenLayerMiddlewareMainnet::new(
deployments.bolt.eigenlayer_middleware,
&provider,
);

el_middleware.getActiveWhitelistedStrategies().call().await?._0
} else if chain == Chain::Holesky {
let el_middleware = BoltEigenLayerMiddlewareHolesky::new(
deployments.bolt.eigenlayer_middleware,
&provider,
);

el_middleware.getRestakeableStrategies().call().await?._0
} else {
unreachable!("Invalid chain");
};

for strategy_address in strategies {
let strategy = IStrategy::new(strategy_address, &provider);
let token_address = strategy.underlyingToken().call().await?.token;
let token = IERC20::new(token_address, &provider);
let token_symbol = token.symbol().call().await?._0;

info!("- Token: {} - Strategy: {}", token_symbol, strategy_address);
}

Ok(())
}
}
}
}
Expand Down
44 changes: 41 additions & 3 deletions bolt-cli/src/commands/operators/symbiotic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ use crate::{
BoltSymbioticMiddlewareHolesky::{self, BoltSymbioticMiddlewareHoleskyErrors},
BoltSymbioticMiddlewareMainnet::{self, BoltSymbioticMiddlewareMainnetErrors},
OperatorsRegistryV1::{self, OperatorsRegistryV1Errors}
},
deployments_for_chain,
symbiotic::IOptInService,
}, deployments_for_chain, erc20::IERC20, symbiotic::{IOptInService, IVault}
},
};

Expand Down Expand Up @@ -365,6 +363,46 @@ impl SymbioticSubcommand {

Ok(())
}

Self::ListVaults { rpc_url } => {
let provider = ProviderBuilder::new().on_http(rpc_url.clone());

let chain = Chain::try_from_provider(&provider).await?;

let deployments = deployments_for_chain(chain);

info!("Listing all Symbiotic whitelisted vaults:");

// TODO(nico): consolidate holesky & mainnet smart contracts
let vaults = if chain == Chain::Mainnet {
let symb_middleware = BoltSymbioticMiddlewareMainnet::new(
deployments.bolt.symbiotic_middleware,
&provider,
);

symb_middleware.getActiveWhitelistedVaults().call().await?._0
} else if chain == Chain::Holesky {
let symb_middleware = BoltSymbioticMiddlewareHolesky::new(
deployments.bolt.symbiotic_middleware,
&provider,
);

symb_middleware.getWhitelistedVaults().call().await?._0
} else {
unreachable!("Invalid chain");
};

for vault_address in vaults {
let vault = IVault::new(vault_address, &provider);
let token_address = vault.collateral().call().await?._0;
let token = IERC20::new(token_address, &provider);
let token_symbol = token.symbol().call().await?._0;

info!("- Token: {} - Vault: {}", token_symbol, vault_address);
}

Ok(())
}
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions bolt-cli/src/contracts/bolt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ sol! {
/// @dev Assumes that the operator is registered and enabled.
function getOperatorCollaterals(address operator) public view returns (address[] memory, uint256[] memory);

/// @notice Get the list of currently restakeable strategies
function getRestakeableStrategies() external view returns (address[] memory);

error AlreadyRegistered();
error NotOperator();
error NotRegistered();
Expand Down Expand Up @@ -145,6 +148,9 @@ sol! {
/// @dev Assumes that the operator is registered and enabled.
function getOperatorCollaterals(address operator) public view returns (address[] memory, uint256[] memory);

/// @notice Get the whitelisted vaults.
function getWhitelistedVaults() public view returns (address[] memory);

error AlreadyRegistered();
error NotOperator();
error NotRegistered();
Expand Down Expand Up @@ -172,6 +178,8 @@ sol! {

function updateOperatorsRegistryAddress(address newOperatorsRegistry) public;

function getActiveWhitelistedStrategies() public view returns (address[] memory);

error InvalidRpc();
error InvalidSigner();
error Unauthorized();
Expand All @@ -193,6 +201,10 @@ sol! {

function deregisterOperator() public;

/// @notice Gets all _active_ whitelisted vaults.
/// @return An array of active whitelisted vaults.
function getActiveWhitelistedVaults() public view returns (address[] memory);

error NotOperator();
error OperatorNotOptedIn();
error OperatorNotRegistered();
Expand Down
9 changes: 9 additions & 0 deletions bolt-cli/src/contracts/erc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,14 @@ sol! {
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);

/// @notice Returns the name of the token.
function name() external view returns (string memory);

/// @notice Returns the symbol of the token.
function symbol() external view returns (string memory);

/// @notice Returns the decimals places of the token.
function decimals() external view returns (uint8);
}
}
8 changes: 3 additions & 5 deletions bolt-cli/src/contracts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,9 @@ lazy_static! {
parameters: address!("0000000000000000000000000000000000000000"),
manager: address!("0000000000000000000000000000000000000000"),

// TODO(nico): change these to mainnet actual addresses
// these point to our Anvil fork for now
operators_registry: address!("Ed8D7d3A98CB4ea6C91a80dcd2220719c264531f"),
eigenlayer_middleware: address!("2ca60d89144D4cdf85dA87af4FE12aBF9265F28C"),
symbiotic_middleware: address!("fD3e0cEe740271f070607aEddd0Bf4Cf99C92204"),
operators_registry: address!("630869F51C012C797FEb3D9006F4280587C78b3f"),
eigenlayer_middleware: address!("35DebC00531Ac8771be5dbEf015feFD084efA958"),
symbiotic_middleware: address!("74c4eF33fce5bbfDb786c65efca513C68C7d19C3"),
},
symbiotic: Symbiotic {
network: address!("A42ec46F2c9DC671a72218E145CC13dc119fB722"),
Expand Down
10 changes: 10 additions & 0 deletions bolt-cli/src/contracts/symbiotic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,14 @@ sol! {
*/
function isOptedIn(address who, address where) external view returns (bool);
}

#[allow(missing_docs)]
#[sol(rpc)]
interface IVault {
/**
* @notice Get a vault collateral.
* @return address of the underlying collateral
*/
function collateral() external view returns (address);
}
}

0 comments on commit 184de4a

Please sign in to comment.