Skip to content

Commit d5542e7

Browse files
authored
Merge pull request #2 from ethan-hurst/fix-rewards-precision-bug-13667709943351071999
Fix rewards precision bug
2 parents b0eb178 + 57fce71 commit d5542e7

1 file changed

Lines changed: 38 additions & 1 deletion

File tree

  • programs/helix-staking/src/instructions

programs/helix-staking/src/instructions/math.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,12 @@ pub fn calculate_pending_rewards(
280280
// Saturating sub handles case where reward_debt > current_value (shouldn't happen but defensive)
281281
let pending_128 = current_value.saturating_sub(reward_debt as u128);
282282

283-
u64::try_from(pending_128).map_err(|_| error!(HelixError::Overflow))
283+
// FIXED: Divide by PRECISION to get unscaled token amount
284+
let pending_rewards = pending_128
285+
.checked_div(PRECISION as u128)
286+
.ok_or(error!(HelixError::Overflow))?;
287+
288+
u64::try_from(pending_rewards).map_err(|_| error!(HelixError::Overflow))
284289
}
285290

286291
/// Calculate reward_debt = t_shares × share_rate with overflow protection.
@@ -515,3 +520,35 @@ mod tests {
515520
assert!(overflow_result.is_err());
516521
}
517522
}
523+
524+
#[test]
525+
fn test_calculate_pending_rewards() {
526+
// PRECISION is 1_000_000_000
527+
let prec = PRECISION;
528+
529+
// Case 1: 1 share, rate increases by 1*PRECISION
530+
// t_shares = 1, rate_start = 0, rate_end = 1*PRECISION
531+
// This corresponds to 1 token distributed to 1 share
532+
// pending should be 1 token (unscaled)
533+
let pending = calculate_pending_rewards(1, prec, 0).unwrap();
534+
assert_eq!(pending, 1, "Should return unscaled token amount (1)");
535+
536+
// Case 2: 1 share, rate increases by 0.5 * PRECISION
537+
// pending should be 0 (0.5 rounds down)
538+
let pending_small = calculate_pending_rewards(1, prec / 2, 0).unwrap();
539+
assert_eq!(pending_small, 0, "Should round down small amounts");
540+
541+
// Case 3: Realistic scenario
542+
// t_shares = 1e12, rate increases by 100_000
543+
// rate_start = 10_000, rate_end = 110_000.
544+
// debt = 1e12 * 10_000 = 1e16.
545+
// current = 1e12 * 110_000 = 1.1e17.
546+
// diff = 1e17.
547+
// pending = 1e17 / 1e9 = 1e8 (100,000,000).
548+
let t_shares = 1_000_000_000_000u64;
549+
let rate_start = 10_000u64;
550+
let rate_end = 110_000u64;
551+
let debt = calculate_reward_debt(t_shares, rate_start).unwrap();
552+
let pending_large = calculate_pending_rewards(t_shares, rate_end, debt).unwrap();
553+
assert_eq!(pending_large, 100_000_000, "Should handle large numbers correctly");
554+
}

0 commit comments

Comments
 (0)