Skip to content
This repository was archived by the owner on Feb 23, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions bolt-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,11 @@ pub enum ValidatorsSubcommand {
/// The private key to sign the transactions with.
#[clap(long, env = "ADMIN_PRIVATE_KEY")]
admin_private_key: B256,

/// Run the command in "dry run" mode, run all steps without broadcast.
/// Useful for testing and debugging purposes.
#[clap(short, long, env = "DRY_RUN", default_value = "false")]
dry_run: bool,
},
/// Check the status of a validator (batch).
Status {
Expand Down Expand Up @@ -242,6 +247,10 @@ pub enum EigenLayerSubcommand {
/// The amount to deposit into the strategy, in units (e.g. '1ether', '10gwei').
#[clap(long, env = "EIGENLAYER_STRATEGY_DEPOSIT_AMOUNT", value_parser = parse_ether_value)]
amount: U256,
/// Run the command in "dry run" mode, run all steps without broadcast.
/// Useful for testing and debugging purposes.
#[clap(short, long, env = "DRY_RUN", default_value = "false")]
dry_run: bool,
},

/// Register an operator into the bolt AVS.
Expand All @@ -264,6 +273,10 @@ pub enum EigenLayerSubcommand {
/// If not provided, a random value is used.
#[clap(long, env = "OPERATOR_SIGNATURE_SALT")]
salt: Option<B256>,
/// Run the command in "dry run" mode, run all steps without broadcast.
/// Useful for testing and debugging purposes.
#[clap(short, long, env = "DRY_RUN", default_value = "false")]
dry_run: bool,
},

/// Deregister an EigenLayer operator from the bolt AVS.
Expand All @@ -274,6 +287,10 @@ pub enum EigenLayerSubcommand {
/// The private key of the operator.
#[clap(long, env = "OPERATOR_PRIVATE_KEY")]
operator_private_key: B256,
/// Run the command in "dry run" mode, run all steps without broadcast.
/// Useful for testing and debugging purposes.
#[clap(short, long, env = "DRY_RUN", default_value = "false")]
dry_run: bool,
},

/// Update the operator RPC.
Expand All @@ -287,6 +304,10 @@ pub enum EigenLayerSubcommand {
/// The URL of the operator RPC.
#[clap(long, env = "OPERATOR_RPC")]
operator_rpc: Url,
/// Run the command in "dry run" mode, run all steps without broadcast.
/// Useful for testing and debugging purposes.
#[clap(short, long, env = "DRY_RUN", default_value = "false")]
dry_run: bool,
},

/// Check the status of an operator in the bolt AVS.
Expand Down Expand Up @@ -325,6 +346,10 @@ pub enum SymbioticSubcommand {
/// The operator's extra data string to be stored in the registry.
#[clap(long, env = "OPERATOR_EXTRA_DATA")]
extra_data: String,
/// Run the command in "dry run" mode, run all steps without broadcast.
/// Useful for testing and debugging purposes.
#[clap(short, long, env = "DRY_RUN", default_value = "false")]
dry_run: bool,
},

/// Deregister a Symbiotic operator from bolt.
Expand All @@ -335,6 +360,10 @@ pub enum SymbioticSubcommand {
/// The private key of the operator.
#[clap(long, env = "OPERATOR_PRIVATE_KEY")]
operator_private_key: B256,
/// Run the command in "dry run" mode, run all steps without broadcast.
/// Useful for testing and debugging purposes.
#[clap(short, long, env = "DRY_RUN", default_value = "false")]
dry_run: bool,
},

/// Update the operator RPC.
Expand All @@ -348,6 +377,10 @@ pub enum SymbioticSubcommand {
/// The URL of the operator RPC.
#[clap(long, env = "OPERATOR_RPC")]
operator_rpc: Url,
/// Run the command in "dry run" mode, run all steps without broadcast.
/// Useful for testing and debugging purposes.
#[clap(short, long, env = "DRY_RUN", default_value = "false")]
dry_run: bool,
},

/// Check the status of a Symbiotic operator.
Expand Down
63 changes: 46 additions & 17 deletions bolt-cli/src/commands/operators/eigenlayer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use crate::{
cli::{Chain, EigenLayerSubcommand},
common::{
// bolt_manager::BoltManagerContract::{self, BoltManagerContractErrors},
handle_rpc_dry_run,
request_confirmation,
shutdown_anvil,
try_parse_contract_error,
},
contracts::{
Expand All @@ -41,15 +43,17 @@ impl EigenLayerSubcommand {
/// Run the EigenLayer subcommand.
pub async fn run(self) -> eyre::Result<()> {
match self {
Self::Deposit { rpc_url, strategy, amount, operator_private_key } => {
Self::Deposit { rpc_url, strategy, amount, operator_private_key, dry_run } => {
let signer = PrivateKeySigner::from_bytes(&operator_private_key)
.wrap_err("valid private key")?;
let operator = signer.address();

let (rpc, anvil) = handle_rpc_dry_run(rpc_url, dry_run)?;

let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(EthereumWallet::from(signer))
.on_http(rpc_url);
.on_http(rpc);

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

Expand Down Expand Up @@ -96,19 +100,30 @@ impl EigenLayerSubcommand {
eyre::bail!("Transaction failed: {:?}", receipt)
}

info!("Succesfully deposited collateral into strategy");
info!("Successfully deposited collateral into strategy");

shutdown_anvil(anvil);

Ok(())
}

Self::Register { rpc_url, operator_rpc, salt, operator_private_key, extra_data } => {
Self::Register {
rpc_url,
operator_rpc,
salt,
operator_private_key,
extra_data,
dry_run,
} => {
let signer = PrivateKeySigner::from_bytes(&operator_private_key)
.wrap_err("valid private key")?;

let (rpc, anvil) = handle_rpc_dry_run(rpc_url, dry_run)?;

let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(EthereumWallet::from(signer.clone()))
.on_http(rpc_url);
.on_http(rpc);

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

Expand Down Expand Up @@ -169,7 +184,7 @@ impl EigenLayerSubcommand {
eyre::bail!("Transaction failed: {:?}", receipt)
}

info!("Succesfully registered EigenLayer operator");
info!("Successfully registered EigenLayer operator");
}
Err(e) => parse_eigenlayer_middleware_mainnet_errors(e)?,
}
Expand All @@ -193,24 +208,28 @@ impl EigenLayerSubcommand {
eyre::bail!("Transaction failed: {:?}", receipt)
}

info!("Succesfully registered EigenLayer operator");
info!("Successfully registered EigenLayer operator");
}
Err(e) => parse_eigenlayer_middleware_holesky_errors(e)?,
}
}

shutdown_anvil(anvil);

Ok(())
}

Self::Deregister { rpc_url, operator_private_key } => {
Self::Deregister { rpc_url, operator_private_key, dry_run } => {
let signer = PrivateKeySigner::from_bytes(&operator_private_key)
.wrap_err("valid private key")?;
let address = signer.address();

let (rpc, anvil) = handle_rpc_dry_run(rpc_url, dry_run)?;

let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(EthereumWallet::from(signer))
.on_http(rpc_url);
.on_http(rpc);

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

Expand Down Expand Up @@ -238,7 +257,7 @@ impl EigenLayerSubcommand {
eyre::bail!("Transaction failed: {:?}", receipt)
}

info!("Succesfully deregistered EigenLayer operator");
info!("Successfully deregistered EigenLayer operator");
}
Err(e) => parse_eigenlayer_middleware_mainnet_errors(e)?,
}
Expand All @@ -258,24 +277,28 @@ impl EigenLayerSubcommand {
eyre::bail!("Transaction failed: {:?}", receipt)
}

info!("Succesfully deregistered EigenLayer operator");
info!("Successfully deregistered EigenLayer operator");
}
Err(e) => parse_eigenlayer_middleware_holesky_errors(e)?,
}
}

