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

Commit 11df4aa

Browse files
Atticlab LLCysavchenko
andauthored
Various postponed fixes and changes to the stake pool program (#1200)
* Various postponed fixes and changes to the stake pool program * Fixed PR comments * Fixed no-signature validator stake account add test Co-authored-by: Yuriy Savchenko <[email protected]>
1 parent beb4aa7 commit 11df4aa

File tree

15 files changed

+1069
-323
lines changed

15 files changed

+1069
-323
lines changed

stake-pool/cli/src/main.rs

Lines changed: 21 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ use spl_stake_pool::{
3939
stake::StakeAuthorize,
4040
stake::StakeState,
4141
state::StakePool,
42-
state::State as PoolState,
4342
state::ValidatorStakeList,
4443
};
4544
use spl_token::{
@@ -148,7 +147,7 @@ fn command_create_pool(config: &Config, fee: PoolFee) -> CommandResult {
148147
.get_minimum_balance_for_rent_exemption(TokenAccount::LEN)?;
149148
let pool_account_balance = config
150149
.rpc_client
151-
.get_minimum_balance_for_rent_exemption(PoolState::LEN)?;
150+
.get_minimum_balance_for_rent_exemption(StakePool::LEN)?;
152151
let validator_stake_list_balance = config
153152
.rpc_client
154153
.get_minimum_balance_for_rent_exemption(ValidatorStakeList::LEN)?;
@@ -193,7 +192,7 @@ fn command_create_pool(config: &Config, fee: PoolFee) -> CommandResult {
193192
&config.fee_payer.pubkey(),
194193
&pool_account.pubkey(),
195194
pool_account_balance,
196-
PoolState::LEN as u64,
195+
StakePool::LEN as u64,
197196
&spl_stake_pool::id(),
198197
),
199198
// Validator stake account list storage
@@ -245,6 +244,7 @@ fn command_create_pool(config: &Config, fee: PoolFee) -> CommandResult {
245244
&validator_stake_list,
246245
&mint_account,
247246
&pool_fee_account,
247+
config.owner.as_ref(),
248248
];
249249
unique_signers!(signers);
250250
transaction.sign(&signers, recent_blockhash);
@@ -289,10 +289,7 @@ fn command_vsa_add(
289289
) -> CommandResult {
290290
// Get stake pool state
291291
let pool_data = config.rpc_client.get_account_data(&pool)?;
292-
let pool_data: StakePool = PoolState::deserialize(pool_data.as_slice())
293-
.unwrap()
294-
.stake_pool()
295-
.unwrap();
292+
let pool_data: StakePool = StakePool::deserialize(pool_data.as_slice()).unwrap();
296293

297294
let mut total_rent_free_balances: u64 = 0;
298295

@@ -383,10 +380,7 @@ fn command_vsa_remove(
383380
) -> CommandResult {
384381
// Get stake pool state
385382
let pool_data = config.rpc_client.get_account_data(&pool)?;
386-
let pool_data: StakePool = PoolState::deserialize(pool_data.as_slice())
387-
.unwrap()
388-
.stake_pool()
389-
.unwrap();
383+
let pool_data: StakePool = StakePool::deserialize(pool_data.as_slice()).unwrap();
390384

391385
let pool_withdraw_authority: Pubkey = PoolProcessor::authority_id(
392386
&spl_stake_pool::id(),
@@ -512,10 +506,7 @@ fn command_deposit(
512506
) -> CommandResult {
513507
// Get stake pool state
514508
let pool_data = config.rpc_client.get_account_data(&pool)?;
515-
let pool_data: StakePool = PoolState::deserialize(pool_data.as_slice())
516-
.unwrap()
517-
.stake_pool()
518-
.unwrap();
509+
let pool_data: StakePool = StakePool::deserialize(pool_data.as_slice()).unwrap();
519510

520511
// Get stake account data
521512
let stake_data = config.rpc_client.get_account_data(&stake)?;
@@ -624,10 +615,7 @@ fn command_deposit(
624615
fn command_list(config: &Config, pool: &Pubkey) -> CommandResult {
625616
// Get stake pool state
626617
let pool_data = config.rpc_client.get_account_data(&pool)?;
627-
let pool_data: StakePool = PoolState::deserialize(pool_data.as_slice())
628-
.unwrap()
629-
.stake_pool()
630-
.unwrap();
618+
let pool_data: StakePool = StakePool::deserialize(pool_data.as_slice()).unwrap();
631619

632620
let pool_withdraw_authority: Pubkey = PoolProcessor::authority_id(
633621
&spl_stake_pool::id(),
@@ -657,10 +645,7 @@ fn command_list(config: &Config, pool: &Pubkey) -> CommandResult {
657645
fn command_update(config: &Config, pool: &Pubkey) -> CommandResult {
658646
// Get stake pool state
659647
let pool_data = config.rpc_client.get_account_data(&pool)?;
660-
let pool_data: StakePool = PoolState::deserialize(pool_data.as_slice())
661-
.unwrap()
662-
.stake_pool()
663-
.unwrap();
648+
let pool_data: StakePool = StakePool::deserialize(pool_data.as_slice()).unwrap();
664649
let validator_stake_list_data = config
665650
.rpc_client
666651
.get_account_data(&pool_data.validator_stake_list)?;
@@ -804,10 +789,7 @@ fn command_withdraw(
804789
) -> CommandResult {
805790
// Get stake pool state
806791
let pool_data = config.rpc_client.get_account_data(&pool)?;
807-
let pool_data: StakePool = PoolState::deserialize(pool_data.as_slice())
808-
.unwrap()
809-
.stake_pool()
810-
.unwrap();
792+
let pool_data: StakePool = StakePool::deserialize(pool_data.as_slice()).unwrap();
811793

812794
let pool_withdraw_authority: Pubkey = PoolProcessor::authority_id(
813795
&spl_stake_pool::id(),
@@ -827,19 +809,21 @@ fn command_withdraw(
827809
}
828810

829811
// Check burn_from balance
830-
let max_withdraw_amount = pool_tokens_to_stake_amount(&pool_data, account_data.amount);
831-
if max_withdraw_amount < amount {
812+
if account_data.amount < amount {
832813
return Err(format!(
833-
"Not enough token balance to withdraw {} SOL.\nMaximum withdraw amount is {} SOL.",
814+
"Not enough token balance to withdraw {} pool tokens.\nMaximum withdraw amount is {} pool tokens.",
834815
lamports_to_sol(amount),
835-
lamports_to_sol(max_withdraw_amount)
816+
lamports_to_sol(account_data.amount)
836817
)
837818
.into());
838819
}
839820

821+
// Convert pool tokens amount to lamports
822+
let sol_withdraw_amount = pool_tokens_to_stake_amount(&pool_data, amount);
823+
840824
// Get the list of accounts to withdraw from
841825
let withdraw_from: Vec<WithdrawAccount> =
842-
prepare_withdraw_accounts(config, &pool_withdraw_authority, amount)?;
826+
prepare_withdraw_accounts(config, &pool_withdraw_authority, sol_withdraw_amount)?;
843827

844828
// Construct transaction to withdraw from withdraw_from account list
845829
let mut instructions: Vec<Instruction> = vec![];
@@ -848,9 +832,6 @@ fn command_withdraw(
848832

849833
let mut total_rent_free_balances: u64 = 0;
850834

851-
// Calculate amount of tokens to burn
852-
let tokens_to_burn = stake_amount_to_pool_tokens(&pool_data, amount);
853-
854835
instructions.push(
855836
// Approve spending token
856837
approve_token(
@@ -859,7 +840,7 @@ fn command_withdraw(
859840
&pool_withdraw_authority,
860841
&config.owner.pubkey(),
861842
&[],
862-
tokens_to_burn,
843+
amount,
863844
)?,
864845
);
865846

@@ -940,10 +921,7 @@ fn command_set_staking_auth(
940921
new_staker: &Pubkey,
941922
) -> CommandResult {
942923
let pool_data = config.rpc_client.get_account_data(&pool)?;
943-
let pool_data: StakePool = PoolState::deserialize(pool_data.as_slice())
944-
.unwrap()
945-
.stake_pool()
946-
.unwrap();
924+
let pool_data: StakePool = StakePool::deserialize(pool_data.as_slice()).unwrap();
947925

948926
let pool_withdraw_authority: Pubkey = PoolProcessor::authority_id(
949927
&spl_stake_pool::id(),
@@ -981,10 +959,7 @@ fn command_set_owner(
981959
new_fee_receiver: &Option<Pubkey>,
982960
) -> CommandResult {
983961
let pool_data = config.rpc_client.get_account_data(&pool)?;
984-
let pool_data: StakePool = PoolState::deserialize(pool_data.as_slice())
985-
.unwrap()
986-
.stake_pool()
987-
.unwrap();
962+
let pool_data: StakePool = StakePool::deserialize(pool_data.as_slice()).unwrap();
988963

989964
// If new accounts are missing in the arguments use the old ones
990965
let new_owner: Pubkey = match new_owner {
@@ -1264,7 +1239,7 @@ fn main() {
12641239
.value_name("AMOUNT")
12651240
.takes_value(true)
12661241
.required(true)
1267-
.help("Amount in SOL to withdraw from the pool."),
1242+
.help("Amount of pool tokens to burn and get rewards."),
12681243
)
12691244
.arg(
12701245
Arg::with_name("burn_from")
@@ -1444,6 +1419,7 @@ fn main() {
14441419
("withdraw", Some(arg_matches)) => {
14451420
let pool_account: Pubkey = pubkey_of(arg_matches, "pool").unwrap();
14461421
let burn_from: Pubkey = pubkey_of(arg_matches, "burn_from").unwrap();
1422+
// convert from float to int, using sol_to_lamports because they have the same precision as SOL
14471423
let amount: u64 = sol_to_lamports(value_t_or_exit!(arg_matches, "amount", f64));
14481424
let stake_receiver: Option<Pubkey> = pubkey_of(arg_matches, "stake_receiver");
14491425
command_withdraw(&config, &pool_account, amount, &burn_from, &stake_receiver)

stake-pool/program/src/error.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub enum StakePoolError {
1313
/// The program address provided doesn't match the value generated by the program.
1414
#[error("InvalidProgramAddress")]
1515
InvalidProgramAddress,
16-
/// The token swap state is invalid.
16+
/// The stake pool state is invalid.
1717
#[error("InvalidState")]
1818
InvalidState,
1919
/// The calculation failed.
@@ -46,6 +46,9 @@ pub enum StakePoolError {
4646
/// Stake account is not in the state expected by the program.
4747
#[error("WrongStakeState")]
4848
WrongStakeState,
49+
/// User stake is not active
50+
#[error("UserStakeNotActive")]
51+
UserStakeNotActive,
4952
/// Stake account voting for this validator already exists in the pool.
5053
#[error("ValidatorAlreadyAdded")]
5154
ValidatorAlreadyAdded,
@@ -58,12 +61,18 @@ pub enum StakePoolError {
5861
/// Identify validator stake accounts with old balances and update them.
5962
#[error("StakeListOutOfDate")]
6063
StakeListOutOfDate,
61-
/// First udpate old validator stake account balances and then pool stake balance.
64+
/// First update old validator stake account balances and then pool stake balance.
6265
#[error("StakeListAndPoolOutOfDate")]
6366
StakeListAndPoolOutOfDate,
6467
/// Validator stake account is not found in the list storage.
6568
#[error("UnknownValidatorStakeAccount")]
6669
UnknownValidatorStakeAccount,
70+
/// Wrong minting authority set for mint pool account
71+
#[error("WrongMintingAuthority")]
72+
WrongMintingAuthority,
73+
/// Account is not rent-exempt
74+
#[error("AccountNotRentExempt")]
75+
AccountNotRentExempt,
6776
}
6877
impl From<StakePoolError> for ProgramError {
6978
fn from(e: StakePoolError) -> Self {

stake-pool/program/src/instruction.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ pub enum StakePoolInstruction {
3535
/// Initializes a new StakePool.
3636
///
3737
/// 0. `[w]` New StakePool to create.
38-
/// 1. `[]` Owner
38+
/// 1. `[s]` Owner
3939
/// 2. `[w]` Uninitialized validator stake list storage account
4040
/// 3. `[]` pool token Mint. Must be non zero, owned by withdraw authority.
4141
/// 4. `[]` Pool Account to deposit the generated fee for owner.
42-
/// 5. `[]` Token program id
42+
/// 5. `[]` Clock sysvar
43+
/// 6. `[]` Rent sysvar
44+
/// 7. `[]` Token program id
4345
Initialize(InitArgs),
4446

4547
/// Creates new program account for accumulating stakes for a particular validator
@@ -66,8 +68,9 @@ pub enum StakePoolInstruction {
6668
/// 6. `[w]` User account to receive pool tokens
6769
/// 7. `[w]` Pool token mint account
6870
/// 8. `[]` Clock sysvar (required)
69-
/// 9. `[]` Pool token program id,
70-
/// 10. `[]` Stake program id,
71+
/// 9. '[]' Sysvar stake history account
72+
/// 10. `[]` Pool token program id,
73+
/// 11. `[]` Stake program id,
7174
AddValidatorStakeAccount,
7275

7376
/// Removes validator stake account from the pool
@@ -253,11 +256,12 @@ pub fn initialize(
253256
let data = init_data.serialize()?;
254257
let accounts = vec![
255258
AccountMeta::new(*stake_pool, true),
256-
AccountMeta::new_readonly(*owner, false),
259+
AccountMeta::new_readonly(*owner, true),
257260
AccountMeta::new(*validator_stake_list, false),
258261
AccountMeta::new_readonly(*pool_mint, false),
259262
AccountMeta::new_readonly(*owner_pool_account, false),
260263
AccountMeta::new_readonly(sysvar::clock::id(), false),
264+
AccountMeta::new_readonly(sysvar::rent::id(), false),
261265
AccountMeta::new_readonly(*token_program_id, false),
262266
];
263267
Ok(Instruction {
@@ -321,6 +325,7 @@ pub fn add_validator_stake_account(
321325
AccountMeta::new(*pool_tokens_to, false),
322326
AccountMeta::new(*pool_mint, false),
323327
AccountMeta::new_readonly(sysvar::clock::id(), false),
328+
AccountMeta::new_readonly(sysvar::stake_history::id(), false),
324329
AccountMeta::new_readonly(*token_program_id, false),
325330
AccountMeta::new_readonly(*stake_program_id, false),
326331
];

0 commit comments

Comments
 (0)