stake: Remove `stake_allow_zero_undelegated_amount` usage (#32210)
This commit is contained in:
parent
9a620b4862
commit
383063eeb2
|
@ -77,13 +77,7 @@ declare_process_instruction!(
|
||||||
let mut me = get_stake_account()?;
|
let mut me = get_stake_account()?;
|
||||||
let rent =
|
let rent =
|
||||||
get_sysvar_with_account_check::rent(invoke_context, instruction_context, 1)?;
|
get_sysvar_with_account_check::rent(invoke_context, instruction_context, 1)?;
|
||||||
initialize(
|
initialize(&mut me, &authorized, &lockup, &rent)
|
||||||
&mut me,
|
|
||||||
&authorized,
|
|
||||||
&lockup,
|
|
||||||
&rent,
|
|
||||||
&invoke_context.feature_set,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Ok(StakeInstruction::Authorize(authorized_pubkey, stake_authorize)) => {
|
Ok(StakeInstruction::Authorize(authorized_pubkey, stake_authorize)) => {
|
||||||
let mut me = get_stake_account()?;
|
let mut me = get_stake_account()?;
|
||||||
|
@ -261,7 +255,6 @@ declare_process_instruction!(
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
&invoke_context.feature_set,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Ok(StakeInstruction::Deactivate) => {
|
Ok(StakeInstruction::Deactivate) => {
|
||||||
|
@ -302,13 +295,7 @@ declare_process_instruction!(
|
||||||
instruction_context,
|
instruction_context,
|
||||||
1,
|
1,
|
||||||
)?;
|
)?;
|
||||||
initialize(
|
initialize(&mut me, &authorized, &Lockup::default(), &rent)
|
||||||
&mut me,
|
|
||||||
&authorized,
|
|
||||||
&Lockup::default(),
|
|
||||||
&rent,
|
|
||||||
&invoke_context.feature_set,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Err(InstructionError::InvalidInstructionData)
|
Err(InstructionError::InvalidInstructionData)
|
||||||
}
|
}
|
||||||
|
@ -525,16 +512,6 @@ mod tests {
|
||||||
feature_set
|
feature_set
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The "old old" behavior is both before the stake minimum delegation was raised *and* before
|
|
||||||
/// undelegated stake accounts could have zero lamports beyond rent
|
|
||||||
fn feature_set_old_old_behavior() -> Arc<FeatureSet> {
|
|
||||||
let mut feature_set = feature_set_old_behavior();
|
|
||||||
Arc::get_mut(&mut feature_set)
|
|
||||||
.unwrap()
|
|
||||||
.deactivate(&feature_set::stake_allow_zero_undelegated_amount::id());
|
|
||||||
feature_set
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_default_account() -> AccountSharedData {
|
fn create_default_account() -> AccountSharedData {
|
||||||
AccountSharedData::new(0, 0, &Pubkey::new_unique())
|
AccountSharedData::new(0, 0, &Pubkey::new_unique())
|
||||||
}
|
}
|
||||||
|
@ -4470,17 +4447,9 @@ mod tests {
|
||||||
/// 3. Deactives the delegation
|
/// 3. Deactives the delegation
|
||||||
/// 4. Withdraws from the account such that the ending balance is *below* rent + minimum delegation
|
/// 4. Withdraws from the account such that the ending balance is *below* rent + minimum delegation
|
||||||
/// 5. Re-delegates, now with less than the minimum delegation, but it still succeeds
|
/// 5. Re-delegates, now with less than the minimum delegation, but it still succeeds
|
||||||
//
|
#[test]
|
||||||
// The "old old" behavior relies on `validate_delegated_amount()` *not* checking if the
|
fn test_behavior_withdrawal_then_redelegate_with_less_than_minimum_stake_delegation() {
|
||||||
// stake amount meets the minimum delegation. Once the
|
let feature_set = feature_set_new_behavior();
|
||||||
// `stake_allow_zero_undelegated_amount` feature is activated, `the expected_result`
|
|
||||||
// parameter can be removed and consolidated.
|
|
||||||
#[test_case(feature_set_old_old_behavior(), Ok(()); "old_old_behavior")]
|
|
||||||
#[test_case(feature_set_new_behavior(), Err(StakeError::InsufficientDelegation.into()); "new_behavior")]
|
|
||||||
fn test_behavior_withdrawal_then_redelegate_with_less_than_minimum_stake_delegation(
|
|
||||||
feature_set: Arc<FeatureSet>,
|
|
||||||
expected_result: Result<(), InstructionError>,
|
|
||||||
) {
|
|
||||||
let minimum_delegation = crate::get_minimum_delegation(&feature_set);
|
let minimum_delegation = crate::get_minimum_delegation(&feature_set);
|
||||||
let rent = Rent::default();
|
let rent = Rent::default();
|
||||||
let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of());
|
let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of());
|
||||||
|
@ -4641,7 +4610,7 @@ mod tests {
|
||||||
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
||||||
transaction_accounts,
|
transaction_accounts,
|
||||||
instruction_accounts,
|
instruction_accounts,
|
||||||
expected_result,
|
Err(StakeError::InsufficientDelegation.into()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@ use {
|
||||||
account_utils::StateMut,
|
account_utils::StateMut,
|
||||||
clock::{Clock, Epoch},
|
clock::{Clock, Epoch},
|
||||||
feature_set::{
|
feature_set::{
|
||||||
self, clean_up_delegation_errors, stake_allow_zero_undelegated_amount,
|
self, clean_up_delegation_errors, stake_merge_with_unmatched_credits_observed,
|
||||||
stake_merge_with_unmatched_credits_observed, stake_split_uses_rent_sysvar, FeatureSet,
|
stake_split_uses_rent_sysvar, FeatureSet,
|
||||||
},
|
},
|
||||||
instruction::{checked_add, InstructionError},
|
instruction::{checked_add, InstructionError},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
|
@ -464,22 +464,13 @@ pub fn initialize(
|
||||||
authorized: &Authorized,
|
authorized: &Authorized,
|
||||||
lockup: &Lockup,
|
lockup: &Lockup,
|
||||||
rent: &Rent,
|
rent: &Rent,
|
||||||
feature_set: &FeatureSet,
|
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
if stake_account.get_data().len() != StakeState::size_of() {
|
if stake_account.get_data().len() != StakeState::size_of() {
|
||||||
return Err(InstructionError::InvalidAccountData);
|
return Err(InstructionError::InvalidAccountData);
|
||||||
}
|
}
|
||||||
if let StakeState::Uninitialized = stake_account.get_state()? {
|
if let StakeState::Uninitialized = stake_account.get_state()? {
|
||||||
let rent_exempt_reserve = rent.minimum_balance(stake_account.get_data().len());
|
let rent_exempt_reserve = rent.minimum_balance(stake_account.get_data().len());
|
||||||
// when removing this feature, remove `minimum_balance` and just use `rent_exempt_reserve`
|
if stake_account.get_lamports() >= rent_exempt_reserve {
|
||||||
let minimum_balance = if feature_set.is_active(&stake_allow_zero_undelegated_amount::id()) {
|
|
||||||
rent_exempt_reserve
|
|
||||||
} else {
|
|
||||||
let minimum_delegation = crate::get_minimum_delegation(feature_set);
|
|
||||||
rent_exempt_reserve + minimum_delegation
|
|
||||||
};
|
|
||||||
|
|
||||||
if stake_account.get_lamports() >= minimum_balance {
|
|
||||||
stake_account.set_state(&StakeState::Initialized(Meta {
|
stake_account.set_state(&StakeState::Initialized(Meta {
|
||||||
rent_exempt_reserve,
|
rent_exempt_reserve,
|
||||||
authorized: *authorized,
|
authorized: *authorized,
|
||||||
|
@ -774,14 +765,6 @@ pub fn split(
|
||||||
}
|
}
|
||||||
StakeState::Initialized(meta) => {
|
StakeState::Initialized(meta) => {
|
||||||
meta.authorized.check(signers, StakeAuthorize::Staker)?;
|
meta.authorized.check(signers, StakeAuthorize::Staker)?;
|
||||||
let additional_required_lamports = if invoke_context
|
|
||||||
.feature_set
|
|
||||||
.is_active(&stake_allow_zero_undelegated_amount::id())
|
|
||||||
{
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
crate::get_minimum_delegation(&invoke_context.feature_set)
|
|
||||||
};
|
|
||||||
let validated_split_info = validate_split_amount(
|
let validated_split_info = validate_split_amount(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
transaction_context,
|
transaction_context,
|
||||||
|
@ -791,7 +774,7 @@ pub fn split(
|
||||||
lamports,
|
lamports,
|
||||||
&meta,
|
&meta,
|
||||||
None,
|
None,
|
||||||
additional_required_lamports,
|
0, // additional_required_lamports
|
||||||
)?;
|
)?;
|
||||||
let mut split_meta = meta;
|
let mut split_meta = meta;
|
||||||
split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
|
split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
|
||||||
|
@ -1026,7 +1009,6 @@ pub fn withdraw(
|
||||||
stake_history: &StakeHistory,
|
stake_history: &StakeHistory,
|
||||||
withdraw_authority_index: IndexOfAccount,
|
withdraw_authority_index: IndexOfAccount,
|
||||||
custodian_index: Option<IndexOfAccount>,
|
custodian_index: Option<IndexOfAccount>,
|
||||||
feature_set: &FeatureSet,
|
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let withdraw_authority_pubkey = transaction_context.get_key_of_account_at_index(
|
let withdraw_authority_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context
|
instruction_context
|
||||||
|
@ -1061,16 +1043,7 @@ pub fn withdraw(
|
||||||
meta.authorized
|
meta.authorized
|
||||||
.check(&signers, StakeAuthorize::Withdrawer)?;
|
.check(&signers, StakeAuthorize::Withdrawer)?;
|
||||||
// stake accounts must have a balance >= rent_exempt_reserve
|
// stake accounts must have a balance >= rent_exempt_reserve
|
||||||
let reserve = if feature_set.is_active(&stake_allow_zero_undelegated_amount::id()) {
|
(meta.lockup, meta.rent_exempt_reserve, false)
|
||||||
meta.rent_exempt_reserve
|
|
||||||
} else {
|
|
||||||
checked_add(
|
|
||||||
meta.rent_exempt_reserve,
|
|
||||||
crate::get_minimum_delegation(feature_set),
|
|
||||||
)?
|
|
||||||
};
|
|
||||||
|
|
||||||
(meta.lockup, reserve, false)
|
|
||||||
}
|
}
|
||||||
StakeState::Uninitialized => {
|
StakeState::Uninitialized => {
|
||||||
if !signers.contains(stake_account.get_key()) {
|
if !signers.contains(stake_account.get_key()) {
|
||||||
|
@ -1200,10 +1173,7 @@ fn validate_delegated_amount(
|
||||||
|
|
||||||
// Stake accounts may be initialized with a stake amount below the minimum delegation so check
|
// Stake accounts may be initialized with a stake amount below the minimum delegation so check
|
||||||
// that the minimum is met before delegation.
|
// that the minimum is met before delegation.
|
||||||
if (feature_set.is_active(&stake_allow_zero_undelegated_amount::id())
|
if stake_amount < crate::get_minimum_delegation(feature_set) {
|
||||||
|| feature_set.is_active(&feature_set::stake_raise_minimum_delegation_to_1_sol::id()))
|
|
||||||
&& stake_amount < crate::get_minimum_delegation(feature_set)
|
|
||||||
{
|
|
||||||
return Err(StakeError::InsufficientDelegation.into());
|
return Err(StakeError::InsufficientDelegation.into());
|
||||||
}
|
}
|
||||||
Ok(ValidatedDelegatedInfo { stake_amount })
|
Ok(ValidatedDelegatedInfo { stake_amount })
|
||||||
|
|
Loading…
Reference in New Issue