Prevent splitting when either source or split stake will equal zero (#13775)

This commit is contained in:
Tyera Eulberg 2020-11-23 19:48:56 -07:00 committed by GitHub
parent 60ce6f1a9b
commit e3a92d6905
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 24 additions and 16 deletions

View File

@ -964,9 +964,13 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
if lamports < split_rent_exempt_reserve.saturating_sub(split.lamports()?)
// verify full withdrawal can cover rent in new split account
|| (lamports < split_rent_exempt_reserve && lamports == self.lamports()?)
// verify enough lamports left in previous stake and not full withdrawal
|| (lamports + meta.rent_exempt_reserve > self.lamports()?
&& lamports != self.lamports()?)
// if not full withdrawal
|| (lamports != self.lamports()?
// verify more than 0 stake left in previous stake
&& (lamports + meta.rent_exempt_reserve >= self.lamports()?
// and verify more than 0 stake in new split account
|| lamports
<= split_rent_exempt_reserve.saturating_sub(split.lamports()?)))
{
return Err(InstructionError::InsufficientFunds);
}
@ -1019,9 +1023,13 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
// enough lamports for rent in new stake
if lamports < split_rent_exempt_reserve
// verify enough lamports left in previous stake
|| (lamports + meta.rent_exempt_reserve > self.lamports()?
&& lamports != self.lamports()?)
// if not full withdrawal
|| (lamports != self.lamports()?
// verify more than 0 stake left in previous stake
&& (lamports + meta.rent_exempt_reserve >= self.lamports()?
// and verify more than 0 stake in new split account
|| lamports
<= split_rent_exempt_reserve.saturating_sub(split.lamports()?)))
{
return Err(InstructionError::InsufficientFunds);
}
@ -3698,20 +3706,20 @@ mod tests {
let split_stake_keyed_account =
KeyedAccount::new(&split_stake_pubkey, true, &split_stake_account);
// not enough to make a stake account
// not enough to make a non-zero stake account
assert_eq!(
stake_keyed_account.split(
rent_exempt_reserve - 1,
rent_exempt_reserve,
&split_stake_keyed_account,
&signers
),
Err(InstructionError::InsufficientFunds)
);
// doesn't leave enough for initial stake
// doesn't leave enough for initial stake to be non-zero
assert_eq!(
stake_keyed_account.split(
(stake_lamports - rent_exempt_reserve) + 1,
stake_lamports - rent_exempt_reserve,
&split_stake_keyed_account,
&signers
),
@ -3722,7 +3730,7 @@ mod tests {
split_stake_keyed_account.account.borrow_mut().lamports = 10_000_000;
assert_eq!(
stake_keyed_account.split(
stake_lamports - rent_exempt_reserve, // leave rent_exempt_reserve in original account
stake_lamports - (rent_exempt_reserve + 1), // leave rent_exempt_reserve + 1 in original account
&split_stake_keyed_account,
&signers
),
@ -3737,7 +3745,7 @@ mod tests {
*meta,
Stake {
delegation: Delegation {
stake: stake_lamports - rent_exempt_reserve,
stake: stake_lamports - rent_exempt_reserve - 1,
..stake.delegation
},
..*stake
@ -3746,11 +3754,11 @@ mod tests {
);
assert_eq!(
stake_keyed_account.account.borrow().lamports,
rent_exempt_reserve
rent_exempt_reserve + 1
);
assert_eq!(
split_stake_keyed_account.account.borrow().lamports,
10_000_000 + stake_lamports - rent_exempt_reserve
10_000_000 + stake_lamports - rent_exempt_reserve - 1
);
}
}
@ -4126,7 +4134,7 @@ mod tests {
std::mem::size_of::<StakeState>() as u64 + 100,
);
let stake_lamports = expected_rent_exempt_reserve + 1;
let split_amount = stake_lamports - rent_exempt_reserve;
let split_amount = stake_lamports - (rent_exempt_reserve + 1); // Enough so that split stake is > 0
let state = StakeState::Stake(
meta,