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

Commit 7f89183

Browse files
authored
stake-pool: Ensure zero pool token supply on init (#1572)
1 parent 17dd53d commit 7f89183

File tree

5 files changed

+122
-26
lines changed

5 files changed

+122
-26
lines changed

stake-pool/program/src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ pub enum StakePoolError {
8282
/// Wrong pool staker account.
8383
#[error("WrongStaker")]
8484
WrongStaker,
85+
/// Pool token supply is not zero on initialization
86+
#[error("NonZeroPoolTokenSupply")]
87+
NonZeroPoolTokenSupply,
8588
}
8689
impl From<StakePoolError> for ProgramError {
8790
fn from(e: StakePoolError) -> Self {

stake-pool/program/src/instruction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub enum StakePoolInstruction {
3333
/// 1. `[s]` Manager
3434
/// 2. `[]` Staker
3535
/// 3. `[w]` Uninitialized validator stake list storage account
36-
/// 4. `[]` Pool token mint. Must be non zero, owned by withdraw authority.
36+
/// 4. `[]` Pool token mint. Must have zero supply, owned by withdraw authority.
3737
/// 5. `[]` Pool account to deposit the generated fee for manager.
3838
/// 6. `[]` Clock sysvar
3939
/// 7. `[]` Rent sysvar

stake-pool/program/src/processor.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ impl Processor {
281281
}
282282

283283
if manager_fee_info.owner != token_program_info.key {
284-
return Err(StakePoolError::InvalidFeeAccount.into());
284+
return Err(ProgramError::IncorrectProgramId);
285285
}
286286

287287
if pool_mint_info.owner != token_program_info.key {
@@ -301,6 +301,10 @@ impl Processor {
301301

302302
let pool_mint = Mint::unpack_from_slice(&pool_mint_info.data.borrow())?;
303303

304+
if pool_mint.supply != 0 {
305+
return Err(StakePoolError::NonZeroPoolTokenSupply.into());
306+
}
307+
304308
if !pool_mint.mint_authority.contains(&withdraw_authority_key) {
305309
return Err(StakePoolError::WrongMintingAuthority.into());
306310
}
@@ -1155,6 +1159,7 @@ impl PrintProgramError for StakePoolError {
11551159
StakePoolError::WrongMintingAuthority => msg!("Error: Wrong minting authority set for mint pool account"),
11561160
StakePoolError::UnexpectedValidatorListAccountSize=> msg!("Error: The size of the given validator stake list does match the expected amount"),
11571161
StakePoolError::WrongStaker=> msg!("Error: Wrong pool staker account"),
1162+
StakePoolError::NonZeroPoolTokenSupply => msg!("Error: Pool token supply is not zero on initialization"),
11581163
}
11591164
}
11601165
}

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,33 @@ pub async fn create_token_account(
126126
Ok(())
127127
}
128128

129+
pub async fn mint_tokens(
130+
banks_client: &mut BanksClient,
131+
payer: &Keypair,
132+
recent_blockhash: &Hash,
133+
mint: &Pubkey,
134+
account: &Pubkey,
135+
mint_authority: &Keypair,
136+
amount: u64,
137+
) -> Result<(), TransportError> {
138+
let transaction = Transaction::new_signed_with_payer(
139+
&[spl_token::instruction::mint_to(
140+
&spl_token::id(),
141+
mint,
142+
account,
143+
&mint_authority.pubkey(),
144+
&[],
145+
amount,
146+
)
147+
.unwrap()],
148+
Some(&payer.pubkey()),
149+
&[payer, mint_authority],
150+
*recent_blockhash,
151+
);
152+
banks_client.process_transaction(transaction).await?;
153+
Ok(())
154+
}
155+
129156
pub async fn get_token_balance(banks_client: &mut BanksClient, token: &Pubkey) -> u64 {
130157
let token_account = banks_client
131158
.get_account(token.clone())

stake-pool/program/tests/initialize.rs

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async fn create_mint_and_token_account(
5252
}
5353

5454
#[tokio::test]
55-
async fn test_stake_pool_initialize() {
55+
async fn success_initialize() {
5656
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
5757
let stake_pool_accounts = StakePoolAccounts::new();
5858
stake_pool_accounts
@@ -77,7 +77,7 @@ async fn test_stake_pool_initialize() {
7777
}
7878

7979
#[tokio::test]
80-
async fn test_initialize_already_initialized_stake_pool() {
80+
async fn fail_double_initialize() {
8181
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
8282
let stake_pool_accounts = StakePoolAccounts::new();
8383
stake_pool_accounts
@@ -108,7 +108,7 @@ async fn test_initialize_already_initialized_stake_pool() {
108108
}
109109

110110
#[tokio::test]
111-
async fn test_initialize_stake_pool_with_already_initialized_stake_list_storage() {
111+
async fn fail_initialize_with_already_initialized_validator_list() {
112112
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
113113
let stake_pool_accounts = StakePoolAccounts::new();
114114
stake_pool_accounts
@@ -139,7 +139,7 @@ async fn test_initialize_stake_pool_with_already_initialized_stake_list_storage(
139139
}
140140

141141
#[tokio::test]
142-
async fn test_initialize_stake_pool_with_high_fee() {
142+
async fn fail_initialize_with_high_fee() {
143143
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
144144
let mut stake_pool_accounts = StakePoolAccounts::new();
145145
stake_pool_accounts.fee = instruction::Fee {
@@ -165,7 +165,7 @@ async fn test_initialize_stake_pool_with_high_fee() {
165165
}
166166

167167
#[tokio::test]
168-
async fn test_initialize_stake_pool_with_wrong_max_validators() {
168+
async fn fail_initialize_with_wrong_max_validators() {
169169
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
170170
let stake_pool_accounts = StakePoolAccounts::new();
171171

@@ -245,7 +245,7 @@ async fn test_initialize_stake_pool_with_wrong_max_validators() {
245245
}
246246

247247
#[tokio::test]
248-
async fn test_initialize_stake_pool_with_wrong_mint_authority() {
248+
async fn fail_initialize_with_wrong_mint_authority() {
249249
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
250250
let stake_pool_accounts = StakePoolAccounts::new();
251251
let wrong_mint = Keypair::new();
@@ -299,7 +299,7 @@ async fn test_initialize_stake_pool_with_wrong_mint_authority() {
299299
}
300300

301301
#[tokio::test]
302-
async fn test_initialize_stake_pool_with_wrong_token_program_id() {
302+
async fn fail_initialize_with_wrong_token_program_id() {
303303
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
304304
let stake_pool_accounts = StakePoolAccounts::new();
305305

@@ -399,7 +399,7 @@ async fn test_initialize_stake_pool_with_wrong_token_program_id() {
399399
}
400400

401401
#[tokio::test]
402-
async fn test_initialize_stake_pool_with_wrong_fee_accounts_manager() {
402+
async fn fail_initialize_with_wrong_fee_account() {
403403
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
404404
let stake_pool_accounts = StakePoolAccounts::new();
405405

@@ -446,24 +446,17 @@ async fn test_initialize_stake_pool_with_wrong_fee_accounts_manager() {
446446
)
447447
.await
448448
.err()
449+
.unwrap()
449450
.unwrap();
450451

451-
match transaction_error {
452-
TransportError::TransactionError(TransactionError::InstructionError(
453-
_,
454-
InstructionError::Custom(error_index),
455-
)) => {
456-
let program_error = error::StakePoolError::InvalidFeeAccount as u32;
457-
assert_eq!(error_index, program_error);
458-
}
459-
_ => panic!(
460-
"Wrong error occurs while try to initialize stake pool with wrong fee account's manager"
461-
),
462-
}
452+
assert_eq!(
453+
transaction_error,
454+
TransactionError::InstructionError(2, InstructionError::IncorrectProgramId)
455+
);
463456
}
464457

465458
#[tokio::test]
466-
async fn test_initialize_stake_pool_with_wrong_withdraw_authority() {
459+
async fn fail_initialize_with_wrong_withdraw_authority() {
467460
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
468461
let mut stake_pool_accounts = StakePoolAccounts::new();
469462

@@ -490,7 +483,7 @@ async fn test_initialize_stake_pool_with_wrong_withdraw_authority() {
490483
}
491484

492485
#[tokio::test]
493-
async fn test_initialize_stake_pool_with_not_rent_exempt_pool() {
486+
async fn fail_initialize_with_not_rent_exempt_pool() {
494487
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
495488
let stake_pool_accounts = StakePoolAccounts::new();
496489

@@ -563,7 +556,7 @@ async fn test_initialize_stake_pool_with_not_rent_exempt_pool() {
563556
}
564557

565558
#[tokio::test]
566-
async fn test_initialize_stake_pool_with_not_rent_exempt_validator_list() {
559+
async fn fail_initialize_with_not_rent_exempt_validator_list() {
567560
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
568561
let stake_pool_accounts = StakePoolAccounts::new();
569562

@@ -638,7 +631,7 @@ async fn test_initialize_stake_pool_with_not_rent_exempt_validator_list() {
638631
}
639632

640633
#[tokio::test]
641-
async fn test_initialize_stake_pool_without_manager_signature() {
634+
async fn fail_initialize_without_manager_signature() {
642635
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
643636
let stake_pool_accounts = StakePoolAccounts::new();
644637

@@ -727,3 +720,71 @@ async fn test_initialize_stake_pool_without_manager_signature() {
727720
),
728721
}
729722
}
723+
724+
#[tokio::test]
725+
async fn fail_initialize_with_pre_minted_pool_tokens() {
726+
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
727+
let stake_pool_accounts = StakePoolAccounts::new();
728+
let mint_authority = Keypair::new();
729+
730+
create_mint(
731+
&mut banks_client,
732+
&payer,
733+
&recent_blockhash,
734+
&stake_pool_accounts.pool_mint,
735+
&mint_authority.pubkey(),
736+
)
737+
.await
738+
.unwrap();
739+
740+
create_token_account(
741+
&mut banks_client,
742+
&payer,
743+
&recent_blockhash,
744+
&stake_pool_accounts.pool_fee_account,
745+
&stake_pool_accounts.pool_mint.pubkey(),
746+
&stake_pool_accounts.manager.pubkey(),
747+
)
748+
.await
749+
.unwrap();
750+
751+
mint_tokens(
752+
&mut banks_client,
753+
&payer,
754+
&recent_blockhash,
755+
&stake_pool_accounts.pool_mint.pubkey(),
756+
&stake_pool_accounts.pool_fee_account.pubkey(),
757+
&mint_authority,
758+
1,
759+
)
760+
.await
761+
.unwrap();
762+
763+
let transaction_error = create_stake_pool(
764+
&mut banks_client,
765+
&payer,
766+
&recent_blockhash,
767+
&stake_pool_accounts.stake_pool,
768+
&stake_pool_accounts.validator_list,
769+
&stake_pool_accounts.pool_mint.pubkey(),
770+
&stake_pool_accounts.pool_fee_account.pubkey(),
771+
&stake_pool_accounts.manager,
772+
&stake_pool_accounts.staker.pubkey(),
773+
&stake_pool_accounts.fee,
774+
stake_pool_accounts.max_validators,
775+
)
776+
.await
777+
.err()
778+
.unwrap();
779+
780+
match transaction_error {
781+
TransportError::TransactionError(TransactionError::InstructionError(
782+
_,
783+
InstructionError::Custom(error_index),
784+
)) => {
785+
let program_error = error::StakePoolError::NonZeroPoolTokenSupply as u32;
786+
assert_eq!(error_index, program_error);
787+
}
788+
_ => panic!("Wrong error occurs while try to initialize stake pool with wrong mint authority of pool fee account"),
789+
}
790+
}

0 commit comments

Comments
 (0)