liquity / bold

Ideas for improvements and enhancements in a Liquity v2.
https://www.liquity.org/liquity-v2
33 stars 7 forks source link

Low LUSD liquidity #31

Closed bingen closed 2 months ago

bingen commented 11 months ago

Problem

bingen commented 11 months ago

See also #26 and #27

edmulraney commented 11 months ago

Liquidity

Need/Problem

Ensure sustainable liquidity on stable Bold pairs of $20m per side (e.g. USDC/BOLD). If users expect 7% on a stable LP this makes $2.8m/year, and we expect $1.4m/year to come from trading fees (curve/uniswap).

Criteria

Assumptions

AMM venue

LP pairs

BOLD/stable (e.g. USDC, 3CRV)

Solution components

When considering a spectrum of centralized <-> governed <-> decentralized solutions, the following must be considered.

Liquidity pairing

AMM venue

Incentivisation mechanism

Yield source

Ensuring we obtain the desired liquidity

Potential solutions

Solution 0

Solution 1

Solution 2

Solution 3

Solution 4

Solution 5

Promising solutions

Solution 0

Solution 1

Solution 2

TBD:

edmulraney commented 10 months ago

Exploring voting mechanisms for the management of yield to be used for incentivising external stablecoin liquidity

Vote locking LQTY options

  1. LQTY holders can vote lock their LQTY toward any LP token

    • Benefits: any AMM venue is usable = future proof
    • Downsides: LPs lose access to their LP token as it would need to be staked
    • Mitigations: we could at least issue a new LP token to represent their staked LP token
  2. LQTY holders can vote lock their LQTY towards any pairable asset on hardcoded AMMs

    • Benefits: instead of voting on specific LP tokens, LQTY holders would vote on a single token which would then be permitted for liquidity pairing with bold on any of the whitelisted AMM venues. This enables LPs to permissionlessly add eligible pools from any whitelisted AMM venue for yield to be directed towards it, the yield would have to be weighted by pool TVL. This also means LPs don’t need to stake an LP token and thus their LP token remains in their wallet. This means their wouldn’t need to be a governance vote per pool, just per asset, whereby there may be the same pool in different venues
    • Downsides: hardcoded AMM venues
    • Mitigations: perhaps voting could be extended to include whitelisting new venues
  3. Yield could be directed towards The DeFi Collective who repurpose the yield for their own chosen liquidity strategy, and LQTY holders can vote to turn off the yield if they underperform

    • Benefits: liquidity strategy isn’t handled by the protocol but offloaded to liquidity experts who can adapt to market changes, AMM venue changes, etc. and run advanced liquidity strategies
    • Downsides: depends on a single organisation which can fail or underperform
    • Mitigations: needs a fallback strategy if LQTY voters revoke the yield from DeFi collective (could be any on chain “marketmaker” entity if they exist)
  4. Clone Maverick contracts and embed in our protocol a specific pool which executes our desired liquidity strategy, pay out all yield to this single pool. LQTY holders can only vote on the asset that can be paired with bold. Position is tokenised.

    • Benefits: not dependent on third party AMM, we have more granular control over the pool and can incentivise deep liquidity in a single pol, while being future proof on the asset which is paired. Removes the need for complex yield distribution among various pools.
    • Downsides: locked into the Maverick design forever, when better designs will come along in the future
    • Mitigations: could enable governance voting over the internal AMM contract, with conditions to prevent misuse
  5. Similar to 4 but create our own specialised AMM, potentially using some ideas from dispenser

  6. Create a Chicken bond for bold LP tokens but instead of having an increasing backing price for bBond, allow people to stake it and collect yield. LQTY holders can vote on which LP tokens can be bonded.

edmulraney commented 10 months ago

Liquidity incentivisation approach

High level We’ll enable LQTY holders to vote on stablecoins which can be paired with bold inside UniV3 (no wrappers like Bunni) to receive system yield rewards. Although voting can happen on a weekly basis, which is good for responding to market exceptions like the paired asset failing/depegging, we don’t want LQTY holders and LPs to have to manage their position on a weekly basis. Instead we expect a pool to last for a very long time, until a better stablecoin pairing comes along. And thus by voting once, you indicate your voting for eternity unless you unstake your LQTY which voted on a pairing. (“Set and forget”). We’re not trying to recreate Curve, but just incentivise long term liquidity.

