KIP 006 - Prioritize the Liquidation Pool in Liquidations

Author: Hover Labs, [email protected]

Created: 09/22/2021

Status: PASSED

Summary

Kolibri is a protocol that issues kUSD, an algorithmic stable coin that is soft pegged to the US dollar. Kolibri functions by using over collateralized debt positions / CDPs (called ovens) which collateralize a synthetic asset. Ovens must maintain a collateralization requirement, otherwise they are eligible for liquidation. The current collateralization requirement is 200%. When a liquidation occurs, a liquidator repays the loan and receives collateral in return.

Collateralization is defined as:


collateralization = value of CDP / value of loan

More specifically in Kolibri:


collateralization = (XTZ in CDP * XTZ Price in USD) / (kUSD borrowed * $1)

As a practical example, if 1 XTZ = 5 USD and an oven had 10 XTZ in it, and 20 kUSD borrowed then the collateralization would be:


collateralization = value of CDP / value of loan

=> collateralization = (XTZ in CDP * XTZ Price in USD) / (kUSD borrowed * $1)
=> collateralization = (10 XTZ * 5 USD/XTZ) / (20 kUSD * $1)

=> collateralization = (50 USD) / (20 USD)
=> collateralization = 2.5 = 250%

There are three states an oven can be in, with regards to a collateralization requirement:

  1. Collateralized - The oven has above 200% collateralization
  2. Undercollateralized - The oven has below 200% collateralization, but above 100% collateralization. Ovens in this range are profitable to liquidate.
  3. Underwater - The oven has below 100% collateralization, meaning the value of the loan is greater than the value backing it. Ovens in this range are unprofitable to liquidate.

In Kolibri, a liquidation occurs when an oven drops below the collateralization threshold. There are three types of users who can perform a liquidation:

  1. A Private Entity: A private entity may choose to liquidate the oven by repaying the loan and receiving the collateral in the oven in return.
  2. Liquidity Pool: A shared pool of kUSD pledged to help liquidate undercollateralized ovens. When the pool liquidates an oven, it receives XTZ as collateral and immediately swaps it to kUSD on Quipuswap. Anyone can direct the pool to liquidate an oven, and for doing so, they receive a liquidation reward (currently 1% of the collateral). LPs in the pool will ratably split the remaining 99% of the rewards.
  3. Stability Fund: The protocol maintains an emergency backstop that can be used to liquidate ovens are either underwater or too large for the Liquidity Pool or private entities to liquidate.

Private Entities and the Liquidity Pool are meant to be the primary liquidators of undercollateralized ovens (which stops them from going underwater). If ovens go underwater, then the stability fund would step in as a liquidator of last resort.

The Liquidity Pool is meant to be a safety feature for the protocol. It allows individuals users to pool together funds, which may be able to liquidate larger undercollateralized ovens, or more undercollateralized ovens than private users in the case of a sudden drop in collateral value.

However, as of today, the majority of liquidations are performed by private entities. This creates a disincentive for users to join the Liquidity Pool as they pay the opportunity cost of parking their kUSD in the pool, for little upside.

Motivation

Having a larger Liquidity Pool provides larger backstops to the protocol. This can lead to a number of positive outcomes:

  1. The protocol can perform more efficiently during times where collateral value drops suddenly (by both being able to liquidate larger ovens, and more ovens than private entities)
  2. A large enough Liquidity Pool may provide enough capital that portions of the stability fund could be redirected towards a savings rate, or other use case in protocol.
  3. A large enough Liquidity Pool could provide enough safety that collateralization requirements could be relaxed.

These benefits are large enough that the protocol should seek to have users join the Liquidity Pool, rather than trying to liquidate ovens as private entities.

Implementation

New Economic Parameter

A new economic parameter, privateLiquidationThreshold is introduced to the Kolibri Protocol. This value should always be set such that:


100% < privateLiquidationThreshold <= collateralizatizationRequirement (currently 200%)

Private entities may only liquidate below the privateLiquidationThreshold. The Liquidity Pool and Stability Fund can always liquidate below the collateralizatizationRequirement.

