Skip to content
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
23 changes: 21 additions & 2 deletions src/cli/existing_mnemonic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,22 @@ pub struct ExistingMnemonicSubcommandOpts {
/// Deposit amount in ETH.
/// For standard validators: exactly 32 ETH.
/// For EIP-7251 compounding validators (0x02 withdrawal credentials): 32 to 2048 ETH.
#[arg(long, visible_alias = "deposit_amount", default_value = "32")]
/// Cannot be used together with --deposit-amount-gwei flag.
#[arg(
long,
visible_alias = "deposit_amount",
default_value = "32",
conflicts_with = "deposit_amount_gwei"
)]
pub deposit_amount_eth: u64,

/// Deposit amount in Gwei.
/// For standard validators: exactly 32000000000 Gwei (32 ETH).
/// For EIP-7251 compounding validators (0x02 withdrawal credentials): 32000000000 to 2048000000000 Gwei.
/// Cannot be used together with --deposit-amount-eth flag.
#[arg(long, conflicts_with = "deposit_amount_eth")]
pub deposit_amount_gwei: Option<u64>,

/// Use EIP-7251 compounding withdrawal credentials (0x02).
///
/// When enabled, validators will use 0x02 withdrawal credentials which support
Expand All @@ -102,6 +115,12 @@ impl ExistingMnemonicSubcommandOpts {
.clone()
.map(|p| p.as_bytes().to_owned());

let deposit_amount_gwei = if let Some(gwei) = self.deposit_amount_gwei {
gwei
} else {
self.deposit_amount_eth * 1_000_000_000 // Convert ETH to Gwei
};

let validators = Validators::new(
Some(self.mnemonic.as_bytes()),
password,
Expand All @@ -114,7 +133,7 @@ impl ExistingMnemonicSubcommandOpts {
.export(
chain,
self.withdrawal_credentials.clone(),
self.deposit_amount_eth * 1_000_000_000, // Convert ETH to Gwei
deposit_amount_gwei,
self.compounding,
self.deposit_cli_version.clone(),
self.testnet_config.clone(),
Expand Down
23 changes: 21 additions & 2 deletions src/cli/new_mnemonic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,22 @@ pub struct NewMnemonicSubcommandOpts {
/// Deposit amount in ETH.
/// For standard validators: exactly 32 ETH.
/// For EIP-7251 compounding validators (0x02 withdrawal credentials): 32 to 2048 ETH.
#[arg(long, visible_alias = "deposit_amount", default_value = "32")]
/// Cannot be used together with --deposit-amount-gwei flag.
#[arg(
long,
visible_alias = "deposit_amount",
default_value = "32",
conflicts_with = "deposit_amount_gwei"
)]
pub deposit_amount_eth: u64,

/// Deposit amount in Gwei.
/// For standard validators: exactly 32000000000 Gwei (32 ETH).
/// For EIP-7251 compounding validators (0x02 withdrawal credentials): 32000000000 to 2048000000000 Gwei.
/// Cannot be used together with --deposit-amount-eth flag.
#[arg(long, conflicts_with = "deposit_amount_eth")]
pub deposit_amount_gwei: Option<u64>,

/// Use EIP-7251 compounding withdrawal credentials (0x02).
///
/// When enabled, validators will use 0x02 withdrawal credentials which support
Expand All @@ -91,6 +104,12 @@ impl NewMnemonicSubcommandOpts {
.clone()
.map(|p| p.as_bytes().to_owned());

let deposit_amount_gwei = if let Some(gwei) = self.deposit_amount_gwei {
gwei
} else {
self.deposit_amount_eth * 1_000_000_000 // Convert ETH to Gwei
};

let validators = Validators::new(
None,
password,
Expand All @@ -103,7 +122,7 @@ impl NewMnemonicSubcommandOpts {
.export(
chain,
self.withdrawal_credentials.clone(),
self.deposit_amount_eth * 1_000_000_000, // Convert ETH to Gwei
deposit_amount_gwei,
self.compounding,
self.deposit_cli_version.clone(),
self.testnet_config.clone(),
Expand Down
76 changes: 76 additions & 0 deletions tests/e2e/new_mnemonic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,3 +630,79 @@ fn parse_kdf_function(keystore: &Keystore) -> String {
.unwrap();
kdf_function
}

/*
generate validator with deposit amount specified in gwei
*/
#[test]
fn test_deposit_amount_gwei() -> Result<(), Box<dyn std::error::Error>> {
let chain = SupportedNetworks::Sepolia;
let decryption_password = "testtest";
let num_validators = "1";
let deposit_amount_gwei = "32000000000"; // 32 ETH in gwei

let mut cmd = Command::cargo_bin("eth-staking-smith")?;

cmd.arg("new-mnemonic");
cmd.arg("--chain");
cmd.arg(chain.to_string());
cmd.arg("--keystore_password");
cmd.arg(decryption_password);
cmd.arg("--num_validators");
cmd.arg(num_validators);
cmd.arg("--deposit-amount-gwei");
cmd.arg(deposit_amount_gwei);

cmd.assert().success();

let output = &cmd
.output()
.expect("could not get output from command")
.stdout;
let command_output = std::str::from_utf8(output).expect("could not parse output into string");
let generated_validator_json: ValidatorExports =
serde_json::from_str(command_output).expect("could not unmarshal command output");
let generated_deposit_data = generated_validator_json
.deposit_data
.get(0)
.expect("could not get generated deposit data")
.to_owned();

// verify the deposit amount is correct
assert_eq!(generated_deposit_data.amount, 32000000000);

generated_deposit_data
.validate(eth_staking_smith::chain_spec::chain_spec_for_network(&chain).unwrap());

Ok(())
}

/*
test that deposit-amount-eth and deposit-amount-gwei flags conflict
*/
#[test]
fn test_conflicting_deposit_flags() -> Result<(), Box<dyn std::error::Error>> {
let chain = "sepolia";
let decryption_password = "testtest";
let num_validators = "1";

let mut cmd = Command::cargo_bin("eth-staking-smith")?;

cmd.arg("new-mnemonic");
cmd.arg("--chain");
cmd.arg(chain);
cmd.arg("--keystore_password");
cmd.arg(decryption_password);
cmd.arg("--num_validators");
cmd.arg(num_validators);
cmd.arg("--deposit-amount-eth");
cmd.arg("32");
cmd.arg("--deposit-amount-gwei");
cmd.arg("32000000000");

cmd.assert()
.failure()
.stderr(predicate::str::contains("cannot be used with"));

Ok(())
}
Loading