Pool Party is here. Earn OP and PERP tokens based on the amount of volume you facilitate! See our blog post for more details.
Rewards are distributed on a weekly basis (on Mondays, at 06:00 UTC), where the amount of OP and PERP tokens earned proportional to the volume facilitated for a certain pool. Your estimated and claimable rewards will be shown here: https://rewards.perp.com/liquidity-mining
Pool Party rewards, by market
As of June 19th, 2023, the Pool Party rewards by market will be adjusted to the amounts shown by the image below:
Update to Calculation Method
As of the week commencing October 16th, Pool Party rewards will be based on:
- the amount of time the price is within the LP's range (only active, in-range liquidity will get rewards), and
- the concentration of liquidity (where concentrated liquidity will get more rewards).
The more total liquidity you provide in the in-range tick, and the more concentrated your liquidity is, the more rewards you will receive. The calculation method is done in similar manner to the Uniswap v3 Staker contract.
The change was introduced to make the Pool Party liquidity mining more efficient and defend against potential wash trading. For liquidity, tits time amount is calculated by a Uniswap v3 contract. We can get secondsInsidePriceRange of a liquidity position during one week by querying the Uniswap v3 contract.
Formula
\[weeklyRewardProrate = secondsInsidePriceRange / secondsInOneWeek\]
\[weeklyReward = marketWeeklyReward * weeklyRewardProrate\]
Example
- Alice provides 100 liquidity with a price range of [80, 100] for one week
- Bob provides 100 liquidity with a price range of [85, 95] for one week
- The price goes to 90 for one day and then stays at 70 for the rest of the time
For Alice:
- secondsInsidePriceRange = 30,240
- weeklyRewardProrate = 30,240 / (60 * 60 * 24 * 7) = 5%
- weeklyReward = 5,000 * 5% = 250
For Bob:
- secondsInsidePriceRange = 54,432
- weeklyRewardProrate = 54,432 / (60 * 60 * 24 * 7) = 9%
- weeklyReward = 5,000 * 9% = 450
Although Alice and Bob provide the same amount of liquidity and have the same duration in which the price is within their ranges, Bob provides liquidity in a more narrow range and has a larger value for secondsInsidePriceRange for his rewards calculation.
If instead the price goes to 90 for one day, then to 80 for another day, and then stays at 70 for the rest of the time, Bob's reward calculation will not change but Alice's will. In this case, the secondsInsidePriceRange becomes 60,480 for Alice, the weeklyRewardProrate increases to 10% and the weeklyReward increases to 500.
In depth calculation
The reward calculation is executed once per week. During the calculation we query snapshotCumulativesInside
from the Uniswap v3 pools multiple times. These calls return snapshots with the cumulative time which the price is inside a specific tick range. For each active (in-range) liquidity position, we get snapshots of cumulative time for 3 kinds of block:
- The first block of the week
- Each block with a liquidity changed event
- The last block of the week
For example, given a position with
- active liquidity with tick range (-1000, 1000)
- some liquidity at the start of week
- more liquidity added during the week
There will be 3 queries
# Block 1000 is the first block of week
1. cumulativeTimeStart = snapshotCumulativesInside(-1000, 1000, {blockTag: 1000})
# Block 2000 is liquidity changed block
2. cumulativeTimeAddLiquidity = snapshotCumulativesInside(-1000, 1000, {blockTag: 2000})
# Block 3000 is the last block of week
3. cumulativeTimeEnd = snapshotCumulativesInside(-1000, 1000, {blockTag: 3000})
Therefore, the secondsInsidePriceRange
is the sum of the time delta between these 3 snapshots.
secondsInsidePriceRange = (cumulativeTimeAddLiquidity - cumulativeTimeStart) * 10000 + (cumulativeTimeEnd - cumulativeTimeAddLiquidity) * 20000
We multiply by the liquidity amount because snapshotCumulativesInside
returns the cumulative time per liquidity. Assume the liquidity amount is:
- 10K between blocks 1000 - 2000
- 20K between blocks 2000 - 3000
Lastly,
snapshotCumulativesInside(-1000, 1000)
returns
time / all of liquidity amount between (-1000, 1000)