This arrangement provides a buffer period where the Liquidation Pool receives the right of first refusal to liquidate undercollateralized ovens. In the past, Hover Labs has (anecdotally) observed that undercollateralized ovens are liquidated fairly quickly, with multiple attempts to liquidate coming from both the Liquidity Pool and private entities. Therefore, Hover Labs theorizes that the majority of liquidations will occur before the collateralization of an oven drops below the privateLiquidationThreshold. The net effect is that the Liquidity Pool is prioritized for liquidations, and participants in the pool will see more successful liquidations, ultimately attracting a larger Liquidity Pool.

Should the pool fail for any reason, a private entity can liquidate if the collateral value continues to drop. This provides a backstop from the pool that should still be profitable enough to incentivize private entities to liquidate.

Lastly, the stability fund retains the right to liquidate anything below the collateralizatizationRequirement. In practice, the Stability Fund should only step in as a liquidator of last resort, when ovens are underwater. Keeping this constraint as it is today reduces the complexity of this change. A future update to the protocol could modify this.

The following graphics depicts the final set of rules for liquidations in the Kolibri Protocol after this proposal:

Initial Value and Governance

Hover Labs suggests an initial value for privateLiquidationThreshold to be set at 180%. This value provides a large buffer time for the Liquidation Pool to be prioritized, while also maintaining a large safety margin for private entities to liquidate before the oven becomes underwater.

A setter to update this value should be provided, which the Kolibri’s decentralized governance and DAO can update and refine. Importantly, if the protocol ever wanted to revert this feature, they could achieve the same behavior the protocol has today by setting the values of privateLiquidationThreshold and collateralizationRequirement to be the same value. This effectively removes this feature, without requiring an additional code change.

Lastly, the address of the Liquidity Pool also becomes governed by the DAO, which allows upgrades to the Liquidity Pool contract to occur without requiring a code change.

Safety Considerations

The Liquidity Pool has a number of safety considerations around it. These concerns are enumerated and addressed below. Hover Labs believes that as private entities can still liquidate ovens, these concerns should not block the proposal (thought they do represent areas of future work).

1. The Liquidity Pool is Unaudited

The Liquidity Pool code has not been formally reviewed by an audit team.

However, the code is relatively simple and fully unit tested. The pool is also open source. As of this writing (09/22/2021) the pool custodies over 800k in value, making it a valuable target that should be worth attacking if there was an exploit.

** 2. Reliance on Quipuswap**

The Liquidity Pool relies on Quipuswap functioning and being able to perform an XTZ to kUSD swap in order to be able to perform liquidations.

If Quipuswap loses liquidity, or if a trade size is too large, a liquidation from the pool may fail. However, Quipuswap is the oldest and most liquid DEX in the Tezos ecosystem, making it the current best option. Additionally, since liquidations via the Liquidity Pool increase trading volume on the Quipuswap XTZ/kUSD pool, more Liquidity Providers should be attracted to provide liquidity on Quipuswap.

Lastly, the address of the pool for swaps is updatable via Governance. If a newer, more liquid DEX emerged on Tezos, governance could vote to utilize that pool instead.

If for any reason Quipuswap was to fail, private entities can always step in below the privateLiquidationThreshold and still liquidate the oven at significant profit.

** 3. Front Running Attacks **

A liquidation performs a market buy of kUSD from Quipuswap with the amount of XTZ received. Liquidators or other malicious users may be able to front-run liquidations on Quipuswap by anticipating or batching liquidations, which may lead to reduced value for LPs.

This attack requires the front runner to have sufficient capital to move the price of the XTZ/kUSD pair on Quipuswap, which becomes harder as more LPs provide liquidity on Quipuswap.

Quipuswap already contains the most liquidity of any DEX for kUSD on Tezos. Additionally, liquidations via the Liquidity Pool increase trading volume on the Quipuswap XTZ/kUSD pool which means more Liquidity Providers should be attracted to provide liquidity on Quipuswap.

If front running attacks ever became an issue, it is likely that Kolibri would move to an alternative implementation of the Liquidity Pool and private entities can always step in below the privateLiquidationThreshold and still liquidate the oven at significant profit.

Implementation

An implementation of this protocol is provided in this pull request.

The feature contains unit tests to ensure:

Unit Tests Added:

  • Liquidity Pool can liquidate above privateOwnerLiquidationThreshold
  • Liquidity Pool can liquidate below privateOwnerLiquidationThreshold
  • Stability Fund can liquidate above privateOwnerLiquidationThreshold
  • Stability Fund can liquidate below privateOwnerLiquidationThreshold
  • Private owner cannot liquidate above privateOwnerLiquidationThreshold
  • Private owner can liquidate below privateOwnerLiquidationThreshold
  • Only the DAO can update the privateOwnerLiquidationThreshold
  • Only the DAO can update the liquidityPoolContractAddress

End to End Tests Added:

  • Liquidity Pool can liquidate above privateOwnerLiquidationThreshold
  • Stability Fund can liquidate above privateOwnerLiquidationThreshold
  • Private owner can liquidate below privateOwnerLiquidationThreshold

Hover Labs believe this should cover all cases, but welcome external code reviews.

Contract Migration

A migration script is provided in this pull request. The migration scripts:

  1. Deploys the new contracts on chain
  2. Validates that storage copied between the old and new contracts correctly
  3. Generates a lambda to submit as a Kolibri Governance Proposal to enable the new contracts in the Kolibri protocol.

This migration has been thoroughly tested in the Kolibri Sandbox.

Lastly, the migration scripts also deploy non-controversial changes from KIP-005 as part of this change. These changes can be decoupled, if the community has reservations.

I think this is a new concept that we’d have to message appropriately (specifically the risk of using the pool to liquidate unprofitable ovens) if that’s what we want to do here. In general I think this is a good idea though since the stability capital is not being put to work anywhere.

Generally speaking though I think this is a good and eloquent solution to this problem of growing the liquidity pool.


The only thing I foresee that might be an issue is the reliance on Quipuswap for pool liquidations, but realistically since private entities can also liquidate that allows for only a bit of wiggle room for something like that to be abused (e.g. large ovens purposefully going under-collaterlaized because they know the LP can’t liquidate them).


Sidenote - I think that diagram is a bit confusing with the top notes since two of them are labeled privateLiquidationThreshold (and presumably should be a group like the bottom).

What are your thoughts on instead of having 2 parameters (collateralizationRequirement and privateLiquidationThreshold) having the privateLiquidationThreshold instead be an offset from the collateralizationRequirement.

So instead of privateLiquidationThreshold = 180% and collateralizationRequirement = 200%, it’d be privateLiquidationThreshold = 20% and collateralizationRequirement = 200%.

