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

Commit 5159608

Browse files
authored
stake-pool: Update pool token supply on update, in case of burns (#2108)
1 parent aef1e23 commit 5159608

File tree

3 files changed

+111
-6
lines changed

3 files changed

+111
-6
lines changed

stake-pool/program/src/processor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,10 @@ impl Processor {
16211621
}
16221622
stake_pool.total_stake_lamports = total_stake_lamports;
16231623
stake_pool.last_update_epoch = clock.epoch;
1624+
1625+
let pool_mint = Mint::unpack_from_slice(&pool_mint_info.data.borrow())?;
1626+
stake_pool.pool_token_supply = pool_mint.supply;
1627+
16241628
stake_pool.serialize(&mut *stake_pool_info.data.borrow_mut())?;
16251629

16261630
Ok(())

stake-pool/program/tests/helpers/mod.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,33 @@ pub async fn mint_tokens(
161161
Ok(())
162162
}
163163

164+
pub async fn burn_tokens(
165+
banks_client: &mut BanksClient,
166+
payer: &Keypair,
167+
recent_blockhash: &Hash,
168+
mint: &Pubkey,
169+
account: &Pubkey,
170+
authority: &Keypair,
171+
amount: u64,
172+
) -> Result<(), TransportError> {
173+
let transaction = Transaction::new_signed_with_payer(
174+
&[spl_token::instruction::burn(
175+
&spl_token::id(),
176+
account,
177+
mint,
178+
&authority.pubkey(),
179+
&[],
180+
amount,
181+
)
182+
.unwrap()],
183+
Some(&payer.pubkey()),
184+
&[payer, authority],
185+
*recent_blockhash,
186+
);
187+
banks_client.process_transaction(transaction).await?;
188+
Ok(())
189+
}
190+
164191
pub async fn get_token_balance(banks_client: &mut BanksClient, token: &Pubkey) -> u64 {
165192
let token_account = banks_client.get_account(*token).await.unwrap().unwrap();
166193
let account_info: spl_token::state::Account =
@@ -1019,7 +1046,7 @@ impl DepositStakeAccount {
10191046
}
10201047

10211048
pub async fn deposit(
1022-
&self,
1049+
&mut self,
10231050
banks_client: &mut BanksClient,
10241051
payer: &Keypair,
10251052
recent_blockhash: &Hash,
@@ -1048,6 +1075,7 @@ impl DepositStakeAccount {
10481075
&self.authority,
10491076
)
10501077
.await;
1078+
self.pool_tokens = get_token_balance(banks_client, &self.pool_account.pubkey()).await;
10511079
assert!(error.is_none());
10521080
}
10531081
}

stake-pool/program/tests/update_validator_list_balance.rs

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ mod helpers;
44

55
use {
66
helpers::*,
7-
solana_program::{borsh::try_from_slice_unchecked, pubkey::Pubkey},
7+
solana_program::{borsh::try_from_slice_unchecked, program_pack::Pack, pubkey::Pubkey},
88
solana_program_test::*,
99
solana_sdk::signature::Signer,
1010
spl_stake_pool::{
1111
stake_program,
1212
state::{StakePool, StakeStatus, ValidatorList},
1313
MAX_VALIDATORS_TO_UPDATE, MINIMUM_ACTIVE_STAKE,
1414
},
15+
spl_token::state::Mint,
1516
};
1617

1718
async fn setup(
@@ -20,6 +21,7 @@ async fn setup(
2021
ProgramTestContext,
2122
StakePoolAccounts,
2223
Vec<ValidatorStakeAccount>,
24+
Vec<DepositStakeAccount>,
2325
u64,
2426
u64,
2527
u64,
@@ -99,7 +101,7 @@ async fn setup(
99101
assert!(error.is_none());
100102
}
101103

102-
for deposit_account in &deposit_accounts {
104+
for deposit_account in &mut deposit_accounts {
103105
deposit_account
104106
.deposit(
105107
&mut context.banks_client,
@@ -131,6 +133,7 @@ async fn setup(
131133
context,
132134
stake_pool_accounts,
133135
stake_accounts,
136+
deposit_accounts,
134137
TEST_STAKE_AMOUNT,
135138
reserve_stake_amount,
136139
slot,
@@ -144,6 +147,7 @@ async fn success() {
144147
mut context,
145148
stake_pool_accounts,
146149
stake_accounts,
150+
_,
147151
validator_lamports,
148152
reserve_lamports,
149153
mut slot,
@@ -207,7 +211,7 @@ async fn success() {
207211

208212
#[tokio::test]
209213
async fn merge_into_reserve() {
210-
let (mut context, stake_pool_accounts, stake_accounts, lamports, _, mut slot) =
214+
let (mut context, stake_pool_accounts, stake_accounts, _, lamports, _, mut slot) =
211215
setup(MAX_VALIDATORS_TO_UPDATE).await;
212216

213217
let pre_lamports = get_validator_list_sum(
@@ -317,7 +321,7 @@ async fn merge_into_reserve() {
317321

318322
#[tokio::test]
319323
async fn merge_into_validator_stake() {
320-
let (mut context, stake_pool_accounts, stake_accounts, lamports, reserve_lamports, mut slot) =
324+
let (mut context, stake_pool_accounts, stake_accounts, _, lamports, reserve_lamports, mut slot) =
321325
setup(MAX_VALIDATORS_TO_UPDATE).await;
322326

323327
let rent = context.banks_client.get_rent().await.unwrap();
@@ -448,7 +452,7 @@ async fn merge_into_validator_stake() {
448452

449453
#[tokio::test]
450454
async fn merge_transient_stake_after_remove() {
451-
let (mut context, stake_pool_accounts, stake_accounts, lamports, reserve_lamports, mut slot) =
455+
let (mut context, stake_pool_accounts, stake_accounts, _, lamports, reserve_lamports, mut slot) =
452456
setup(1).await;
453457

454458
let rent = context.banks_client.get_rent().await.unwrap();
@@ -590,6 +594,75 @@ async fn merge_transient_stake_after_remove() {
590594
assert_eq!(validator_list.validators.len(), 0);
591595
}
592596

597+
#[tokio::test]
598+
async fn success_with_burned_tokens() {
599+
let num_validators = 5;
600+
let (mut context, stake_pool_accounts, stake_accounts, deposit_accounts, _, _, mut slot) =
601+
setup(num_validators).await;
602+
603+
let mint_info = get_account(
604+
&mut context.banks_client,
605+
&stake_pool_accounts.pool_mint.pubkey(),
606+
)
607+
.await;
608+
let mint = Mint::unpack(&mint_info.data).unwrap();
609+
610+
let stake_pool_info = get_account(
611+
&mut context.banks_client,
612+
&stake_pool_accounts.stake_pool.pubkey(),
613+
)
614+
.await;
615+
let stake_pool = try_from_slice_unchecked::<StakePool>(&stake_pool_info.data).unwrap();
616+
assert_eq!(mint.supply, stake_pool.pool_token_supply);
617+
618+
burn_tokens(
619+
&mut context.banks_client,
620+
&context.payer,
621+
&context.last_blockhash,
622+
&stake_pool_accounts.pool_mint.pubkey(),
623+
&deposit_accounts[0].pool_account.pubkey(),
624+
&deposit_accounts[0].authority,
625+
deposit_accounts[0].pool_tokens,
626+
)
627+
.await
628+
.unwrap();
629+
630+
let mint_info = get_account(
631+
&mut context.banks_client,
632+
&stake_pool_accounts.pool_mint.pubkey(),
633+
)
634+
.await;
635+
let mint = Mint::unpack(&mint_info.data).unwrap();
636+
assert_ne!(mint.supply, stake_pool.pool_token_supply);
637+
638+
let slots_per_epoch = context.genesis_config().epoch_schedule.slots_per_epoch;
639+
slot += slots_per_epoch;
640+
context.warp_to_slot(slot).unwrap();
641+
642+
stake_pool_accounts
643+
.update_all(
644+
&mut context.banks_client,
645+
&context.payer,
646+
&context.last_blockhash,
647+
stake_accounts
648+
.iter()
649+
.map(|v| v.vote.pubkey())
650+
.collect::<Vec<Pubkey>>()
651+
.as_slice(),
652+
false,
653+
)
654+
.await;
655+
656+
let stake_pool_info = get_account(
657+
&mut context.banks_client,
658+
&stake_pool_accounts.stake_pool.pubkey(),
659+
)
660+
.await;
661+
let stake_pool = try_from_slice_unchecked::<StakePool>(&stake_pool_info.data).unwrap();
662+
663+
assert_eq!(mint.supply, stake_pool.pool_token_supply);
664+
}
665+
593666
#[tokio::test]
594667
async fn fail_with_uninitialized_validator_list() {} // TODO
595668

0 commit comments

Comments
 (0)