Background
liquidity.rs::calculate_lp_rewards computes rewards purely as a function of a provider's share of total_liquidity squared, with no relation to fees actually collected by the pool and no consideration of how long a position has been held:
/// # Note
/// This is a simplified proportional reward model. In production, rewards
/// should also factor in time-in-pool and accumulated fee revenue.
///
/// # TODO
/// - Integrate actual fee revenue collected by the pool so LP rewards
/// reflect real earnings rather than a synthetic proportional amount.
/// - Add time-weighting: providers who stay longer earn a multiplier.
fn calculate_lp_rewards(_env: &Env, position: &LPPosition, total_liquidity: i128) -> i128 {
...
}
The module-level doc comment flags the same gap independently:
//! # TODO
//! - Implement time-weighted LP rewards so long-term providers earn more than
//! flash liquidity providers.
In the current implementation, a "flash" liquidity provider that deposits right before a reward calculation and withdraws immediately after earns identical rewards to a long-term provider with the same position size — there's no economic disincentive for this, and rewards aren't backed by real fee income, which means the reward pool's payout isn't tied to actual protocol revenue.
Implementation Plan
- Track accumulated fee revenue per pool (or per position) so
calculate_lp_rewards draws from real fees collected rather than a synthetic formula.
- Add a time-in-pool multiplier to
LPPosition (e.g., track deposit timestamp, apply a scaling factor based on duration held) so long-term providers are rewarded more than flash liquidity.
- Add tests comparing rewards for a short-duration vs. long-duration position of equal size, and confirming rewards stay bounded by actual collected fees.
Acceptance Criteria
- LP rewards are derived from real fee revenue, not a purely proportional synthetic formula
- Positions held longer earn proportionally more than equally-sized flash positions
- Tests cover both the fee-revenue basis and the time-weighting behavior
Background
liquidity.rs::calculate_lp_rewardscomputes rewards purely as a function of a provider's share oftotal_liquiditysquared, with no relation to fees actually collected by the pool and no consideration of how long a position has been held:The module-level doc comment flags the same gap independently:
In the current implementation, a "flash" liquidity provider that deposits right before a reward calculation and withdraws immediately after earns identical rewards to a long-term provider with the same position size — there's no economic disincentive for this, and rewards aren't backed by real fee income, which means the reward pool's payout isn't tied to actual protocol revenue.
Implementation Plan
calculate_lp_rewardsdraws from real fees collected rather than a synthetic formula.LPPosition(e.g., track deposit timestamp, apply a scaling factor based on duration held) so long-term providers are rewarded more than flash liquidity.Acceptance Criteria