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:
- Collateralized - The oven has above 200% collateralization
- Undercollateralized - The oven has below 200% collateralization, but above 100% collateralization. Ovens in this range are profitable to liquidate.
- 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:
- 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.
- 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.
- 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:
- 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)
- 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.
- 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:
- Deploys the new contracts on chain
- Validates that storage copied between the old and new contracts correctly
- 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.