How It Works
Each DAMM v2 pool has up to two reward slots. Once a reward slot is initialized, it cannot return to the uninitialized state. A reward slot defines:- The reward token mint.
- The reward vault that holds funded tokens.
- The funder that can add reward tokens.
- The reward duration.
- The reward rate over time.
What Counts as Liquidity
DAMM v2 uses total position liquidity for reward accounting. That can include:- Unlocked liquidity.
- Vesting liquidity.
- Permanently locked liquidity.
Reward Campaign Lifecycle
1
Initialize a reward slot
The pool creator or an authorized operator sets up reward slot 0 or 1 with a reward mint, funder, and duration.
2
Fund the reward vault
The funder sends reward tokens into the vault. DAMM v2 calculates the reward rate over the active duration.
3
LP positions accrue rewards
Positions earn rewards over time based on their share of total liquidity.
4
Position owners claim rewards
Rewards remain pending on the position until the position owner claims them.
Reward Limits
Only the configured funder can fund a reward slot. Reward duration can be updated separately, but it must remain within the 1 day to 1 year limit.
Why It Matters
Liquidity mining helps projects bootstrap deeper markets. Instead of asking LPs to provide liquidity only for trading fees, a project can add reward tokens that make participation more attractive during key market phases.Launch Incentives
Reward early LPs during the first days or weeks of a new pool.
Sticky Liquidity
Encourage LPs to keep capital in the pool through important growth periods.
No Separate Farm
Rewards accrue directly to DAMM v2 positions, reducing operational complexity.
Position-Aware Rewards
Rewards are tied to NFT positions, making incentives easier to track and compose.
Empty Liquidity Periods
If a reward campaign is active but the pool has no liquidity, DAMM v2 tracks the number of empty-liquidity seconds. On the next funding, the funder can carry that ineligible reward value forward into the new reward window. If they do not carry it forward, the ineligible reward must be withdrawn before funding again.Growth Past the Field Limit
reward_per_token_stored is a U256. Funding a reward while pool liquidity is very small can make one growth step larger than that field. The field wraps, and a position reads the difference with wrapping subtraction. If the position’s new pending reward does not fit in a u64, the program stores u64::MAX and continues. The same wrap applies to fee_a_per_liquidity and fee_b_per_liquidity.
On a compounding pool, the funder can call withdraw_dead_liquidity_reward for the reward share of DEAD_LIQUIDITY (100 << 64). That share is not owned by any position. The checkpoint is the quotient wrapped to a u64. claim_protocol_fee2 uses the same wrap for dead_liquidity_fee_checkpoint. Quote the reward with getDeadLiquidityReward.