This achieves the same controls but does not require upgrades to be done in lock-step with one another (i.e. one can lower the collateralizationRequirement to 175% and the private liquidation threshold would automatically be 155%.

With 2 variables if one somehow got adjusted improperly from the other it could have bad consequences, and with this setup single variables are easy to tweak/validate. If people want to disable the feature they’d just set privateLiquidationThreshold = 0 instead of perpetually having to adjust both values at the same time if the desire is to disable the feature (imagine reducing the collateralization ratio, but forgetting to adjust the privateLiquidationThreshold!).

I think it’s an elegant solution that adds stability to the system.
Though rewardPercent needs to be updated as well to keep users motivated to run bots
Speaking of the stability fund, what do you guys think about moving it to the liquidation pool on behalf of the DAO? not a well thought idea, just something that came to my mind while I was reading this

What are your thoughts on instead of having 2 parameters (collateralizationRequirement and privateLiquidationThreshold) having the privateLiquidationThreshold instead be an offset from the collateralizationRequirement.

I do think @fitblip’s suggestion makes sense and I can implement those changes.

Would you want the API to look like:

setCollateralizationRequirement(newValue)
setPrivateLiquidationThreshold(newValue)

or

setCollateralizationParams(newCollatRequirement, newPrivateLiquidationThreshold)

I prefer the former. Even though the API is more verbose, it will make governance tooling easier to write and lambdas easier to verify.

Though rewardPercent needs to be updated as well to keep users motivated to run bots

I agree that this makes sense to do. I’d welcome a KIP or governance proposal to do this. I am not sure what I think the right value should be?

Speaking of the stability fund, what do you guys think about moving it to the liquidation pool on behalf of the DAO?

This may make sense to do in the long term. I think that there’s some value in having fallbacks for the liquidation pool (they’re described in the KIP above) and that in the short term it probably makes sense to prioritize having a solid fallback.

One key way to derisk this is to have the liquidity pool not automatically swap the returned collateral. This is a solved problem (the Liquidity protocol whitepaper describes one approach for this) but the code is non trivial to write and test.

1 Like

Agreed, 2 separate entry points make more sense IMO.

Yeah I think this needs updating for sure, maybe something like 10%? 25%? People running the bots should get a nice reward IMO.

I think that the liquidity pool as it currently stands has people expecting not to have their funds used in a black swan event, and I think that were something to occur we’d have capital flight before the funds could actually be used.

I think if those funds should go anywhere it should go to a kolibri savings rate type contract and act as buffer funds until we can update contracts to calculate interest in real time.


Related - I think we should really do a risk assessment as to what the stability fund is specifically derisking in concrete terms. I know it’s for liquidating ovens that are not economically viable to liquidate, but my main questions are:

  • Under what concrete circumstances would this actually occur? The price of tezos crossing some threshold? Wouldn’t liquidations offset this risk? Is there something else I’m not considering?
  • If we decide we still need the stability fund - how much is enough to stash away to offset the current debt ceiling/system metrics? Enough to liquidate the largest oven? Something else? Once we cross that threshold, what should we do with the excess funds?

I’ve got no idea how to correctly asses a reward but tend to lean towards a smaller one (10%) because even though running a bot requires effort, you’re exposed to no risk as opposed to liquidity providers

yeah 100%.

Ah yeah that’s a good point. 10% sounds reasonable then :+1:, though I suspect we’ll have similar contention around trying to call the liquidate function as well that I wish we could solve (though short of something like flashbots I don’t think there’s really a solution).

Ummm, I find this a little perplexing. Although the mechanics are sound, I don’t like the idea behind prioritizing the Liquidity Pool. It goes against the theme of a free market by providing an unfair advantage to the core protocol. There’s fierce competition now amongst liquidators [as should be the case], albeit those with programming skills and extra technical tooling do carry an [arguably unfair] advantage.

  1. Motivation #1 - I agree the protocol can be more efficient by targeting larger ovens, but I don’t think it can be more efficient than freely competing private entities.
  2. Motivation #2 - If this is a driver, maybe incentivize liquidators via a larger share of the target oven. The Stability Fund can be utilized elsewhere to incentivize the rest of the ecosystem (i.e. other use cases).
  3. Motivation #3 - The collateralization requirement should be a parameter which is treated very much like the protocol debt ceiling. I don’t think this prioritization of the Liquidity Pool properly subsidizes the use case for a lower collateralization ratio.

I think the Liquidation Pool probably hasn’t shown its true, useful colors yet due the the pithy 1% reward. I’d rather first experiment with the reward structure than making an extensive change.

Another incentive could be in the form of funding a “savings pool” from the target ovens - say 10% of the value of the [liquidated] oven goes to fund a savings pool which can act as an yield to park kUSD in the Liquidation Pool. The remaining 90% are spread to Liquidity Pool funders on a prorata basis (as is now). Note that these are made up numbers, community VOTES on what these parameters could be… these attributes being parameterized can also aid with future tweaking (just like the debt ceiling).

I am on the fence with this proposal…

Thanks for the thoughtful response. A few responses inlined below…

It goes against the theme of a free market by providing an unfair advantage to the core protocol. There’s fierce competition now amongst liquidators [as should be the case], albeit those with programming skills and extra technical tooling do carry an [arguably unfair] advantage.

From the protocol’s perspective, the only two things that really matter are:

  1. Capital available to liquidate ovens
  2. Time it takes to liquidate ovens

As it stands now, it is unclear how we measure (1). There may be a lot of capital sloshing around, or it could be totally tied up. Tying it up in the Liquidation pool gives us some idea of this, and incentivizing the liquidation pool means that it is likely that capital is used.

I think the free market ethos is fine, presumably liquidators can still compete to use the pool to liquidate ovens (and receive the results of liquidation either via pool profit sharing or the reward structure).

I agree technical users have an unfair advantage; they almost always will on permissionless networks.

If this is a driver, maybe incentivize liquidators via a larger share of the target oven.

This isn’t a terrible idea and I’d be happy to see us make a change here and see if it changes behavior. I do think that if we privilege the pool we get the same outcome (folks will write bots that target the pool, and not themselves)

The Stability Fund can be utilized elsewhere to incentivize the rest of the ecosystem (i.e. other use cases).

Agree. I suggested reasons why we might benefit from having increased amounts of capital in the liquidity pool. I think anything WRT the stability fund is a separate proposal that merits discussion.

Point taken, of course, that using that as a justification for this proposal may be misleading.

The collateralization requirement should be a parameter which is treated very much like the protocol debt ceiling.

Agree. Same point as above, I think this change would be a separate discussion based on current parameters.

I think the Liquidation Pool probably hasn’t shown its true, useful colors yet due the the pithy 1% reward. I’d rather first experiment with the reward structure than making an extensive change.

What do you think a reasonable rate should be? I’m not sure how to determine this so I am mostly curious.

Another incentive could be in the form of funding a “savings pool” from the target ovens - say 10% of the value of the [liquidated] oven goes to fund a savings pool which can act as an yield to park kUSD in the Liquidation Pool.

I’m not opposed to this particular idea.

IIUC, you’re suggesting that private liquidations should receive 90% of profits and 10% of capital. This sounds a lot like a pool with a reward rate of 90% which is incentivized. Is there something I’m missing?

This PR will apply the API changes you suggested:

It is unit tested and I tested on the sandbox.

Edit: this isn’t to say I don’t think the opposing viewpoints in this thread don’t hold water; started working on this before they were posted.

1 Like

From the protocol’s perspective, the only two things that really matter are:

  1. Capital available to liquidate ovens
  2. Time it takes to liquidate ovens

I’d add that the protocol also has an inherent third goal to be successful in the long run. Because we know #2 is almost instantaneous due to competition, I’d make the educated guess that the extra “slosh” is simply waiting to be utilized for liquidations (along with other frequent use cases like farming and supplying liquidity). For #1, why worry if there’s extra capital - that’s the whole point of holding “cash” aka stablecoins. What we should be measuring is HOW the protocol behaves long-term - XTZ price goes up, protocol is utilized more (increased leverage), and vice versa.

There will be other utility for kUSD as new dapps launch - I think it’s too soon to make this change also because of a lack of advanced dapps for lending and yield aggregation. The direct connection I make for kUSD is DAI (ETH). Don’t think MakerDAO has this mechanism of prioritizing the protocol over regular users.

==============================================================================

I think the free market ethos is fine, presumably liquidators can still compete to use the pool to liquidate ovens (and receive the results of liquidation either via pool profit sharing or the reward structure).

Well, so using this logic, the “slosh” is now parked in the Liquidity Pool instead of private wallets. If you push the line of thinking, it comes down to incentivizing users to activate kUSD utility, not park capital at all (either the Liquidity Pool or own wallets). So we aren’t really solving for velocity of money, are we?

==============================================================================

I do think that if we privilege the pool we get the same outcome (folks will write bots that target the pool, and not themselves).

But that’s OK now though, correct? Since users will now at least park idle kUSD in the Liquidity Pool vs. their own wallets… I’m not sure why are we distressed with folks hanging on to cash - if anything, there are ample lessons from macroeconomics in the real world to increase the velocity/utility of money. It comes down to incentivizing actions. If we want folks to park idle cash in the Liquidity Pool, then let’s incentivize that rather than giving the protocol an unfair advantage. The reason why I’m superficially against this idea is I genuinely think that this change will affect competition. I can make the anecdotal argument that currently I have some incentive to use and hold kUSD (if I’m a liquidator)… with this change, there may be decreased utility since my incentive [as a liquidator] in the Liquidity Pool is exponentially lower than with my private wallet.

==============================================================================

What do you think a reasonable rate should be? I’m not sure how to determine this so I am mostly curious.

In line with my prior suggestions and the ethos of a DAO, the rate could be a parameter which the community votes on. I think a 10% starting rate is a high enough incentive for folks to park the slosh in the Liquidity Pool (especially in order to liquidate large ovens). In fact, a 10% “win rate” is high enough that it will promote competition among users/bots to click the “Liquidate” button - the key being, everyone is pari passu (on equal footing). IMO, the current 1% reward isn’t a high enough incentive for anyone to park their idle kUSD in the protocol. On the flip side, 10% may be too high if/when XTZ price is say $100. So the idea of letting the DAO decide makes sense to me. I suggested 10% since it seems a reasonable starting point given where markets are now.

==============================================================================

IIUC, you’re suggesting that private liquidations should receive 90% of profits and 10% of capital. This sounds a lot like a pool with a reward rate of 90% which is incentivized. Is there something I’m missing?

Sorry, I should have used another number to explain this; the 10% here is the same as the 10% reward I suggested for liquidating through the Liquidity Pool, hence the confusion. But yes, your understanding is correct. In fact, I am suggesting the following (assume this “savings” parameter is 7% to avoid confusion):

  1. When someone liquidates from their private wallet, 7% of resulting kUSD funds a “savings pool” (SP). Liquidator receives the remaining 93%.
  2. When someone liquidates from the Liquidity Pool, they receive a 10% reward on the overall liquidation value. The remaining 90% is first charged a 7% fee to fund the SP; the rest is spread among Liquidity Pool funders on a prorata basis (the original liquidator gets rewarded again based on their share of the Liquidity Pool).
  3. Along with the stability fund, I reckon the SP will have enough slosh (:wink:) to fund a proper yield back to the funders of the Liquidity Pool (another incentive for people to utilize the Liquidity Pool).

Assuming I am not missing anything obvious, I think that this structure gets us to probably the same, if not better, outcome that was originally envisioned with KIP-006. All without impacting competition and redirecting users to Kolibri competitors.

I’m not sure I follow the logic for your opposition @Oyster - right now the liquidity pool gets a very small (if any) amount of liquidations due to 1.) contention around liquidation transactions and (arguably more importantly) 2.) no strong incentives for people to liquidate via the pool.

