Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stake-pool: Update program to work with minimum delegation #3127

Merged
merged 5 commits into from
May 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions stake-pool/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use {
find_withdraw_authority_program_address,
instruction::{FundingType, PreferredValidatorType},
state::{Fee, FeeType, StakePool, ValidatorList},
MINIMUM_ACTIVE_STAKE,
MINIMUM_ACTIVE_STAKE, MINIMUM_RESERVE_LAMPORTS,
},
std::cmp::Ordering,
std::{process::exit, sync::Arc},
Expand Down Expand Up @@ -250,7 +250,7 @@ fn command_create_pool(
let reserve_stake_balance = config
.rpc_client
.get_minimum_balance_for_rent_exemption(STAKE_STATE_LEN)?
+ 1;
+ MINIMUM_RESERVE_LAMPORTS;
let mint_account_balance = config
.rpc_client
.get_minimum_balance_for_rent_exemption(spl_token::state::Mint::LEN)?;
Expand Down Expand Up @@ -1058,7 +1058,7 @@ fn command_list(config: &Config, stake_pool_address: &Pubkey) -> CommandResult {
let minimum_reserve_stake_balance = config
.rpc_client
.get_minimum_balance_for_rent_exemption(STAKE_STATE_LEN)?
+ 1;
+ MINIMUM_RESERVE_LAMPORTS;
let cli_stake_pool_stake_account_infos = validator_list
.validators
.iter()
Expand Down Expand Up @@ -1271,7 +1271,7 @@ fn prepare_withdraw_accounts(
stake_pool.reserve_stake,
reserve_stake.lamports
- rpc_client.get_minimum_balance_for_rent_exemption(STAKE_STATE_LEN)?
- 1,
- MINIMUM_RESERVE_LAMPORTS,
None,
));

Expand Down
2 changes: 1 addition & 1 deletion stake-pool/js/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ export const TRANSIENT_STAKE_SEED_PREFIX = Buffer.from('transient');

// Minimum amount of staked SOL required in a validator stake account to allow
// for merges without a mismatch on credits observed
export const MINIMUM_ACTIVE_STAKE = LAMPORTS_PER_SOL / 1_000;
export const MINIMUM_ACTIVE_STAKE = LAMPORTS_PER_SOL;
10 changes: 6 additions & 4 deletions stake-pool/program/src/entrypoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

#![cfg(all(target_arch = "bpf", not(feature = "no-entrypoint")))]

use crate::{error::StakePoolError, processor::Processor};
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
program_error::PrintProgramError, pubkey::Pubkey,
use {
crate::{error::StakePoolError, processor::Processor},
solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
program_error::PrintProgramError, pubkey::Pubkey,
},
};

entrypoint!(process_instruction);
Expand Down
8 changes: 5 additions & 3 deletions stake-pool/program/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Error types

use num_derive::FromPrimitive;
use solana_program::{decode_error::DecodeError, program_error::ProgramError};
use thiserror::Error;
use {
num_derive::FromPrimitive,
solana_program::{decode_error::DecodeError, program_error::ProgramError},
thiserror::Error,
};

/// Errors that may be returned by the StakePool program.
#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
Expand Down
8 changes: 6 additions & 2 deletions stake-pool/program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ const TRANSIENT_STAKE_SEED_PREFIX: &[u8] = b"transient";

/// Minimum amount of staked SOL required in a validator stake account to allow
/// for merges without a mismatch on credits observed
pub const MINIMUM_ACTIVE_STAKE: u64 = LAMPORTS_PER_SOL / 1_000;
pub const MINIMUM_ACTIVE_STAKE: u64 = LAMPORTS_PER_SOL;

/// Minimum amount of SOL in the reserve
pub const MINIMUM_RESERVE_LAMPORTS: u64 = LAMPORTS_PER_SOL;