shutdown_anvil(anvil);

Ok(())
}

Self::UpdateRpc { rpc_url, operator_private_key, operator_rpc } => {
Self::UpdateRpc { rpc_url, operator_private_key, operator_rpc, dry_run } => {
let signer = PrivateKeySigner::from_bytes(&operator_private_key)
.wrap_err("valid private key")?;
let address = signer.address();

let (rpc, anvil) = handle_rpc_dry_run(rpc_url, dry_run)?;

let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(EthereumWallet::from(signer))
.on_http(rpc_url);
.on_http(rpc);

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

Expand Down Expand Up @@ -308,7 +331,7 @@ impl EigenLayerSubcommand {
eyre::bail!("Transaction failed: {:?}", receipt)
}

info!("Succesfully updated EigenLayer operator RPC");
info!("Successfully updated EigenLayer operator RPC");
}
Err(e) => parse_eigenlayer_middleware_mainnet_errors(e)?,
}
Expand All @@ -334,7 +357,7 @@ impl EigenLayerSubcommand {
eyre::bail!("Transaction failed: {:?}", receipt)
}

info!("Succesfully updated EigenLayer operator RPC");
info!("Successfully updated EigenLayer operator RPC");
}
Err(e) => match try_parse_contract_error::<BoltManagerErrors>(e)? {
BoltManagerErrors::OperatorNotRegistered(_) => {
Expand All @@ -350,6 +373,8 @@ impl EigenLayerSubcommand {
}
}

shutdown_anvil(anvil);

Ok(())
}

Expand Down Expand Up @@ -380,7 +405,7 @@ impl EigenLayerSubcommand {
info!(?address, "EigenLayer operator is registered");
} else {
warn!(?address, "Operator not registered");
return Ok(())
return Ok(());
}
}
Err(e) => {
Expand Down Expand Up @@ -428,7 +453,7 @@ impl EigenLayerSubcommand {
info!(?address, "EigenLayer operator is registered");
} else {
warn!(?address, "Operator not registered");
return Ok(())
return Ok(());
}

let middleware = BoltEigenLayerMiddlewareHolesky::new(
Expand Down Expand Up @@ -653,6 +678,7 @@ mod tests {
operator_private_key: secret_key,
strategy: weth_strategy_address,
amount: U256::from(1),
dry_run: false,
},
},
};
Expand All @@ -669,6 +695,7 @@ mod tests {
extra_data: "hello world computer 🌐".to_string(),
operator_rpc: None,
salt: None,
dry_run: false,
},
},
};
Expand All @@ -693,6 +720,7 @@ mod tests {
rpc_url: anvil_url.clone(),
operator_private_key: secret_key,
operator_rpc: "https://boooooolt.chainbound.io/rpc".parse().expect("valid url"),
dry_run: false,
},
},
};
Expand All @@ -715,6 +743,7 @@ mod tests {
subcommand: EigenLayerSubcommand::Deregister {
rpc_url: anvil_url.clone(),
operator_private_key: secret_key,
dry_run: false,
},
},
};
Expand Down
Loading