Process

  1. LQTY holders will vote at most once per week on a stablecoin they want to pair with BOLD to receive yield rewards for (they vote by staking and locking their LQTY for 1 week)

Questions How will the system know the asset users are voting on is a stablecoin? It won’t know possible future stablecoins ahead of time

  1. At the end of the voting period, their LQTY is unlocked and they can unstake if they want to stop voting, but if they don’t unstake, it means they’re automatically voting for the same pool to continue receiving rewards next period

Questions I’m assuming the LQTY will be unstakable until just before the end of the next voting period (1 week), meaning they have 1 week to unstake until it gets auto-locked for the next week as a vote

  1. At the same time, a permissionless function becomes callable which will: If there’s no existing Univ3 BOLD pool with the voted on asset: Deploy a new UniV3 pool with a fixed parameters like tick range determined by the system, and with the paired asset being the only dynamic parameter which was voted on

Questions How will the system know the tick range for the asset? If we somehow limit it only to stablecoins then maybe this is easier? If there’s an existing Univ3 BOLD pool: don’t deploy a new pool Deploy a Univ3Staker contract, with pool/incentivisation parameters all pre-configured by the system (not chosen by users)

The parameters will be: baseFee: (1bp, 5bps, 30bps) univ3pool: the pool from above tickRange: TODO startTime: now endTime: end of period (1 week) refundee: bold smart contract which holds the yield (any remaining rewards are given back to the system) maxTargetTVL: TBD amountOfRewards: this should be a function of the maxTargetTVL and the amount of available system yield that can be paid out, the system shouldn’t pay more yield out than should attract maxTargetTVL, but of course if the system doesn’t have enough yield for maxTargetTVL then it can only pay out its max yield and the realized TVL may be lower

The UniV3 pool needs to have admin control given to a bold smart contract which can kick start the rewards again at the start of the next period if the same pool is voted upon to receive yield

Questions Does the Univ3Staker contract actually support this functionality or would we need to redeploy a new staking contract every period and have the system move the staked NFT over to the new one?

  1. Once the UniV3Staker contract is deployed, LPs can now stake their UniV3 NFT within the staking contract to receive the allocated system yield rewards
  2. If the same pool is voted upon again next period, then LPs do not need to remove/restake their liquidity (TBD is this possible? see question in last part of step 3)

Other questions: How do we handle the first week? Their LQTY will be locked and no pool will be receiving rewards as we won’t have the result of the first vote. Perhaps we can just initialize a pool we think is worth incentivising first e.g. BOLD/USDC or whatever

edmulraney commented 10 months ago

Colin's feedback:

