Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit ee52f1d

Browse files
committed
Reimplement spl-stake-pool list command to use the StakePool/ValidatorList as the primary source of information
1 parent 092432f commit ee52f1d

File tree

8 files changed

+177
-128
lines changed

8 files changed

+177
-128
lines changed

stake-pool/cli/src/client.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ use {
1818

1919
type Error = Box<dyn std::error::Error>;
2020

21-
pub(crate) fn get_stake_pool(
21+
pub fn get_stake_pool(
2222
rpc_client: &RpcClient,
23-
pool_address: &Pubkey,
23+
stake_pool_address: &Pubkey,
2424
) -> Result<StakePool, Error> {
25-
let account_data = rpc_client.get_account_data(pool_address)?;
25+
let account_data = rpc_client.get_account_data(stake_pool_address)?;
2626
let stake_pool = StakePool::try_from_slice(account_data.as_slice())
27-
.map_err(|err| format!("Invalid stake pool {}: {}", pool_address, err))?;
27+
.map_err(|err| format!("Invalid stake pool {}: {}", stake_pool_address, err))?;
2828
Ok(stake_pool)
2929
}
3030

31-
pub(crate) fn get_validator_list(
31+
pub fn get_validator_list(
3232
rpc_client: &RpcClient,
3333
validator_list_address: &Pubkey,
3434
) -> Result<ValidatorList, Error> {
@@ -38,7 +38,7 @@ pub(crate) fn get_validator_list(
3838
Ok(validator_list)
3939
}
4040

41-
pub(crate) fn get_token_account(
41+
pub fn get_token_account(
4242
rpc_client: &RpcClient,
4343
token_account_address: &Pubkey,
4444
expected_token_mint: &Pubkey,
@@ -58,7 +58,7 @@ pub(crate) fn get_token_account(
5858
}
5959
}
6060

61-
pub(crate) fn get_token_mint(
61+
pub fn get_token_mint(
6262
rpc_client: &RpcClient,
6363
token_mint_address: &Pubkey,
6464
) -> Result<spl_token::state::Mint, Error> {

stake-pool/cli/src/main.rs

Lines changed: 77 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ fn command_vsa_remove(
372372
// Calculate amount of tokens to withdraw
373373
let stake_account = config.rpc_client.get_account(&stake)?;
374374
let tokens_to_withdraw = stake_pool
375-
.calc_pool_withdraw_amount(stake_account.lamports)
375+
.calc_pool_tokens_for_withdraw(stake_account.lamports)
376376
.unwrap();
377377

378378
// Check balance and mint
@@ -583,47 +583,84 @@ fn command_deposit(
583583

584584
fn command_list(config: &Config, stake_pool_address: &Pubkey) -> CommandResult {
585585
let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
586+
let validator_list = get_validator_list(&config.rpc_client, &stake_pool.validator_list)?;
587+
let pool_mint = get_token_mint(&config.rpc_client, &stake_pool.pool_mint)?;
588+
let epoch_info = config.rpc_client.get_epoch_info()?;
589+
590+
for validator in validator_list.validators {
591+
println!(
592+
"Validator Vote Account: {}\tBalance: {}\tLast Update Epoch: {}{}",
593+
validator.vote_account,
594+
Sol(validator.stake_lamports),
595+
validator.last_update_epoch,
596+
if validator.last_update_epoch != epoch_info.epoch {
597+
" [UPDATE REQUIRED]"
598+
} else {
599+
""
600+
}
601+
);
602+
}
603+
604+
println!(
605+
"Total Pool Stake: {}{}",
606+
Sol(stake_pool.total_stake_lamports),
607+
if stake_pool.last_update_epoch != epoch_info.epoch {
608+
" [UPDATE REQUIRED]"
609+
} else {
610+
""
611+
}
612+
);
613+
println!(
614+
"Total Pool Tokens: {}",
615+
spl_token::amount_to_ui_amount(stake_pool.pool_token_supply, pool_mint.decimals)
616+
);
586617

587618
if config.verbose {
588-
println!("Current validator list");
589-
let validator_list = get_validator_list(&config.rpc_client, &stake_pool.validator_list)?;
590-
for validator in validator_list.validators {
619+
println!();
620+
621+
let pool_withdraw_authority =
622+
find_withdraw_authority_program_address(&spl_stake_pool::id(), stake_pool_address).0;
623+
624+
let accounts =
625+
get_stake_accounts_by_withdraw_authority(&config.rpc_client, &pool_withdraw_authority)?;
626+
if accounts.is_empty() {
627+
return Err(format!("No stake accounts found for {}", pool_withdraw_authority).into());
628+
}
629+
630+
let mut total_stake_lamports: u64 = 0;
631+
for (pubkey, stake_lamports, stake_state) in accounts {
632+
total_stake_lamports += stake_lamports;
591633
println!(
592-
"Vote Account: {}\tBalance: {}\tEpoch: {}",
593-
validator.vote_account, validator.balance, validator.last_update_epoch
634+
"Stake Account: {}\tVote Account: {}\t{}",
635+
pubkey,
636+
stake_state.delegation().expect("delegation").voter_pubkey,
637+
Sol(stake_lamports)
594638
);
595639
}
596-
}
597-
598-
let pool_withdraw_authority =
599-
find_withdraw_authority_program_address(&spl_stake_pool::id(), stake_pool_address).0;
600-
601-
let accounts =
602-
get_stake_accounts_by_withdraw_authority(&config.rpc_client, &pool_withdraw_authority)?;
603-
if accounts.is_empty() {
604-
return Err("No accounts found.".to_string().into());
605-
}
640+
println!("Total Stake Account Balance: {}", Sol(total_stake_lamports));
606641

607-
let mut total_lamports: u64 = 0;
608-
for (pubkey, lamports, stake_state) in accounts {
609-
total_lamports += lamports;
610-
println!(
611-
"Stake Account: {}\tVote Account: {}\t{}",
612-
pubkey,
613-
stake_state.delegation().expect("delegation").voter_pubkey,
614-
Sol(lamports)
615-
);
642+
if pool_mint.supply != stake_pool.pool_token_supply {
643+
println!(
644+
"BUG! Pool Tokens supply mismatch. Pool mint reports {}",
645+
spl_token::amount_to_ui_amount(pool_mint.supply, pool_mint.decimals)
646+
);
647+
}
616648
}
617-
println!("Total Stake: {}", Sol(total_lamports));
618649

619650
Ok(())
620651
}
621652

622653
fn command_update(config: &Config, stake_pool_address: &Pubkey) -> CommandResult {
623654
let stake_pool = get_stake_pool(&config.rpc_client, stake_pool_address)?;
624-
let validator_list = get_validator_list(&config.rpc_client, &stake_pool.validator_list)?;
625655
let epoch_info = config.rpc_client.get_epoch_info()?;
626656

657+
if stake_pool.last_update_epoch == epoch_info.epoch {
658+
println!("Update not required");
659+
return Ok(());
660+
}
661+
662+
let validator_list = get_validator_list(&config.rpc_client, &stake_pool.validator_list)?;
663+
627664
let accounts_to_update: Vec<Pubkey> = validator_list
628665
.validators
629666
.iter()
@@ -651,26 +688,21 @@ fn command_update(config: &Config, stake_pool_address: &Pubkey) -> CommandResult
651688
)?);
652689
}
653690

654-
if instructions.is_empty() && stake_pool.last_update_epoch == epoch_info.epoch {
655-
println!("Stake pool balances are up to date, no update required.");
656-
Ok(())
657-
} else {
658-
println!("Updating stake pool...");
659-
instructions.push(spl_stake_pool::instruction::update_stake_pool_balance(
660-
&spl_stake_pool::id(),
661-
stake_pool_address,
662-
&stake_pool.validator_list,
663-
)?);
691+
println!("Updating stake pool...");
692+
instructions.push(spl_stake_pool::instruction::update_stake_pool_balance(
693+
&spl_stake_pool::id(),
694+
stake_pool_address,
695+
&stake_pool.validator_list,
696+
)?);
664697

665-
let mut transaction =
666-
Transaction::new_with_payer(&instructions, Some(&config.fee_payer.pubkey()));
698+
let mut transaction =
699+
Transaction::new_with_payer(&instructions, Some(&config.fee_payer.pubkey()));
667700

668-
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
669-
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
670-
transaction.sign(&[config.fee_payer.as_ref()], recent_blockhash);
671-
send_transaction(&config, transaction)?;
672-
Ok(())
673-
}
701+
let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?;
702+
check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?;
703+
transaction.sign(&[config.fee_payer.as_ref()], recent_blockhash);
704+
send_transaction(&config, transaction)?;
705+
Ok(())
674706
}
675707

676708
#[derive(PartialEq, Debug)]

stake-pool/program/src/processor.rs

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -513,8 +513,8 @@ impl Processor {
513513

514514
// Calculate and mint tokens
515515
let stake_lamports = **stake_account_info.lamports.borrow();
516-
let token_amount = stake_pool
517-
.calc_pool_deposit_amount(stake_lamports)
516+
let pool_tokens = stake_pool
517+
.calc_pool_tokens_for_deposit(stake_lamports)
518518
.ok_or(StakePoolError::CalculationFailure)?;
519519
Self::token_mint_to(
520520
stake_pool_info.key,
@@ -524,21 +524,21 @@ impl Processor {
524524
withdraw_info.clone(),
525525
AUTHORITY_WITHDRAW,
526526
stake_pool.withdraw_bump_seed,
527-
token_amount,
527+
pool_tokens,
528528
)?;
529529

530530
// Check if stake is warmed up
531531
Self::check_stake_activation(stake_account_info, clock, stake_history)?;
532532

533533
validator_list.validators.push(ValidatorStakeInfo {
534534
vote_account,
535-
balance: stake_lamports,
535+
stake_lamports,
536536
last_update_epoch: clock.epoch,
537537
});
538538
validator_list.serialize(&mut *validator_list_info.data.borrow_mut())?;
539539

540-
stake_pool.pool_total += token_amount;
541-
stake_pool.stake_total += stake_lamports;
540+
stake_pool.pool_token_supply += pool_tokens;
541+
stake_pool.total_stake_lamports += stake_lamports;
542542
stake_pool.serialize(&mut *stake_pool_info.data.borrow_mut())?;
543543

544544
Ok(())
@@ -622,8 +622,8 @@ impl Processor {
622622

623623
// Calculate and burn tokens
624624
let stake_lamports = **stake_account_info.lamports.borrow();
625-
let token_amount = stake_pool
626-
.calc_pool_withdraw_amount(stake_lamports)
625+
let pool_tokens = stake_pool
626+
.calc_pool_tokens_for_withdraw(stake_lamports)
627627
.ok_or(StakePoolError::CalculationFailure)?;
628628
Self::token_burn(
629629
stake_pool_info.key,
@@ -633,16 +633,16 @@ impl Processor {
633633
withdraw_info.clone(),
634634
AUTHORITY_WITHDRAW,
635635
stake_pool.withdraw_bump_seed,
636-
token_amount,
636+
pool_tokens,
637637
)?;
638638

639639
validator_list
640640
.validators
641641
.retain(|item| item.vote_account != vote_account);
642642
validator_list.serialize(&mut *validator_list_info.data.borrow_mut())?;
643643

644-
stake_pool.pool_total -= token_amount;
645-
stake_pool.stake_total -= stake_lamports;
644+
stake_pool.pool_token_supply -= pool_tokens;
645+
stake_pool.total_stake_lamports -= stake_lamports;
646646
stake_pool.serialize(&mut *stake_pool_info.data.borrow_mut())?;
647647

648648
Ok(())
@@ -685,7 +685,7 @@ impl Processor {
685685
continue;
686686
}
687687
validator_stake_record.last_update_epoch = clock.epoch;
688-
validator_stake_record.balance = **validator_stake_account.lamports.borrow();
688+
validator_stake_record.stake_lamports = **validator_stake_account.lamports.borrow();
689689
changes = true;
690690
}
691691
}
@@ -723,15 +723,15 @@ impl Processor {
723723
return Err(StakePoolError::InvalidState.into());
724724
}
725725

726-
let mut total_balance: u64 = 0;
726+
let mut total_stake_lamports: u64 = 0;
727727
for validator_stake_record in validator_list.validators {
728728
if validator_stake_record.last_update_epoch < clock.epoch {
729729
return Err(StakePoolError::StakeListOutOfDate.into());
730730
}
731-
total_balance += validator_stake_record.balance;
731+
total_stake_lamports += validator_stake_record.stake_lamports;
732732
}
733733

734-
stake_pool.stake_total = total_balance;
734+
stake_pool.total_stake_lamports = total_stake_lamports;
735735
stake_pool.last_update_epoch = clock.epoch;
736736
stake_pool.serialize(&mut *stake_pool_info.data.borrow_mut())?;
737737

@@ -830,16 +830,16 @@ impl Processor {
830830
.ok_or(StakePoolError::ValidatorNotFound)?;
831831

832832
let stake_lamports = **stake_info.lamports.borrow();
833-
let pool_amount = stake_pool
834-
.calc_pool_deposit_amount(stake_lamports)
833+
let new_pool_tokens = stake_pool
834+
.calc_pool_tokens_for_deposit(stake_lamports)
835835
.ok_or(StakePoolError::CalculationFailure)?;
836836

837-
let fee_amount = stake_pool
838-
.calc_fee_amount(pool_amount)
837+
let fee_pool_tokens = stake_pool
838+
.calc_fee_amount(new_pool_tokens)
839839
.ok_or(StakePoolError::CalculationFailure)?;
840840

841-
let user_amount = pool_amount
842-
.checked_sub(fee_amount)
841+
let user_pool_tokens = new_pool_tokens
842+
.checked_sub(fee_pool_tokens)
843843
.ok_or(StakePoolError::CalculationFailure)?;
844844

845845
Self::stake_authorize(
@@ -886,7 +886,7 @@ impl Processor {
886886
withdraw_info.clone(),
887887
AUTHORITY_WITHDRAW,
888888
stake_pool.withdraw_bump_seed,
889-
user_amount,
889+
user_pool_tokens,
890890
)?;
891891

892892
Self::token_mint_to(
@@ -897,13 +897,13 @@ impl Processor {
897897
withdraw_info.clone(),
898898
AUTHORITY_WITHDRAW,
899899
stake_pool.withdraw_bump_seed,
900-
fee_amount,
900+
fee_pool_tokens,
901901
)?;
902-
stake_pool.pool_total += pool_amount;
903-
stake_pool.stake_total += stake_lamports;
902+
stake_pool.pool_token_supply += new_pool_tokens;
903+
stake_pool.total_stake_lamports += stake_lamports;
904904
stake_pool.serialize(&mut *stake_pool_info.data.borrow_mut())?;
905905

906-
validator_list_item.balance = **validator_stake_account_info.lamports.borrow();
906+
validator_list_item.stake_lamports = **validator_stake_account_info.lamports.borrow();
907907
validator_list.serialize(&mut *validator_list_info.data.borrow_mut())?;
908908

909909
Ok(())
@@ -912,7 +912,7 @@ impl Processor {
912912
/// Processes [Withdraw](enum.Instruction.html).
913913
fn process_withdraw(
914914
program_id: &Pubkey,
915-
pool_amount: u64,
915+
pool_tokens: u64,
916916
accounts: &[AccountInfo],
917917
) -> ProgramResult {
918918
let account_info_iter = &mut accounts.iter();
@@ -965,8 +965,8 @@ impl Processor {
965965
.find_mut(&vote_account)
966966
.ok_or(StakePoolError::ValidatorNotFound)?;
967967

968-
let stake_amount = stake_pool
969-
.calc_lamports_withdraw_amount(pool_amount)
968+
let stake_lamports = stake_pool
969+
.calc_lamports_withdraw_amount(pool_tokens)
970970
.ok_or(StakePoolError::CalculationFailure)?;
971971

972972
Self::stake_split(
@@ -975,7 +975,7 @@ impl Processor {
975975
withdraw_info.clone(),
976976
AUTHORITY_WITHDRAW,
977977
stake_pool.withdraw_bump_seed,
978-
stake_amount,
978+
stake_lamports,
979979
stake_split_to.clone(),
980980
)?;
981981

@@ -1011,14 +1011,14 @@ impl Processor {
10111011
withdraw_info.clone(),
10121012
AUTHORITY_WITHDRAW,
10131013
stake_pool.withdraw_bump_seed,
1014-
pool_amount,
1014+
pool_tokens,
10151015
)?;
10161016

1017-
stake_pool.pool_total -= pool_amount;
1018-
stake_pool.stake_total -= stake_amount;
1017+
stake_pool.pool_token_supply -= pool_tokens;
1018+
stake_pool.total_stake_lamports -= stake_lamports;
10191019
stake_pool.serialize(&mut *stake_pool_info.data.borrow_mut())?;
10201020

1021-
validator_list_item.balance = **stake_split_from.lamports.borrow();
1021+
validator_list_item.stake_lamports = **stake_split_from.lamports.borrow();
10221022
validator_list.serialize(&mut *validator_list_info.data.borrow_mut())?;
10231023

10241024
Ok(())

0 commit comments

Comments
 (0)