ADD: LP: Separate Yield From Principle
Context
Currently all LP yield is trapped in the pool and exposed to IL and volatility. Block rewards and fees are also continuously sold to principle.
This feature isolates the yield as RUNE and allows LPs to claim it or convert it back to LP. It is likely that most LPs will retain the REWARDS as RUNE, thus also reducing RUNE sell pressure.
Uniswap V3 migrated all users to accrue yield outside the pool. This was a favourable change to LP experience.
Implementation
Currently income for LPs are paid into RUNE for each pool. This sells half to the asset and adds to the principle. https://gitlab.com/thorchain/thornode/-/blob/develop/x/thorchain/manager_network_current.go#L1722
Instead, pay this RUNE into the pool module balance, attributed against the pool, but not in the pool itself:
https://thornode.ninerealms.com/thorchain/pool/AVAX.USDC-0XB97EF9EF8734C71904D8002F8B6BC66DD9C48A6E
pending_rewards_rune = //balance
Each LP is entitled to a share of this yield based on liquidityUnits / totalLiquidityUnits
.
Aggregation
Use the rewardDebt
implementation from Sushiswap Masterchef contract. The rewardDebt
tracks how much of the pool's yield is not the user's and is computed each time the users deposits, withdraws or claims.
User Actions
- CLAIM -> claim the RUNE
- ADD -> add back as liquidity
Memo
// new CLAIM memo
claim:pool:basispoints:asset:affiliate:fee
claim:btc.btc:10000 // claiming RUNE is inferred
claim:btc.btc:10000:btc.btc:t:30 // Claim the yield back as L1 asset
Add back as liquidity
Users can move all their RUNE claim back into the pool by using the ADD-liquidity memo from their address. First sweep the yield, add to RUNE balance, then add to LP position. Need to add paired-address if doing dual-sided
ADD:POOL // Add the RUNE yield as single-sided
ADD:POOL:PAIREDADDR // Add the yield back into the LP position; dual-sided (if already dual-sided)
need to verify the paired-address, in order to find the user in the key-value store (since they can exist as both single-sided and dual-sided
Endpoints
/pool/{asset}
pending_rewards_rune: 12345678 // total balance of stored RUNE
/pool/{asset}/liquidity_provider/{address}
pending_rewards: 123456 // computed for the LP as (pending_rewards_rune * units / LP_units)
Consids
Synths
Deduct the Synth Share of yield from the RUNE, and continue to pay this into the pool, then mint the synth balance to match.
RUNEPool
Deduct the RUNEPool share of yield from the RUNE and pay direct into the module (this will rebase it, allowing RP holders to claim it automatically as part of their yield).
Impact
Users
All users will be migrated and will start receiving yield separately. Single-sided L1 users will need to "claim" using their L1 address, which will swap to L1 asset and send out.
To withdraw yield, they need to perform a "CLAIM" on their yield. If they withdraw principle, their yield is added and withdrawn collectively.
Midgard
Claim events should be tracked.
Store
Users can compute their share of the yield