How will the system know the asset users are voting on is a stablecoin? It won’t know possible future stablecoins ahead of time One potential option is to have a fixed number of slots, say 5, which would represent the stables that could be paired next to BOLD. Initially we should probably set them to USDC, USDT, DAI, LUSD and FRAX (whatever, but not important for this demonstration). Few things we should consider, what is the time horizon of this version. While the code would remain immutable --or at least until state rent (maybe) gently coasts it off Ethereum. It's not crazy to imagine that it has a 5-10 year practical lifespan, after which we're on v3 (or more), and this version is less relevant. Given our expressed desire to use a single version of staked ETH, this time horizon is probably towards the top end of what the effective lifespan could be. That in mind, I see essentially we need to design against 2 scenarios: A token is no longer a relevant pair (e.g. say we drop BOLD-FRAX to replace it with BOLD-CRVUSD --again just to demonstrate, don't worry about the choice). We could hold a time locked vote (say 4 successive 1 week epochs need more votes for CRVUSD more than for FRAX), after which CRVUSD replaces FRAX as the fifth position on the 'allowable paired assets' list. This would suggest that effectively anyone (maybe with token gating) could propose assets, most of the time this will fail the 4 epoch test in which case it's discarded), but it would need to be something that is guarded against (a reasonable rationale fundamental for holding a token). Couple of things: This does potentially allow other assets, which are not stablecoins to become the incentivised pair. As I mentioned, I don't think that I'm smarter than the market, so if that's the choice of governance, so be it. It may, however, raise the effective cost of liquidity, but it doesn't put us in a worse situation than with v1. We could imagine putting guardrails in for minimum liquidity or snapshot volatility (using TWAP metrics in Univ3) but again, maybe we don't factor that we're smarter than the market. We probably need to consider including a veto or blank spot, where less than the max number of pairable assets in the list (e.g., 4 of 5) slots could be incentivised and it's not easy to abuse spamming in a 5th. A token has been replaced and/or redeployed. We've seen this with DAI (now SAI), but it's also not impossible to imagine that USDC or USDT could be redeployed without a long lead time. That would create a ton of headaches, not only for us, but large swathes of DeFi, so I'm not too concerned with this being a messy process, but it should be factored into the design. I think that the solution for 1 is probably sufficient, with the worst case being that it takes a few weeks of paying incentives to a defunct token while we sort out replacing it in the list. I’m assuming the LQTY will be unstakable until just before the end of the next voting period (1 week), meaning they have 1 week to unstake until it gets auto-locked for the next week as a vote Most ve designs I've seen have a "reset" mechanism to nullify their vote if they were to remove (unstake it) over the course of a epoch snapshot in the event of it's expiry. If someone locks for 1 week and votes, but waits until after the epoch to withdraw their LQTY (or whatever), that usually counts. I would advocate that we force people to relock their tokens, or give them a roll-over option through an external mechanism, but wouldn't overengineer this point. Questions: how will the system know the tick range for the asset? If we somehow limit it only to stablecoins then maybe this is easier The UniV3 staker doesn't require this, it balances incentives within range, which means we don't 'guide' liquidity, we just pay liquidity that is actually used. If we want to do guided, I would suggest we use a discretionary offchain mechanism (i.e. Brice) to do this. Does the Univ3Staker contract actually support this functionality or would we need to redeploy a new staking contract every period and have the system move the staked NFT over to the new one? I'd suggest we design it that the 'kicking' should be done from the governance module that we deploy, which would create a new set of incentives at the start of each epoch and reward those assets already staked. I will need to pick apart the contract a bit more, but I think that if (for instance) we reward BOLD-USDC 0.05 in epoch 1 and epoch 2 (creating new incentives each time), an LP with that who staked in epoch 0 and didn't unstake, wouldn't need to do any further action, which would be ideal UX imo. Though there is probably a step immediately before epoch 2 incentives are created that epoch 1 incentives need to be ended (which should be trigged by the governance module). The staker contract, does have logic on createIncentive to specify where refunds would be sent (BOLD or whatever incentive token we give), which would be the governance contract or a treasury that handles this.

edmulraney commented 10 months ago

Choosing an AMM venue

We need to assess which AMM makes most sense to use immutably into the protocol.

Contenders: UniV3, Curve, UniV4, Maverick.

Since UniV4 isn't out yet we can't assess it.

Note on Merkl: Merkl is an incentivisation layer for UniV3. However, it depends on a complex stack of dependencies: Merkl off-chain logic + dispute process -> Arrakis -> Gelato bots.

It requires off-chain calculation of rewards by the Angle team, which an immutable protocol should not depend on ideally.

UX / how would users receive rewards for their liquidity

UniV3

Curve

Maverick

Safety/risk

UniV3: battle tested, confidence high Curve: battle tested, confidence high Maverick: less battle tested, significant/complex changes over UniV3, confidence medium (related to KyberSwap concentrated liquidity hack recently)

Efficiency / peg

UniV3: no effect, liquidity goes where LPs choose to place it, if the price moves out of LP range Curve: dynamically moves concentrated liquidity where its needed Maverick: allows us, or market participants, to create "boosted pools" - choose a liquidity shape that effects the peg in a way favourable to us

edmulraney commented 10 months ago

Comparing options

There are two main paths we seem to be converging on:

  1. Minimal approach: simple incentivisation on-chain, complex incentivisation off-chain
  2. Maximal approach: complex incentivisation on-chain, no incentivisation off-chain

Minimal approach

Pros

Cons

Maximal approach

Pros

Cons

edmulraney commented 10 months ago

Conclusion from today's dev call

Let's assume we'll go with the minimal approach.

Next steps

Given some TVL and some average interest rate:

Factors:

Base numbers:

* USDC could be any paired asset

Outstanding:

edmulraney commented 9 months ago

Moved to docs: https://docs.google.com/document/d/1AptoX4ZzZCFWujBYAkf-wmaA4tVpMym4w7hf4B8Ge_w/edit#heading=h.kvhz0bsk85i3

bingen commented 2 months ago

Hopefully the governance module fixes this.