/// Maximum amount of validator stake accounts to update per
/// `UpdateValidatorListBalance` instruction, based on compute limits
Expand Down Expand Up @@ -64,7 +67,8 @@ pub fn minimum_stake_lamports(meta: &Meta) -> u64 {
/// conversions
#[inline]
pub fn minimum_reserve_lamports(meta: &Meta) -> u64 {
meta.rent_exempt_reserve.saturating_add(1)
meta.rent_exempt_reserve
.saturating_add(MINIMUM_RESERVE_LAMPORTS)
}

/// Generates the deposit authority program address for the stake pool
Expand Down
37 changes: 24 additions & 13 deletions stake-pool/program/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,14 @@ use {
borsh::{BorshDeserialize, BorshSerialize},
num_traits::FromPrimitive,
solana_program::{
account_info::next_account_info,
account_info::AccountInfo,
account_info::{next_account_info, AccountInfo},
borsh::try_from_slice_unchecked,
clock::{Clock, Epoch},
decode_error::DecodeError,
entrypoint::ProgramResult,
msg,
program::{invoke, invoke_signed},
program_error::PrintProgramError,
program_error::ProgramError,
program_error::{PrintProgramError, ProgramError},
program_pack::Pack,
pubkey::Pubkey,
rent::Rent,
Expand Down Expand Up @@ -136,6 +134,17 @@ fn check_account_owner(
}
}

/// Checks if a stake acount can be managed by the pool
fn stake_is_usable_by_pool(
meta: &stake::state::Meta,
expected_authority: &Pubkey,
expected_lockup: &stake::state::Lockup,
) -> bool {
meta.authorized.staker == *expected_authority
&& meta.authorized.withdrawer == *expected_authority
&& meta.lockup == *expected_lockup
}

/// Create a transient stake account without transferring lamports
fn create_transient_stake_account<'a>(
transient_stake_account_info: AccountInfo<'a>,
Expand Down Expand Up @@ -747,7 +756,7 @@ impl Processor {
stake_pool.manager_fee_account = *manager_fee_info.key;
stake_pool.token_program_id = *token_program_info.key;
stake_pool.total_lamports = total_lamports;
stake_pool.pool_token_supply = 0;
stake_pool.pool_token_supply = total_lamports;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests uncovered this little oopsie!

stake_pool.last_update_epoch = Clock::get()?.epoch;
stake_pool.lockup = stake::state::Lockup::default();
stake_pool.epoch_fee = epoch_fee;
Expand Down Expand Up @@ -1543,10 +1552,11 @@ impl Processor {
// * not a stake -> ignore
match transient_stake_state {
Some(stake::state::StakeState::Initialized(meta)) => {
// if transient account was hijacked, ignore it
if meta.authorized.staker == *withdraw_authority_info.key
&& meta.authorized.withdrawer == *withdraw_authority_info.key
{
if stake_is_usable_by_pool(
&meta,
withdraw_authority_info.key,
&stake_pool.lockup,
) {
if no_merge {
transient_stake_lamports = transient_stake_info.lamports();
} else {
Expand All @@ -1571,10 +1581,11 @@ impl Processor {
}
}
Some(stake::state::StakeState::Stake(meta, stake)) => {
// if transient account was hijacked, ignore it
if meta.authorized.staker == *withdraw_authority_info.key
&& meta.authorized.withdrawer == *withdraw_authority_info.key
{
if stake_is_usable_by_pool(
&meta,
withdraw_authority_info.key,
&stake_pool.lockup,
) {
let account_stake = meta
.rent_exempt_reserve
.saturating_add(stake.delegation.stake);
Expand Down
8 changes: 3 additions & 5 deletions stake-pool/program/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! State transition types

use spl_token::state::{Account, AccountState};
use {
crate::{
big_vec::BigVec, error::StakePoolError, MAX_WITHDRAWAL_FEE_INCREASE,
Expand All @@ -20,6 +19,7 @@ use {
stake::state::Lockup,
},
spl_math::checked_ceil_div::CheckedCeilDiv,
spl_token::state::{Account, AccountState},
std::{convert::TryFrom, fmt, matches},
};

Expand Down Expand Up @@ -535,7 +535,7 @@ impl Default for StakeStatus {
pub struct ValidatorStakeInfo {
/// Amount of active stake delegated to this validator, minus the minimum
/// required stake amount of rent-exemption + `crate::MINIMUM_ACTIVE_STAKE`
/// (currently 0.001 SOL).
/// (currently 1 SOL).
///
/// Note that if `last_update_epoch` does not match the current epoch then
/// this field may not be accurate
Expand Down Expand Up @@ -823,10 +823,8 @@ mod test {
use {
super::*,
proptest::prelude::*,
solana_program::borsh::{
get_instance_packed_len, get_packed_len, try_from_slice_unchecked,
},
solana_program::{
borsh::{get_instance_packed_len, get_packed_len, try_from_slice_unchecked},
clock::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_S_PER_SLOT, SECONDS_PER_DAY},
native_token::LAMPORTS_PER_SOL,
},
Expand Down
20 changes: 14 additions & 6 deletions stake-pool/program/tests/decrease.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use {
},
spl_stake_pool::{
error::StakePoolError, find_transient_stake_program_address, id, instruction,
MINIMUM_ACTIVE_STAKE, MINIMUM_RESERVE_LAMPORTS,
},
};

Expand All @@ -28,9 +29,16 @@ async fn setup() -> (
u64,
) {
let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
let rent = banks_client.get_rent().await.unwrap();
let stake_rent = rent.minimum_balance(std::mem::size_of::<stake::state::StakeState>());
let stake_pool_accounts = StakePoolAccounts::new();
stake_pool_accounts
.initialize_stake_pool(&mut banks_client, &payer, &recent_blockhash, 1)
.initialize_stake_pool(
&mut banks_client,
&payer,
&recent_blockhash,
MINIMUM_RESERVE_LAMPORTS,
)
.await
.unwrap();

Expand All @@ -48,12 +56,12 @@ async fn setup() -> (
&recent_blockhash,
&stake_pool_accounts,
&validator_stake_account,
100_000_000,
MINIMUM_ACTIVE_STAKE * 2 + stake_rent,
)
.await
.unwrap();

let lamports = deposit_info.stake_lamports / 2;
let decrease_lamports = MINIMUM_ACTIVE_STAKE + stake_rent;

(
banks_client,
Expand All @@ -62,7 +70,7 @@ async fn setup() -> (
stake_pool_accounts,
validator_stake_account,
deposit_info,
lamports,
decrease_lamports,
)
}

Expand Down Expand Up @@ -297,7 +305,7 @@ async fn fail_decrease_twice() {
&recent_blockhash,
&validator_stake.stake_account,
&validator_stake.transient_stake_account,
decrease_lamports / 3,
decrease_lamports,
validator_stake.transient_stake_seed,
)
.await;
Expand All @@ -318,7 +326,7 @@ async fn fail_decrease_twice() {
&recent_blockhash,
&validator_stake.stake_account,
&transient_stake_address,
decrease_lamports / 2,
decrease_lamports,
transient_stake_seed,
)
.await
Expand Down
17 changes: 12 additions & 5 deletions stake-pool/program/tests/deposit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ use {
solana_program_test::*,
solana_sdk::{
signature::{Keypair, Signer},
transaction::Transaction,
transaction::TransactionError,
transaction::{Transaction, TransactionError},
transport::TransportError,
},
spl_stake_pool::{error::StakePoolError, id, instruction, minimum_stake_lamports, state},
spl_stake_pool::{
error::StakePoolError, id, instruction, minimum_stake_lamports, state,
MINIMUM_RESERVE_LAMPORTS,
},
spl_token::error as token_error,
};

Expand All @@ -40,7 +42,7 @@ async fn setup() -> (
&mut context.banks_client,
&context.payer,
&context.last_blockhash,
1,
MINIMUM_RESERVE_LAMPORTS,
)
.await
.unwrap();
Expand Down Expand Up @@ -616,7 +618,12 @@ async fn fail_with_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, 1)
.initialize_stake_pool(
&mut banks_client,
&payer,
&recent_blockhash,
MINIMUM_RESERVE_LAMPORTS,
)
.await
.unwrap();

Expand Down
23 changes: 19 additions & 4 deletions stake-pool/program/tests/deposit_authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use {
signature::{Keypair, Signer},
transaction::TransactionError,
},
spl_stake_pool::{error::StakePoolError, state::StakePool},
spl_stake_pool::{error::StakePoolError, state::StakePool, MINIMUM_RESERVE_LAMPORTS},
};

#[tokio::test]
Expand All @@ -21,7 +21,12 @@ async fn success_initialize() {
let stake_pool_accounts = StakePoolAccounts::new_with_deposit_authority(deposit_authority);
let deposit_authority = stake_pool_accounts.stake_deposit_authority;
stake_pool_accounts
.initialize_stake_pool(&mut banks_client, &payer, &recent_blockhash, 1)
.initialize_stake_pool(
&mut banks_client,
&payer,
&recent_blockhash,
MINIMUM_RESERVE_LAMPORTS,
)
.await
.unwrap();

Expand All @@ -41,7 +46,12 @@ async fn success_deposit() {
let stake_pool_accounts =
StakePoolAccounts::new_with_deposit_authority(stake_deposit_authority);
stake_pool_accounts
.initialize_stake_pool(&mut banks_client, &payer, &recent_blockhash, 1)
.initialize_stake_pool(
&mut banks_client,
&payer,
&recent_blockhash,
MINIMUM_RESERVE_LAMPORTS,
)
.await
.unwrap();

Expand Down Expand Up @@ -116,7 +126,12 @@ async fn fail_deposit_without_authority_signature() {
let mut stake_pool_accounts =
StakePoolAccounts::new_with_deposit_authority(stake_deposit_authority);
stake_pool_accounts
.initialize_stake_pool(&mut banks_client, &payer, &recent_blockhash, 1)
.initialize_stake_pool(
&mut banks_client,
&payer,
&recent_blockhash,
MINIMUM_RESERVE_LAMPORTS,
)
.await
.unwrap();

Expand Down
Loading