Skip to content

Commit 1efffbb

Browse files
committed
fix: ensure pool_liquidity < DEAD_LIQUIDITY before settling dead_liquidity_reward
1 parent efec2a5 commit 1efffbb

2 files changed

Lines changed: 22 additions & 18 deletions

File tree

‎programs/cp-amm/src/instructions/ix_fund_reward.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub fn handle_fund_reward(
7777
let mut pool = ctx.accounts.pool.load_mut()?;
7878
let current_time = Clock::get()?.unix_timestamp;
7979
let collect_fee_mode: CollectFeeMode = pool.collect_fee_mode.safe_cast()?;
80+
let pool_liquidity = pool.liquidity;
8081
// 1. update pool rewards
8182
pool.update_rewards(current_time as u64)?;
8283

@@ -98,7 +99,8 @@ pub fn handle_fund_reward(
9899
reward_info.cumulative_seconds_with_empty_liquidity_reward = 0;
99100

100101
// carry forward dead liquidity reward
101-
let dead_liquidity_reward = reward_info.settle_dead_liquidity_reward(collect_fee_mode)?;
102+
let dead_liquidity_reward =
103+
reward_info.settle_dead_liquidity_reward(pool_liquidity, collect_fee_mode)?;
102104

103105
transfer_fee_excluded_amount_in
104106
.safe_add(carry_forward_ineligible_reward)?

‎programs/cp-amm/src/state/pool.rs‎

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -319,25 +319,26 @@ impl RewardInfo {
319319
/// At that point the reward stops accruing. This is accepted to keep the dead_liquidity_reward_checkpoint at 8 bytes.
320320
pub fn settle_dead_liquidity_reward(
321321
&mut self,
322+
pool_liquidity: u128,
322323
collect_fee_mode: CollectFeeMode,
323324
) -> Result<u64> {
324-
if collect_fee_mode == CollectFeeMode::Compounding {
325-
// saturate on overflow
326-
let new_dead_liquidity_reward_checkpoint: u64 = safe_mul_shr_256_cast(
327-
U256::from(DEAD_LIQUIDITY),
328-
self.reward_per_token_stored(),
329-
TOTAL_REWARD_SCALE,
330-
)
331-
.unwrap_or(u64::MAX); // saturate to u64::MAX
332-
333-
let dead_liquidity_reward = new_dead_liquidity_reward_checkpoint
334-
.safe_sub(self.dead_liquidity_reward_checkpoint)?;
335-
self.dead_liquidity_reward_checkpoint = new_dead_liquidity_reward_checkpoint;
336-
337-
Ok(dead_liquidity_reward)
338-
} else {
339-
Ok(0)
325+
if collect_fee_mode != CollectFeeMode::Compounding || pool_liquidity < DEAD_LIQUIDITY {
326+
return Ok(0);
340327
}
328+
329+
// saturate on overflow
330+
let new_dead_liquidity_reward_checkpoint: u64 = safe_mul_shr_256_cast(
331+
U256::from(DEAD_LIQUIDITY),
332+
self.reward_per_token_stored(),
333+
TOTAL_REWARD_SCALE,
334+
)
335+
.unwrap_or(u64::MAX); // saturate to u64::MAX
336+
337+
let dead_liquidity_reward =
338+
new_dead_liquidity_reward_checkpoint.safe_sub(self.dead_liquidity_reward_checkpoint)?;
339+
self.dead_liquidity_reward_checkpoint = new_dead_liquidity_reward_checkpoint;
340+
341+
Ok(dead_liquidity_reward)
341342
}
342343

343344
pub fn get_seconds_elapsed_since_last_update(&self, current_time: u64) -> Result<u64> {
@@ -1113,7 +1114,8 @@ impl Pool {
11131114
REWARD_RATE_SCALE,
11141115
)?;
11151116

1116-
let dead_liquidity_reward = reward_info.settle_dead_liquidity_reward(collect_fee_mode)?;
1117+
let dead_liquidity_reward =
1118+
reward_info.settle_dead_liquidity_reward(self.liquidity, collect_fee_mode)?;
11171119

11181120
let ineligible_reward = empty_liquidity_reward.safe_add(dead_liquidity_reward)?;
11191121

0 commit comments

Comments
 (0)