If an individual has a liquidation bot they’ve written then it’s massively in their interest to liquidate with their own funds and not use the pool - arguably having a more unfair advantage than the LP being able to liquidate things. For the LP to fulfill it’s role and potentially provide a liquidity backstop it also needs an incentive (besides farming) to have people participate.

These changes to the liquidity pool basically just shift the allocation of liquidation profits from 100% going to individuals with technical abilities to write liquidation bots (who then battle each-other come time to liquidate something) to splitting the rewards 10% to those bot builder individuals, and the rest going to the LP participants (which helps encourage people to participate in the LP). This is why I’m generally in favor of a larger share going to the bot builders, but we can always adjust later and I don’t feel that strongly about it. There’s still an incentive to run bots, which is something we don’t want to get rid of for sure.

I don’t think the reward rate really has much to do with it - if I were to run a liquidation bot I’d put a good chunk of my own money at the ready to liquidate ovens and then only fall back on the LP if I didn’t have the funds to cover it. Otherwise I would never use the LP because why would I (as a hypothetical rational economic actor) settle for 1% (or 10%, or even 50%) if the opportunity exists for me to take 100%? What I think this proposal aims to fix is this incentives problem - by increasing the reward % and allowing the LP first dibs on liquidations it provides real value for liquidity providers to help while also giving the bot builders a good chunk without it being an all or nothing for either party.

