From 9f38a6f4b21aa95d5539692d6b955d092b23ddcc Mon Sep 17 00:00:00 2001 From: Jon Cinque Date: Wed, 31 Mar 2021 00:54:15 +0200 Subject: [PATCH] Rework create validator stake account (#1539) --- stake-pool/cli/src/main.rs | 16 +- stake-pool/program/src/instruction.rs | 52 +++--- stake-pool/program/src/processor.rs | 42 ++++- stake-pool/program/src/stake.rs | 16 +- stake-pool/program/tests/deposit.rs | 140 ++++----------- stake-pool/program/tests/helpers/mod.rs | 41 ++--- stake-pool/program/tests/vsa_add.rs | 133 +++++--------- stake-pool/program/tests/vsa_create.rs | 220 ++++++++++++++---------- stake-pool/program/tests/vsa_remove.rs | 121 ++++--------- stake-pool/program/tests/withdraw.rs | 170 +++++------------- 10 files changed, 379 insertions(+), 572 deletions(-) diff --git a/stake-pool/cli/src/main.rs b/stake-pool/cli/src/main.rs index f52c6165554..6497b1d4270 100644 --- a/stake-pool/cli/src/main.rs +++ b/stake-pool/cli/src/main.rs @@ -277,13 +277,10 @@ fn command_vsa_create(config: &Config, pool: &Pubkey, vote_account: &Pubkey) -> create_validator_stake_account( &spl_stake_pool::id(), &pool, + &config.owner.pubkey(), &config.fee_payer.pubkey(), &stake_account, &vote_account, - &config.owner.pubkey(), - &config.owner.pubkey(), - &solana_program::system_program::id(), - &stake_program_id(), )?, ], Some(&config.fee_payer.pubkey()), @@ -291,7 +288,10 @@ fn command_vsa_create(config: &Config, pool: &Pubkey, vote_account: &Pubkey) -> let (recent_blockhash, fee_calculator) = config.rpc_client.get_recent_blockhash()?; check_fee_payer_balance(config, fee_calculator.calculate_fee(&transaction.message()))?; - transaction.sign(&[config.fee_payer.as_ref()], recent_blockhash); + transaction.sign( + &[config.fee_payer.as_ref(), config.owner.as_ref()], + recent_blockhash, + ); send_transaction(&config, transaction)?; Ok(()) } @@ -377,7 +377,6 @@ fn command_vsa_add( &token_receiver, &pool_data.pool_mint, &spl_token::id(), - &stake_program_id(), )?, ]); @@ -468,7 +467,6 @@ fn command_vsa_remove( &withdraw_from, &pool_data.pool_mint, &spl_token::id(), - &stake_program_id(), )?, ], Some(&config.fee_payer.pubkey()), @@ -645,7 +643,6 @@ fn command_deposit( &pool_data.owner_fee_account, &pool_data.pool_mint, &spl_token::id(), - &stake_program_id(), )?, ]); @@ -984,7 +981,6 @@ fn command_withdraw( &withdraw_from, &pool_data.pool_mint, &spl_token::id(), - &stake_program_id(), withdraw_stake.pool_amount, )?); } @@ -1163,7 +1159,7 @@ fn main() { .help("Max number of validators included in the stake pool"), ) ) - .subcommand(SubCommand::with_name("create-validator-stake").about("Create a new stake account to use with the pool") + .subcommand(SubCommand::with_name("create-validator-stake").about("Create a new stake account to use with the pool. Must be signed by the pool owner.") .arg( Arg::with_name("pool") .index(1) diff --git a/stake-pool/program/src/instruction.rs b/stake-pool/program/src/instruction.rs index eb2881a50c3..db3043870e1 100644 --- a/stake-pool/program/src/instruction.rs +++ b/stake-pool/program/src/instruction.rs @@ -3,12 +3,13 @@ #![allow(clippy::too_many_arguments)] use { + crate::stake, borsh::{BorshDeserialize, BorshSchema, BorshSerialize}, solana_program::{ instruction::{AccountMeta, Instruction}, program_error::ProgramError, pubkey::Pubkey, - sysvar, + system_program, sysvar, }, }; @@ -48,17 +49,17 @@ pub enum StakePoolInstruction { /// Creates new program account for accumulating stakes for a particular validator /// /// 0. `[]` Stake pool account this stake will belong to - /// 1. `[ws]` Funding account (must be a system account) - /// 2. `[w]` Stake account to be created - /// 3. `[]` Validator this stake account will vote for - /// 4. `[]` Stake authority for the new stake account - /// 5. `[]` Withdraw authority for the new stake account - /// 6. `[]` Rent sysvar - /// 7. `[]` System program - /// 8. `[]` Stake program + /// 1. `[s]` Owner + /// 2. `[ws]` Funding account (must be a system account) + /// 3. `[w]` Stake account to be created + /// 4. `[]` Validator this stake account will vote for + /// 5. `[]` Rent sysvar + /// 6. `[]` System program + /// 7. `[]` Stake program CreateValidatorStakeAccount, - /// Adds validator stake account to the pool + /// Adds stake account delegated to validator to the pool's list of + /// managed validators /// /// 0. `[w]` Stake pool /// 1. `[s]` Owner @@ -185,24 +186,23 @@ pub fn initialize( pub fn create_validator_stake_account( program_id: &Pubkey, stake_pool: &Pubkey, + owner: &Pubkey, funder: &Pubkey, stake_account: &Pubkey, validator: &Pubkey, - stake_authority: &Pubkey, - withdraw_authority: &Pubkey, - system_program_id: &Pubkey, - stake_program_id: &Pubkey, ) -> Result { let accounts = vec![ AccountMeta::new_readonly(*stake_pool, false), + AccountMeta::new_readonly(*owner, true), AccountMeta::new(*funder, true), AccountMeta::new(*stake_account, false), AccountMeta::new_readonly(*validator, false), - AccountMeta::new_readonly(*stake_authority, false), - AccountMeta::new_readonly(*withdraw_authority, false), AccountMeta::new_readonly(sysvar::rent::id(), false), - AccountMeta::new_readonly(*system_program_id, false), - AccountMeta::new_readonly(*stake_program_id, false), + AccountMeta::new_readonly(sysvar::clock::id(), false), + AccountMeta::new_readonly(sysvar::stake_history::id(), false), + AccountMeta::new_readonly(stake::config_id(), false), + AccountMeta::new_readonly(system_program::id(), false), + AccountMeta::new_readonly(stake::id(), false), ]; Ok(Instruction { program_id: *program_id, @@ -220,10 +220,9 @@ pub fn add_validator_to_pool( stake_pool_withdraw: &Pubkey, validator_list: &Pubkey, stake_account: &Pubkey, - pool_tokens_to: &Pubkey, + pool_token_receiver: &Pubkey, pool_mint: &Pubkey, token_program_id: &Pubkey, - stake_program_id: &Pubkey, ) -> Result { let accounts = vec![ AccountMeta::new(*stake_pool, false), @@ -232,12 +231,12 @@ pub fn add_validator_to_pool( AccountMeta::new_readonly(*stake_pool_withdraw, false), AccountMeta::new(*validator_list, false), AccountMeta::new(*stake_account, false), - AccountMeta::new(*pool_tokens_to, false), + AccountMeta::new(*pool_token_receiver, false), AccountMeta::new(*pool_mint, false), AccountMeta::new_readonly(sysvar::clock::id(), false), AccountMeta::new_readonly(sysvar::stake_history::id(), false), AccountMeta::new_readonly(*token_program_id, false), - AccountMeta::new_readonly(*stake_program_id, false), + AccountMeta::new_readonly(stake::id(), false), ]; Ok(Instruction { program_id: *program_id, @@ -258,7 +257,6 @@ pub fn remove_validator_from_pool( burn_from: &Pubkey, pool_mint: &Pubkey, token_program_id: &Pubkey, - stake_program_id: &Pubkey, ) -> Result { let accounts = vec![ AccountMeta::new(*stake_pool, false), @@ -271,7 +269,7 @@ pub fn remove_validator_from_pool( AccountMeta::new(*pool_mint, false), AccountMeta::new_readonly(sysvar::clock::id(), false), AccountMeta::new_readonly(*token_program_id, false), - AccountMeta::new_readonly(*stake_program_id, false), + AccountMeta::new_readonly(stake::id(), false), ]; Ok(Instruction { program_id: *program_id, @@ -330,7 +328,6 @@ pub fn deposit( pool_fee_to: &Pubkey, pool_mint: &Pubkey, token_program_id: &Pubkey, - stake_program_id: &Pubkey, ) -> Result { let accounts = vec![ AccountMeta::new(*stake_pool, false), @@ -345,7 +342,7 @@ pub fn deposit( AccountMeta::new_readonly(sysvar::clock::id(), false), AccountMeta::new_readonly(sysvar::stake_history::id(), false), AccountMeta::new_readonly(*token_program_id, false), - AccountMeta::new_readonly(*stake_program_id, false), + AccountMeta::new_readonly(stake::id(), false), ]; Ok(Instruction { program_id: *program_id, @@ -366,7 +363,6 @@ pub fn withdraw( burn_from: &Pubkey, pool_mint: &Pubkey, token_program_id: &Pubkey, - stake_program_id: &Pubkey, amount: u64, ) -> Result { let accounts = vec![ @@ -380,7 +376,7 @@ pub fn withdraw( AccountMeta::new(*pool_mint, false), AccountMeta::new_readonly(sysvar::clock::id(), false), AccountMeta::new_readonly(*token_program_id, false), - AccountMeta::new_readonly(*stake_program_id, false), + AccountMeta::new_readonly(stake::id(), false), ]; Ok(Instruction { program_id: *program_id, diff --git a/stake-pool/program/src/processor.rs b/stake-pool/program/src/processor.rs index ad1e790bde9..d9c35f533b0 100644 --- a/stake-pool/program/src/processor.rs +++ b/stake-pool/program/src/processor.rs @@ -403,24 +403,38 @@ impl Processor { let account_info_iter = &mut accounts.iter(); // Stake pool account let stake_pool_info = next_account_info(account_info_iter)?; + // Owner account + let owner_info = next_account_info(account_info_iter)?; // Account creation funder account let funder_info = next_account_info(account_info_iter)?; // Stake account to be created let stake_account_info = next_account_info(account_info_iter)?; // Validator this stake account will vote for let validator_info = next_account_info(account_info_iter)?; - // Stake authority for the new stake account - let stake_authority_info = next_account_info(account_info_iter)?; - // Withdraw authority for the new stake account - let withdraw_authority_info = next_account_info(account_info_iter)?; // Rent sysvar account let rent_info = next_account_info(account_info_iter)?; let rent = &Rent::from_account_info(rent_info)?; + // Clock sysvar account + let clock_info = next_account_info(account_info_iter)?; + // Stake history sysvar account + let stake_history_info = next_account_info(account_info_iter)?; + // Stake config sysvar account + let stake_config_info = next_account_info(account_info_iter)?; // System program id let system_program_info = next_account_info(account_info_iter)?; // Staking program id let stake_program_info = next_account_info(account_info_iter)?; + // Get stake pool stake (and check if it is initialized) + if stake_pool_info.owner != program_id { + return Err(ProgramError::IncorrectProgramId); + } + let stake_pool = StakePool::try_from_slice(&stake_pool_info.data.borrow())?; + if !stake_pool.is_valid() { + return Err(StakePoolError::InvalidState.into()); + } + stake_pool.check_owner(owner_info)?; + // Check program ids if *system_program_info.key != solana_program::system_program::id() { return Err(ProgramError::IncorrectProgramId); @@ -466,8 +480,8 @@ impl Processor { &stake::initialize( &stake_account_info.key, &stake::Authorized { - staker: *stake_authority_info.key, - withdrawer: *withdraw_authority_info.key, + staker: *owner_info.key, + withdrawer: *owner_info.key, }, &stake::Lockup::default(), ), @@ -476,6 +490,22 @@ impl Processor { rent_info.clone(), stake_program_info.clone(), ], + )?; + + invoke( + &stake::delegate_stake( + &stake_account_info.key, + &owner_info.key, + &validator_info.key, + ), + &[ + stake_account_info.clone(), + validator_info.clone(), + clock_info.clone(), + stake_history_info.clone(), + stake_config_info.clone(), + owner_info.clone(), + ], ) } diff --git a/stake-pool/program/src/stake.rs b/stake-pool/program/src/stake.rs index a23f52049d7..2eeb53b322d 100644 --- a/stake-pool/program/src/stake.rs +++ b/stake-pool/program/src/stake.rs @@ -13,6 +13,10 @@ use std::str::FromStr; solana_program::declare_id!("Stake11111111111111111111111111111111111111"); const STAKE_CONFIG: &str = "StakeConfig11111111111111111111111111111111"; +/// Id for stake config account +pub fn config_id() -> Pubkey { + Pubkey::from_str(STAKE_CONFIG).unwrap() +} /// FIXME copied from solana stake program #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] @@ -489,8 +493,18 @@ pub fn delegate_stake( AccountMeta::new_readonly(*vote_pubkey, false), AccountMeta::new_readonly(sysvar::clock::id(), false), AccountMeta::new_readonly(sysvar::stake_history::id(), false), - AccountMeta::new_readonly(Pubkey::from_str(STAKE_CONFIG).unwrap(), false), + AccountMeta::new_readonly(config_id(), false), AccountMeta::new_readonly(*authorized_pubkey, true), ]; Instruction::new_with_bincode(id(), &StakeInstruction::DelegateStake, account_metas) } + +/// FIXME copied from stake program +pub fn deactivate_stake(stake_pubkey: &Pubkey, authorized_pubkey: &Pubkey) -> Instruction { + let account_metas = vec![ + AccountMeta::new(*stake_pubkey, false), + AccountMeta::new_readonly(sysvar::clock::id(), false), + AccountMeta::new_readonly(*authorized_pubkey, true), + ]; + Instruction::new_with_bincode(id(), &StakeInstruction::Deactivate, account_metas) +} diff --git a/stake-pool/program/tests/deposit.rs b/stake-pool/program/tests/deposit.rs index e750bd3ea8a..a5b911d4e0e 100644 --- a/stake-pool/program/tests/deposit.rs +++ b/stake-pool/program/tests/deposit.rs @@ -3,12 +3,16 @@ mod helpers; use { - borsh::BorshDeserialize, + borsh::{BorshDeserialize, BorshSerialize}, helpers::*, - solana_program::hash::Hash, + solana_program::{ + hash::Hash, + instruction::{AccountMeta, Instruction, InstructionError}, + pubkey::Pubkey, + sysvar, + }, solana_program_test::*, solana_sdk::{ - instruction::InstructionError, signature::{Keypair, Signer}, transaction::Transaction, transaction::TransactionError, @@ -237,26 +241,32 @@ async fn test_stake_pool_deposit_with_wrong_stake_program_id() { .await .unwrap(); - let wrong_stake_program = Keypair::new(); + let wrong_stake_program = Pubkey::new_unique(); + + let accounts = vec![ + AccountMeta::new(stake_pool_accounts.stake_pool.pubkey(), false), + AccountMeta::new(stake_pool_accounts.validator_list.pubkey(), false), + AccountMeta::new_readonly(stake_pool_accounts.deposit_authority, false), + AccountMeta::new_readonly(stake_pool_accounts.withdraw_authority, false), + AccountMeta::new(user_stake.pubkey(), false), + AccountMeta::new(validator_stake_account.stake_account, false), + AccountMeta::new(user_pool_account.pubkey(), false), + AccountMeta::new(stake_pool_accounts.pool_fee_account.pubkey(), false), + AccountMeta::new(stake_pool_accounts.pool_mint.pubkey(), false), + AccountMeta::new_readonly(sysvar::clock::id(), false), + AccountMeta::new_readonly(sysvar::stake_history::id(), false), + AccountMeta::new_readonly(spl_token::id(), false), + AccountMeta::new_readonly(wrong_stake_program, false), + ]; + let instruction = Instruction { + program_id: id(), + accounts, + data: instruction::StakePoolInstruction::Deposit + .try_to_vec() + .unwrap(), + }; - let mut transaction = Transaction::new_with_payer( - &[instruction::deposit( - &id(), - &stake_pool_accounts.stake_pool.pubkey(), - &stake_pool_accounts.validator_list.pubkey(), - &stake_pool_accounts.deposit_authority, - &stake_pool_accounts.withdraw_authority, - &user_stake.pubkey(), - &validator_stake_account.stake_account, - &user_pool_account.pubkey(), - &stake_pool_accounts.pool_fee_account.pubkey(), - &stake_pool_accounts.pool_mint.pubkey(), - &spl_token::id(), - &wrong_stake_program.pubkey(), - ) - .unwrap()], - Some(&payer.pubkey()), - ); + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); transaction.sign(&[&payer], recent_blockhash); let transaction_error = banks_client .process_transaction(transaction) @@ -392,7 +402,6 @@ async fn test_stake_pool_deposit_with_wrong_token_program_id() { &stake_pool_accounts.pool_fee_account.pubkey(), &stake_pool_accounts.pool_mint.pubkey(), &wrong_token_program.pubkey(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -482,7 +491,7 @@ async fn test_stake_pool_deposit_with_wrong_validator_list_account() { } #[tokio::test] -async fn test_stake_pool_deposit_where_stake_acc_not_in_stake_state() { +async fn test_stake_pool_deposit_to_unknown_validator() { let (mut banks_client, payer, recent_blockhash) = program_test().start().await; let stake_pool_accounts = StakePoolAccounts::new(); stake_pool_accounts @@ -494,90 +503,13 @@ async fn test_stake_pool_deposit_where_stake_acc_not_in_stake_state() { &stake_pool_accounts.deposit_authority, &stake_pool_accounts.stake_pool.pubkey(), ); - - let user_stake_authority = Keypair::new(); - create_validator_stake_account( - &mut banks_client, - &payer, - &recent_blockhash, - &validator_stake_account.stake_pool, - &validator_stake_account.stake_account, - &validator_stake_account.vote.pubkey(), - &user_stake_authority.pubkey(), - &validator_stake_account.target_authority, - ) - .await; - - let user_pool_account = Keypair::new(); - let user = Keypair::new(); - create_token_account( - &mut banks_client, - &payer, - &recent_blockhash, - &user_pool_account, - &stake_pool_accounts.pool_mint.pubkey(), - &user.pubkey(), - ) - .await - .unwrap(); - - let user_stake_acc = Keypair::new(); - let lockup = stake::Lockup::default(); - let authorized = stake::Authorized { - staker: stake_pool_accounts.deposit_authority, - withdrawer: stake_pool_accounts.deposit_authority, - }; - create_independent_stake_account( - &mut banks_client, - &payer, - &recent_blockhash, - &user_stake_acc, - &authorized, - &lockup, - ) - .await; - let transaction_error = stake_pool_accounts - .deposit_stake( + validator_stake_account + .create_and_delegate( &mut banks_client, &payer, &recent_blockhash, - &user_stake_acc.pubkey(), - &user_pool_account.pubkey(), - &validator_stake_account.stake_account, + &stake_pool_accounts.owner, ) - .await - .err() - .unwrap(); - - match transaction_error { - TransportError::TransactionError(TransactionError::InstructionError( - _, - InstructionError::Custom(error_index), - )) => { - let program_error = error::StakePoolError::WrongStakeState as u32; - assert_eq!(error_index, program_error); - } - _ => panic!( - "Wrong error occurs while try to make a deposit when stake acc not in stake state" - ), - } -} - -#[tokio::test] -async fn test_stake_pool_deposit_to_unknown_validator() { - let (mut banks_client, payer, recent_blockhash) = program_test().start().await; - let stake_pool_accounts = StakePoolAccounts::new(); - stake_pool_accounts - .initialize_stake_pool(&mut banks_client, &payer, &recent_blockhash) - .await - .unwrap(); - - let validator_stake_account = ValidatorStakeAccount::new_with_target_authority( - &stake_pool_accounts.deposit_authority, - &stake_pool_accounts.stake_pool.pubkey(), - ); - validator_stake_account - .create_and_delegate(&mut banks_client, &payer, &recent_blockhash) .await; let user_pool_account = Keypair::new(); diff --git a/stake-pool/program/tests/helpers/mod.rs b/stake-pool/program/tests/helpers/mod.rs index 0ca4dbe4abd..13f8569e14a 100644 --- a/stake-pool/program/tests/helpers/mod.rs +++ b/stake-pool/program/tests/helpers/mod.rs @@ -300,30 +300,26 @@ pub async fn create_validator_stake_account( payer: &Keypair, recent_blockhash: &Hash, stake_pool: &Pubkey, + owner: &Keypair, stake_account: &Pubkey, validator: &Pubkey, - stake_authority: &Pubkey, - withdraw_authority: &Pubkey, ) { let mut transaction = Transaction::new_with_payer( &[ instruction::create_validator_stake_account( &id(), &stake_pool, + &owner.pubkey(), &payer.pubkey(), &stake_account, &validator, - &stake_authority, - &withdraw_authority, - &solana_program::system_program::id(), - &stake::id(), ) .unwrap(), system_instruction::transfer(&payer.pubkey(), &stake_account, TEST_STAKE_AMOUNT), ], Some(&payer.pubkey()), ); - transaction.sign(&[payer], *recent_blockhash); + transaction.sign(&[payer, owner], *recent_blockhash); banks_client.process_transaction(transaction).await.unwrap(); } @@ -393,29 +389,29 @@ impl ValidatorStakeAccount { mut banks_client: &mut BanksClient, payer: &Keypair, recent_blockhash: &Hash, + owner: &Keypair, ) { - // make stake account - let user_stake_authority = Keypair::new(); + create_vote(&mut banks_client, &payer, &recent_blockhash, &self.vote).await; + create_validator_stake_account( &mut banks_client, &payer, &recent_blockhash, &self.stake_pool, + owner, &self.stake_account, &self.vote.pubkey(), - &user_stake_authority.pubkey(), - &self.target_authority, ) .await; - create_vote(&mut banks_client, &payer, &recent_blockhash, &self.vote).await; - delegate_stake_account( + authorize_stake_account( &mut banks_client, &payer, &recent_blockhash, &self.stake_account, - &user_stake_authority, - &self.vote.pubkey(), + &owner, + &self.target_authority, + stake::StakeAuthorize::Staker, ) .await; @@ -424,9 +420,9 @@ impl ValidatorStakeAccount { &payer, &recent_blockhash, &self.stake_account, - &user_stake_authority, + &owner, &self.target_authority, - stake::StakeAuthorize::Staker, + stake::StakeAuthorize::Withdrawer, ) .await; } @@ -542,7 +538,6 @@ impl StakePoolAccounts { &self.pool_fee_account.pubkey(), &self.pool_mint.pubkey(), &spl_token::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -575,7 +570,6 @@ impl StakePoolAccounts { pool_account, &self.pool_mint.pubkey(), &spl_token::id(), - &stake::id(), amount, ) .unwrap()], @@ -606,7 +600,6 @@ impl StakePoolAccounts { pool_account, &self.pool_mint.pubkey(), &spl_token::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -636,7 +629,6 @@ impl StakePoolAccounts { pool_account, &self.pool_mint.pubkey(), &spl_token::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -657,7 +649,12 @@ pub async fn simple_add_validator_to_pool( &stake_pool_accounts.stake_pool.pubkey(), ); user_stake - .create_and_delegate(banks_client, &payer, &recent_blockhash) + .create_and_delegate( + banks_client, + &payer, + &recent_blockhash, + &stake_pool_accounts.owner, + ) .await; let user_pool_account = Keypair::new(); diff --git a/stake-pool/program/tests/vsa_add.rs b/stake-pool/program/tests/vsa_add.rs index 048f0ef1399..f2645f1b40e 100644 --- a/stake-pool/program/tests/vsa_add.rs +++ b/stake-pool/program/tests/vsa_add.rs @@ -8,12 +8,12 @@ use { helpers::*, solana_program::{ hash::Hash, - instruction::{AccountMeta, Instruction}, + instruction::{AccountMeta, Instruction, InstructionError}, + pubkey::Pubkey, sysvar, }, solana_program_test::*, solana_sdk::{ - instruction::InstructionError, signature::{Keypair, Signer}, transaction::{Transaction, TransactionError}, transport::TransportError, @@ -43,7 +43,12 @@ async fn setup() -> ( &stake_pool_accounts.stake_pool.pubkey(), ); user_stake - .create_and_delegate(&mut banks_client, &payer, &recent_blockhash) + .create_and_delegate( + &mut banks_client, + &payer, + &recent_blockhash, + &stake_pool_accounts.owner, + ) .await; // make pool token account @@ -170,7 +175,6 @@ async fn test_add_validator_to_pool_with_wrong_token_program_id() { &user_pool_account.pubkey(), &stake_pool_accounts.pool_mint.pubkey(), &stake::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -215,7 +219,6 @@ async fn test_add_validator_to_pool_with_wrong_pool_mint_account() { &user_pool_account.pubkey(), &wrong_pool_mint.pubkey(), &spl_token::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -264,7 +267,6 @@ async fn test_add_validator_to_pool_with_wrong_validator_list_account() { &user_pool_account.pubkey(), &stake_pool_accounts.pool_mint.pubkey(), &spl_token::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -359,7 +361,6 @@ async fn test_not_owner_try_to_add_validator_to_pool() { &user_pool_account.pubkey(), &stake_pool_accounts.pool_mint.pubkey(), &spl_token::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -436,69 +437,6 @@ async fn test_not_owner_try_to_add_validator_to_pool_without_signature() { } } -#[tokio::test] -async fn test_add_validator_to_pool_when_stake_acc_not_in_stake_state() { - let (mut banks_client, payer, recent_blockhash) = program_test().start().await; - let stake_pool_accounts = StakePoolAccounts::new(); - stake_pool_accounts - .initialize_stake_pool(&mut banks_client, &payer, &recent_blockhash) - .await - .unwrap(); - - let user = Keypair::new(); - - let user_stake = ValidatorStakeAccount::new_with_target_authority( - &stake_pool_accounts.deposit_authority, - &stake_pool_accounts.stake_pool.pubkey(), - ); - let user_stake_authority = Keypair::new(); - create_validator_stake_account( - &mut banks_client, - &payer, - &recent_blockhash, - &user_stake.stake_pool, - &user_stake.stake_account, - &user_stake.vote.pubkey(), - &user_stake_authority.pubkey(), - &user_stake.target_authority, - ) - .await; - - let user_pool_account = Keypair::new(); - create_token_account( - &mut banks_client, - &payer, - &recent_blockhash, - &user_pool_account, - &stake_pool_accounts.pool_mint.pubkey(), - &user.pubkey(), - ) - .await - .unwrap(); - - let transaction_error = stake_pool_accounts - .add_validator_to_pool( - &mut banks_client, - &payer, - &recent_blockhash, - &user_stake.stake_account, - &user_pool_account.pubkey(), - ) - .await - .unwrap(); - - match transaction_error { - TransportError::TransactionError(TransactionError::InstructionError( - _, - InstructionError::Custom(error_index), - )) => { - let program_error = error::StakePoolError::WrongStakeState as u32; - assert_eq!(error_index, program_error); - } - _ => panic!("Wrong error occurs while try to add validator stake account when it isn't in stake state"), - } -} - #[tokio::test] async fn test_add_validator_to_pool_with_wrong_stake_program_id() { let ( @@ -510,25 +448,30 @@ async fn test_add_validator_to_pool_with_wrong_stake_program_id() { user_pool_account, ) = setup().await; - let wrong_stake_program = Keypair::new(); + let wrong_stake_program = Pubkey::new_unique(); - let mut transaction = Transaction::new_with_payer( - &[instruction::add_validator_to_pool( - &id(), - &stake_pool_accounts.stake_pool.pubkey(), - &stake_pool_accounts.owner.pubkey(), - &stake_pool_accounts.deposit_authority, - &stake_pool_accounts.withdraw_authority, - &stake_pool_accounts.validator_list.pubkey(), - &user_stake.stake_account, - &user_pool_account.pubkey(), - &stake_pool_accounts.pool_mint.pubkey(), - &spl_token::id(), - &wrong_stake_program.pubkey(), - ) - .unwrap()], - Some(&payer.pubkey()), - ); + let accounts = vec![ + AccountMeta::new(stake_pool_accounts.stake_pool.pubkey(), false), + AccountMeta::new_readonly(stake_pool_accounts.owner.pubkey(), true), + AccountMeta::new_readonly(stake_pool_accounts.deposit_authority, false), + AccountMeta::new_readonly(stake_pool_accounts.withdraw_authority, false), + AccountMeta::new(stake_pool_accounts.validator_list.pubkey(), false), + AccountMeta::new(user_stake.stake_account, false), + AccountMeta::new(user_pool_account.pubkey(), false), + AccountMeta::new(stake_pool_accounts.pool_mint.pubkey(), false), + AccountMeta::new_readonly(sysvar::clock::id(), false), + AccountMeta::new_readonly(sysvar::stake_history::id(), false), + AccountMeta::new_readonly(spl_token::id(), false), + AccountMeta::new_readonly(wrong_stake_program, false), + ]; + let instruction = Instruction { + program_id: id(), + accounts, + data: instruction::StakePoolInstruction::AddValidatorToPool + .try_to_vec() + .unwrap(), + }; + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); transaction.sign(&[&payer, &stake_pool_accounts.owner], recent_blockhash); let transaction_error = banks_client .process_transaction(transaction) @@ -563,7 +506,12 @@ async fn test_add_too_many_validator_stake_accounts() { &stake_pool_accounts.stake_pool.pubkey(), ); user_stake - .create_and_delegate(&mut banks_client, &payer, &recent_blockhash) + .create_and_delegate( + &mut banks_client, + &payer, + &recent_blockhash, + &stake_pool_accounts.owner, + ) .await; // make pool token account @@ -595,7 +543,12 @@ async fn test_add_too_many_validator_stake_accounts() { &stake_pool_accounts.stake_pool.pubkey(), ); user_stake - .create_and_delegate(&mut banks_client, &payer, &recent_blockhash) + .create_and_delegate( + &mut banks_client, + &payer, + &recent_blockhash, + &stake_pool_accounts.owner, + ) .await; let error = stake_pool_accounts .add_validator_to_pool( diff --git a/stake-pool/program/tests/vsa_create.rs b/stake-pool/program/tests/vsa_create.rs index baad6e65291..e0f36fde1c3 100644 --- a/stake-pool/program/tests/vsa_create.rs +++ b/stake-pool/program/tests/vsa_create.rs @@ -2,22 +2,27 @@ mod helpers; -use crate::solana_program::pubkey::Pubkey; -use helpers::*; - -use bincode::deserialize; -use solana_program_test::*; -use solana_sdk::{ - instruction::InstructionError, - signature::{Keypair, Signer}, - transaction::Transaction, - transaction::TransactionError, - transport::TransportError, +use { + bincode::deserialize, + borsh::BorshSerialize, + helpers::*, + solana_program::{ + instruction::{AccountMeta, Instruction, InstructionError}, + pubkey::Pubkey, + system_program, sysvar, + }, + solana_program_test::*, + solana_sdk::{ + signature::{Keypair, Signer}, + transaction::Transaction, + transaction::TransactionError, + transport::TransportError, + }, + spl_stake_pool::{error, id, instruction, processor, stake}, }; -use spl_stake_pool::*; #[tokio::test] -async fn test_create_validator_stake_account() { +async fn success_create_validator_stake_account() { let (mut banks_client, payer, recent_blockhash) = program_test().start().await; let stake_pool_accounts = StakePoolAccounts::new(); stake_pool_accounts @@ -25,13 +30,12 @@ async fn test_create_validator_stake_account() { .await .unwrap(); - let validator = Pubkey::new_unique(); - let user_stake_authority = Keypair::new(); - let user_withdraw_authority = Keypair::new(); + let validator = Keypair::new(); + create_vote(&mut banks_client, &payer, &recent_blockhash, &validator).await; let (stake_account, _) = processor::Processor::find_stake_address_for_validator( &id(), - &validator, + &validator.pubkey(), &stake_pool_accounts.stake_pool.pubkey(), ); @@ -39,37 +43,35 @@ async fn test_create_validator_stake_account() { &[instruction::create_validator_stake_account( &id(), &stake_pool_accounts.stake_pool.pubkey(), + &stake_pool_accounts.owner.pubkey(), &payer.pubkey(), &stake_account, - &validator, - &user_stake_authority.pubkey(), - &user_withdraw_authority.pubkey(), - &solana_program::system_program::id(), - &stake::id(), + &validator.pubkey(), ) .unwrap()], Some(&payer.pubkey()), ); - transaction.sign(&[&payer], recent_blockhash); + transaction.sign(&[&payer, &stake_pool_accounts.owner], recent_blockhash); banks_client.process_transaction(transaction).await.unwrap(); // Check authorities let stake = get_account(&mut banks_client, &stake_account).await; let stake_state = deserialize::(&stake.data).unwrap(); match stake_state { - stake::StakeState::Initialized(meta) => { - assert_eq!(&meta.authorized.staker, &user_stake_authority.pubkey()); + stake::StakeState::Stake(meta, stake) => { + assert_eq!(&meta.authorized.staker, &stake_pool_accounts.owner.pubkey()); assert_eq!( &meta.authorized.withdrawer, - &user_withdraw_authority.pubkey() + &stake_pool_accounts.owner.pubkey() ); + assert_eq!(stake.delegation.voter_pubkey, validator.pubkey()); } _ => panic!(), } } #[tokio::test] -async fn test_create_validator_stake_account_with_incorrect_address() { +async fn fail_create_validator_stake_account_on_non_vote_account() { let (mut banks_client, payer, recent_blockhash) = program_test().start().await; let stake_pool_accounts = StakePoolAccounts::new(); stake_pool_accounts @@ -78,48 +80,41 @@ async fn test_create_validator_stake_account_with_incorrect_address() { .unwrap(); let validator = Pubkey::new_unique(); - let user_stake_authority = Keypair::new(); - let user_withdraw_authority = Keypair::new(); - let stake_account = Keypair::new(); + + let (stake_account, _) = processor::Processor::find_stake_address_for_validator( + &id(), + &validator, + &stake_pool_accounts.stake_pool.pubkey(), + ); let mut transaction = Transaction::new_with_payer( &[instruction::create_validator_stake_account( &id(), &stake_pool_accounts.stake_pool.pubkey(), + &stake_pool_accounts.owner.pubkey(), &payer.pubkey(), - &stake_account.pubkey(), + &stake_account, &validator, - &user_stake_authority.pubkey(), - &user_withdraw_authority.pubkey(), - &solana_program::system_program::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), ); - transaction.sign(&[&payer], recent_blockhash); + transaction.sign(&[&payer, &stake_pool_accounts.owner], recent_blockhash); let transaction_error = banks_client .process_transaction(transaction) .await .err() + .unwrap() .unwrap(); - match transaction_error { - TransportError::TransactionError(TransactionError::InstructionError( - _, - InstructionError::Custom(error_index), - )) => { - let program_error = error::StakePoolError::InvalidStakeAccountAddress as u32; - assert_eq!(error_index, program_error); - } - _ => panic!( - "Wrong error occurs while try to create validator stake account with incorrect address" - ), - } + assert_eq!( + transaction_error, + TransactionError::InstructionError(0, InstructionError::IncorrectProgramId,) + ); } #[tokio::test] -async fn test_create_validator_stake_account_with_wrong_system_program() { +async fn fail_create_validator_stake_account_with_wrong_system_program() { let (mut banks_client, payer, recent_blockhash) = program_test().start().await; let stake_pool_accounts = StakePoolAccounts::new(); stake_pool_accounts @@ -128,51 +123,51 @@ async fn test_create_validator_stake_account_with_wrong_system_program() { .unwrap(); let validator = Pubkey::new_unique(); - let user_stake_authority = Keypair::new(); - let user_withdraw_authority = Keypair::new(); let (stake_account, _) = processor::Processor::find_stake_address_for_validator( &id(), &validator, &stake_pool_accounts.stake_pool.pubkey(), ); + let wrong_system_program = Pubkey::new_unique(); + let accounts = vec![ + AccountMeta::new_readonly(stake_pool_accounts.stake_pool.pubkey(), false), + AccountMeta::new_readonly(stake_pool_accounts.owner.pubkey(), true), + AccountMeta::new(payer.pubkey(), true), + AccountMeta::new(stake_account, false), + AccountMeta::new_readonly(validator, false), + AccountMeta::new_readonly(sysvar::rent::id(), false), + AccountMeta::new_readonly(sysvar::clock::id(), false), + AccountMeta::new_readonly(sysvar::stake_history::id(), false), + AccountMeta::new_readonly(stake::config_id(), false), + AccountMeta::new_readonly(wrong_system_program, false), + AccountMeta::new_readonly(stake::id(), false), + ]; + let instruction = Instruction { + program_id: id(), + accounts, + data: instruction::StakePoolInstruction::CreateValidatorStakeAccount + .try_to_vec() + .unwrap(), + }; - let wrong_system_program = Keypair::new(); - - let mut transaction = Transaction::new_with_payer( - &[instruction::create_validator_stake_account( - &id(), - &stake_pool_accounts.stake_pool.pubkey(), - &payer.pubkey(), - &stake_account, - &validator, - &user_stake_authority.pubkey(), - &user_withdraw_authority.pubkey(), - &wrong_system_program.pubkey(), - &stake::id(), - ) - .unwrap()], - Some(&payer.pubkey()), - ); - transaction.sign(&[&payer], recent_blockhash); + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer, &stake_pool_accounts.owner], recent_blockhash); let transaction_error = banks_client .process_transaction(transaction) .await .err() + .unwrap() .unwrap(); - match transaction_error { - TransportError::TransactionError(TransactionError::InstructionError(_, error)) => { - assert_eq!(error, InstructionError::IncorrectProgramId); - } - _ => panic!( - "Wrong error occurs while try to create validator stake account with wrong token program ID" - ), - } + assert_eq!( + transaction_error, + TransactionError::InstructionError(0, InstructionError::IncorrectProgramId,) + ); } #[tokio::test] -async fn test_create_validator_stake_account_with_wrong_stake_program() { +async fn fail_create_validator_stake_account_with_wrong_stake_program() { let (mut banks_client, payer, recent_blockhash) = program_test().start().await; let stake_pool_accounts = StakePoolAccounts::new(); stake_pool_accounts @@ -181,33 +176,74 @@ async fn test_create_validator_stake_account_with_wrong_stake_program() { .unwrap(); let validator = Pubkey::new_unique(); - let user_stake_authority = Keypair::new(); - let user_withdraw_authority = Keypair::new(); let (stake_account, _) = processor::Processor::find_stake_address_for_validator( &id(), &validator, &stake_pool_accounts.stake_pool.pubkey(), ); + let wrong_stake_program = Pubkey::new_unique(); + let accounts = vec![ + AccountMeta::new_readonly(stake_pool_accounts.stake_pool.pubkey(), false), + AccountMeta::new_readonly(stake_pool_accounts.owner.pubkey(), true), + AccountMeta::new(payer.pubkey(), true), + AccountMeta::new(stake_account, false), + AccountMeta::new_readonly(validator, false), + AccountMeta::new_readonly(sysvar::rent::id(), false), + AccountMeta::new_readonly(sysvar::clock::id(), false), + AccountMeta::new_readonly(sysvar::stake_history::id(), false), + AccountMeta::new_readonly(stake::config_id(), false), + AccountMeta::new_readonly(system_program::id(), false), + AccountMeta::new_readonly(wrong_stake_program, false), + ]; + let instruction = Instruction { + program_id: id(), + accounts, + data: instruction::StakePoolInstruction::CreateValidatorStakeAccount + .try_to_vec() + .unwrap(), + }; + + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); + transaction.sign(&[&payer, &stake_pool_accounts.owner], recent_blockhash); + let transaction_error = banks_client + .process_transaction(transaction) + .await + .err() + .unwrap() + .unwrap(); - let wrong_stake_program = Keypair::new(); + assert_eq!( + transaction_error, + TransactionError::InstructionError(0, InstructionError::IncorrectProgramId,) + ); +} + +#[tokio::test] +async fn fail_create_validator_stake_account_with_incorrect_address() { + let (mut banks_client, payer, recent_blockhash) = program_test().start().await; + let stake_pool_accounts = StakePoolAccounts::new(); + stake_pool_accounts + .initialize_stake_pool(&mut banks_client, &payer, &recent_blockhash) + .await + .unwrap(); + + let validator = Pubkey::new_unique(); + let stake_account = Keypair::new(); let mut transaction = Transaction::new_with_payer( &[instruction::create_validator_stake_account( &id(), &stake_pool_accounts.stake_pool.pubkey(), + &stake_pool_accounts.owner.pubkey(), &payer.pubkey(), - &stake_account, + &stake_account.pubkey(), &validator, - &user_stake_authority.pubkey(), - &user_withdraw_authority.pubkey(), - &solana_program::system_program::id(), - &wrong_stake_program.pubkey(), ) .unwrap()], Some(&payer.pubkey()), ); - transaction.sign(&[&payer], recent_blockhash); + transaction.sign(&[&payer, &stake_pool_accounts.owner], recent_blockhash); let transaction_error = banks_client .process_transaction(transaction) .await @@ -215,11 +251,15 @@ async fn test_create_validator_stake_account_with_wrong_stake_program() { .unwrap(); match transaction_error { - TransportError::TransactionError(TransactionError::InstructionError(_, error)) => { - assert_eq!(error, InstructionError::IncorrectProgramId); + TransportError::TransactionError(TransactionError::InstructionError( + _, + InstructionError::Custom(error_index), + )) => { + let program_error = error::StakePoolError::InvalidStakeAccountAddress as u32; + assert_eq!(error_index, program_error); } _ => panic!( - "Wrong error occurs while try to create validator stake account with wrong stake program ID" + "Wrong error occurs while try to create validator stake account with incorrect address" ), } } diff --git a/stake-pool/program/tests/vsa_remove.rs b/stake-pool/program/tests/vsa_remove.rs index 8cc29edaa7a..93d8dd93972 100644 --- a/stake-pool/program/tests/vsa_remove.rs +++ b/stake-pool/program/tests/vsa_remove.rs @@ -8,13 +8,12 @@ use { helpers::*, solana_program::{ hash::Hash, - instruction::{AccountMeta, Instruction}, + instruction::{AccountMeta, Instruction, InstructionError}, pubkey::Pubkey, sysvar, }, solana_program_test::*, solana_sdk::{ - instruction::InstructionError, signature::{Keypair, Signer}, transaction::{Transaction, TransactionError}, transport::TransportError, @@ -45,7 +44,12 @@ async fn setup() -> ( &stake_pool_accounts.stake_pool.pubkey(), ); user_stake - .create_and_delegate(&mut banks_client, &payer, &recent_blockhash) + .create_and_delegate( + &mut banks_client, + &payer, + &recent_blockhash, + &stake_pool_accounts.owner, + ) .await; // make pool token account @@ -165,26 +169,31 @@ async fn test_remove_validator_from_pool_with_wrong_stake_program_id() { _, ) = setup().await; - let wrong_stake_program = Keypair::new(); + let wrong_stake_program = Pubkey::new_unique(); let new_authority = Pubkey::new_unique(); - let mut transaction = Transaction::new_with_payer( - &[instruction::remove_validator_from_pool( - &id(), - &stake_pool_accounts.stake_pool.pubkey(), - &stake_pool_accounts.owner.pubkey(), - &stake_pool_accounts.withdraw_authority, - &new_authority, - &stake_pool_accounts.validator_list.pubkey(), - &user_stake.stake_account, - &user_pool_account.pubkey(), - &stake_pool_accounts.pool_mint.pubkey(), - &spl_token::id(), - &wrong_stake_program.pubkey(), - ) - .unwrap()], - Some(&payer.pubkey()), - ); + let accounts = vec![ + AccountMeta::new(stake_pool_accounts.stake_pool.pubkey(), false), + AccountMeta::new_readonly(stake_pool_accounts.owner.pubkey(), true), + AccountMeta::new_readonly(stake_pool_accounts.withdraw_authority, false), + AccountMeta::new_readonly(new_authority, false), + AccountMeta::new(stake_pool_accounts.validator_list.pubkey(), false), + AccountMeta::new(user_stake.stake_account, false), + AccountMeta::new(user_pool_account.pubkey(), false), + AccountMeta::new(stake_pool_accounts.pool_mint.pubkey(), false), + AccountMeta::new_readonly(sysvar::clock::id(), false), + AccountMeta::new_readonly(spl_token::id(), false), + AccountMeta::new_readonly(wrong_stake_program, false), + ]; + let instruction = Instruction { + program_id: id(), + accounts, + data: instruction::StakePoolInstruction::RemoveValidatorFromPool + .try_to_vec() + .unwrap(), + }; + + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); transaction.sign(&[&payer, &stake_pool_accounts.owner], recent_blockhash); let transaction_error = banks_client .process_transaction(transaction) @@ -230,7 +239,6 @@ async fn test_remove_validator_from_pool_with_wrong_token_program_id() { &user_pool_account.pubkey(), &stake_pool_accounts.pool_mint.pubkey(), &wrong_token_program.pubkey(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -277,7 +285,6 @@ async fn test_remove_validator_from_pool_with_wrong_pool_mint_account() { &user_pool_account.pubkey(), &wrong_pool_mint.pubkey(), &spl_token::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -328,7 +335,6 @@ async fn test_remove_validator_from_pool_with_wrong_validator_list_account() { &user_pool_account.pubkey(), &stake_pool_accounts.pool_mint.pubkey(), &spl_token::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -444,7 +450,6 @@ async fn test_not_owner_try_to_remove_validator_from_pool() { &user_pool_account.pubkey(), &stake_pool_accounts.pool_mint.pubkey(), &spl_token::id(), - &stake::id(), ) .unwrap()], Some(&payer.pubkey()), @@ -523,72 +528,6 @@ async fn test_not_owner_try_to_remove_validator_from_pool_without_signature() { } } -#[tokio::test] -async fn test_remove_validator_from_pool_when_stake_acc_not_in_stake_state() { - let (mut banks_client, payer, recent_blockhash) = program_test().start().await; - let stake_pool_accounts = StakePoolAccounts::new(); - stake_pool_accounts - .initialize_stake_pool(&mut banks_client, &payer, &recent_blockhash) - .await - .unwrap(); - - let user = Keypair::new(); - - let user_stake = ValidatorStakeAccount::new_with_target_authority( - &stake_pool_accounts.deposit_authority, - &stake_pool_accounts.stake_pool.pubkey(), - ); - let user_stake_authority = Keypair::new(); - create_validator_stake_account( - &mut banks_client, - &payer, - &recent_blockhash, - &user_stake.stake_pool, - &user_stake.stake_account, - &user_stake.vote.pubkey(), - &user_stake_authority.pubkey(), - &user_stake.target_authority, - ) - .await; - - let user_pool_account = Keypair::new(); - create_token_account( - &mut banks_client, - &payer, - &recent_blockhash, - &user_pool_account, - &stake_pool_accounts.pool_mint.pubkey(), - &user.pubkey(), - ) - .await - .unwrap(); - - let new_authority = Pubkey::new_unique(); - - let transaction_error = stake_pool_accounts - .remove_validator_from_pool( - &mut banks_client, - &payer, - &recent_blockhash, - &user_stake.stake_account, - &user_pool_account.pubkey(), - &new_authority, - ) - .await - .unwrap(); - - match transaction_error { - TransportError::TransactionError(TransactionError::InstructionError( - _, - InstructionError::Custom(error_index), - )) => { - let program_error = error::StakePoolError::WrongStakeState as u32; - assert_eq!(error_index, program_error); - } - _ => panic!("Wrong error occurs while try to add validator stake account when it isn't in stake state"), - } -} - #[tokio::test] async fn test_remove_validator_from_pool_from_unupdated_stake_pool() {} // TODO diff --git a/stake-pool/program/tests/withdraw.rs b/stake-pool/program/tests/withdraw.rs index c5e73777c98..ecb4e08a948 100644 --- a/stake-pool/program/tests/withdraw.rs +++ b/stake-pool/program/tests/withdraw.rs @@ -3,13 +3,16 @@ mod helpers; use { - borsh::BorshDeserialize, + borsh::{BorshDeserialize, BorshSerialize}, helpers::*, - solana_program::hash::Hash, - solana_program::pubkey::Pubkey, + solana_program::{ + hash::Hash, + instruction::{AccountMeta, Instruction, InstructionError}, + pubkey::Pubkey, + sysvar, + }, solana_program_test::*, solana_sdk::{ - instruction::InstructionError, signature::{Keypair, Signer}, transaction::{Transaction, TransactionError}, transport::TransportError, @@ -204,26 +207,30 @@ async fn test_stake_pool_withdraw_with_wrong_stake_program() { let user_stake_recipient = Keypair::new(); let new_authority = Pubkey::new_unique(); - let wrong_stake_program = Keypair::new(); + let wrong_stake_program = Pubkey::new_unique(); + + let accounts = vec![ + AccountMeta::new(stake_pool_accounts.stake_pool.pubkey(), false), + AccountMeta::new(stake_pool_accounts.validator_list.pubkey(), false), + AccountMeta::new_readonly(stake_pool_accounts.withdraw_authority, false), + AccountMeta::new(validator_stake_account.stake_account, false), + AccountMeta::new(user_stake_recipient.pubkey(), false), + AccountMeta::new_readonly(new_authority, false), + AccountMeta::new(deposit_info.user_pool_account, false), + AccountMeta::new(stake_pool_accounts.pool_mint.pubkey(), false), + AccountMeta::new_readonly(sysvar::clock::id(), false), + AccountMeta::new_readonly(spl_token::id(), false), + AccountMeta::new_readonly(wrong_stake_program, false), + ]; + let instruction = Instruction { + program_id: id(), + accounts, + data: instruction::StakePoolInstruction::Withdraw(tokens_to_burn) + .try_to_vec() + .unwrap(), + }; - let mut transaction = Transaction::new_with_payer( - &[instruction::withdraw( - &id(), - &stake_pool_accounts.stake_pool.pubkey(), - &stake_pool_accounts.validator_list.pubkey(), - &stake_pool_accounts.withdraw_authority, - &validator_stake_account.stake_account, - &user_stake_recipient.pubkey(), - &new_authority, - &deposit_info.user_pool_account, - &stake_pool_accounts.pool_mint.pubkey(), - &spl_token::id(), - &wrong_stake_program.pubkey(), - tokens_to_burn, - ) - .unwrap()], - Some(&payer.pubkey()), - ); + let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey())); transaction.sign(&[&payer], recent_blockhash); let transaction_error = banks_client .process_transaction(transaction) @@ -314,7 +321,6 @@ async fn test_stake_pool_withdraw_with_wrong_token_program_id() { &deposit_info.user_pool_account, &stake_pool_accounts.pool_mint.pubkey(), &wrong_token_program.pubkey(), - &stake::id(), tokens_to_burn, ) .unwrap()], @@ -383,7 +389,7 @@ async fn test_stake_pool_withdraw_with_wrong_validator_list() { } #[tokio::test] -async fn test_stake_pool_withdraw_when_stake_acc_not_in_stake_state() { +async fn test_stake_pool_withdraw_from_unknown_validator() { let (mut banks_client, payer, recent_blockhash) = program_test().start().await; let stake_pool_accounts = StakePoolAccounts::new(); stake_pool_accounts @@ -395,114 +401,13 @@ async fn test_stake_pool_withdraw_when_stake_acc_not_in_stake_state() { &stake_pool_accounts.deposit_authority, &stake_pool_accounts.stake_pool.pubkey(), ); - - let user_stake_authority = Keypair::new(); - create_validator_stake_account( - &mut banks_client, - &payer, - &recent_blockhash, - &validator_stake_account.stake_pool, - &validator_stake_account.stake_account, - &validator_stake_account.vote.pubkey(), - &user_stake_authority.pubkey(), - &validator_stake_account.target_authority, - ) - .await; - - let user = Keypair::new(); - // make stake account - let user_stake = Keypair::new(); - let lockup = stake::Lockup::default(); - let authorized = stake::Authorized { - staker: stake_pool_accounts.deposit_authority, - withdrawer: stake_pool_accounts.deposit_authority, - }; - create_independent_stake_account( - &mut banks_client, - &payer, - &recent_blockhash, - &user_stake, - &authorized, - &lockup, - ) - .await; - // make pool token account - let user_pool_account = Keypair::new(); - create_token_account( - &mut banks_client, - &payer, - &recent_blockhash, - &user_pool_account, - &stake_pool_accounts.pool_mint.pubkey(), - &user.pubkey(), - ) - .await - .unwrap(); - - let user_pool_account = user_pool_account.pubkey(); - let pool_tokens = get_token_balance(&mut banks_client, &user_pool_account).await; - - let tokens_to_burn = pool_tokens / 4; - - // Delegate tokens for burning - delegate_tokens( - &mut banks_client, - &payer, - &recent_blockhash, - &user_pool_account, - &user, - &stake_pool_accounts.withdraw_authority, - tokens_to_burn, - ) - .await; - - // Create stake account to withdraw to - let user_stake_recipient = Keypair::new(); - - let new_authority = Pubkey::new_unique(); - - let transaction_error = stake_pool_accounts - .withdraw_stake( + validator_stake_account + .create_and_delegate( &mut banks_client, &payer, &recent_blockhash, - &user_stake_recipient.pubkey(), - &user_pool_account, - &validator_stake_account.stake_account, - &new_authority, - tokens_to_burn, + &stake_pool_accounts.owner, ) - .await - .err() - .unwrap(); - - match transaction_error { - TransportError::TransactionError(TransactionError::InstructionError( - _, - InstructionError::Custom(error_index), - )) => { - let program_error = error::StakePoolError::WrongStakeState as u32; - assert_eq!(error_index, program_error); - } - _ => panic!("Wrong error occurs while try to withdraw when stake acc not in stake state"), - } -} - -#[tokio::test] -async fn test_stake_pool_withdraw_from_unknown_validator() { - let (mut banks_client, payer, recent_blockhash) = program_test().start().await; - let stake_pool_accounts = StakePoolAccounts::new(); - stake_pool_accounts - .initialize_stake_pool(&mut banks_client, &payer, &recent_blockhash) - .await - .unwrap(); - - let validator_stake_account = ValidatorStakeAccount::new_with_target_authority( - &stake_pool_accounts.deposit_authority, - &stake_pool_accounts.stake_pool.pubkey(), - ); - validator_stake_account - .create_and_delegate(&mut banks_client, &payer, &recent_blockhash) .await; let user_stake = ValidatorStakeAccount::new_with_target_authority( @@ -510,7 +415,12 @@ async fn test_stake_pool_withdraw_from_unknown_validator() { &stake_pool_accounts.stake_pool.pubkey(), ); user_stake - .create_and_delegate(&mut banks_client, &payer, &recent_blockhash) + .create_and_delegate( + &mut banks_client, + &payer, + &recent_blockhash, + &stake_pool_accounts.owner, + ) .await; let user_pool_account = Keypair::new();