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

Commit 0d8a248

Browse files
authored
stake-pool: Fix zero withdraw calculation (#2251)
1 parent 7c89855 commit 0d8a248

File tree

1 file changed

+25
-4
lines changed

1 file changed

+25
-4
lines changed

stake-pool/program/src/state.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,17 @@ impl StakePool {
136136

137137
/// calculate lamports amount on withdrawal
138138
pub fn calc_lamports_withdraw_amount(&self, pool_tokens: u64) -> Option<u64> {
139-
let (quotient, _) = (pool_tokens as u128)
140-
.checked_mul(self.total_stake_lamports as u128)?
141-
.checked_ceil_div(self.pool_token_supply as u128)?;
142-
u64::try_from(quotient).ok()
139+
// `checked_ceil_div` returns `None` for a 0 quotient result, but in this
140+
// case, a return of 0 is valid for small amounts of pool tokens. So
141+
// we check for that separately
142+
let numerator = (pool_tokens as u128).checked_mul(self.total_stake_lamports as u128)?;
143+
let denominator = self.pool_token_supply as u128;
144+
if numerator < denominator || denominator == 0 {
145+
Some(0)
146+
} else {
147+
let (quotient, _) = numerator.checked_ceil_div(denominator)?;
148+
u64::try_from(quotient).ok()
149+
}
143150
}
144151

145152
/// calculate pool tokens to be deducted as withdrawal fees
@@ -783,6 +790,20 @@ mod test {
783790
assert_eq!(fee_lamports, LAMPORTS_PER_SOL);
784791
}
785792

793+
#[test]
794+
fn zero_withdraw_calculation() {
795+
let fee = Fee {
796+
numerator: 0,
797+
denominator: 1,
798+
};
799+
let stake_pool = StakePool {
800+
fee,
801+
..StakePool::default()
802+
};
803+
let fee_lamports = stake_pool.calc_lamports_withdraw_amount(0).unwrap();
804+
assert_eq!(fee_lamports, 0);
805+
}
806+
786807
#[test]
787808
fn divide_by_zero_fee() {
788809
let stake_pool = StakePool {

0 commit comments

Comments
 (0)