I do like this idea and think that the protocol should take a cut (maybe 10% or something) as well to help fund future endeavors and whatnot.

Awesome!
Kevin Durant Mvp GIF by NBA

Also at this point I think we need to gauge general sentiment, so I suggest we:

In general I’m a firm believer in rough consensus (and running code), so if there are one or two voices that are in opposition to the idea but generally the community is amenable to it (which equates to a likely proposal passing successfully) then we should propose it and push forward.

1 Like

I’ve created Put KIP-006 Up For Vote in the Signal Requests category.

1 Like

BTW, I just wanted to raise a couple of points around the competitive nature of transactions. I will vote with the [indicative] majority in the end, so there’s that!

This has been submitted to the DAO in operation oodWcGS1LF974DCE5TzpaCz3gXjCpLaeZh2vj7UdfwCM56FVGH2/contents

Voting ends in ~3d12h!

I crunched some numbers WRT to the pool liquidations vs individuals.

To date, individuals have successfully liquidated 165,908.07 XTZ from ovens over 245 liquidations, while the pool has liquidated 8.2 XTZ from 64 liquidations (many of which weren’t actually profitable to execute).

Needless to say, the individual liquidators are winning out wholeheartedly.

(Liquidity pool allocation not pictured because it was so small it wouldn't render)

You can find the source code for this analysis in this gist: Github Gist

And you can find the spreadsheet for the graph here: Google Docs