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

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