KIP 010 - The Kolibri Savings Rate

Author: Hover Labs, [email protected]

Created: 10/04/2021

Status: DRAFT

Overview

kUSD minted against an oven is charged an interest rate (currently set at 19.5%). This interest rate is adjustable by the protocol. When loans are repaid, interest is allocated to the developer fund (10%) and stability fund (90%).

The Developer Fund is meant to be a discretionary fund to reimburse, create or develop projects and integrations with Kolibri. The stability fund is meant to be a liquidator of last resort, who will help to liquidate underwater ovens (Oven’s whose collateral is worth less than the loan).

Lastly, the protocol has a Liquidity Pool, where users can pledge kUSD to be used in oven liquidations. This creates a pool of capital that is waiting to liquidate ovens.

Rationale

The Liquidity Pool is pretty large (495k kUSD as of 10/4/2021) and KIP-006 would likely cause it to grow since the Liquidity Pool will receive priority in liquidations. Additionally, we’ve seen healthy collateral ratios (an average of X%) and most liquidations are processed in seconds by private liquidators.

The stability fund is also large (148 kUSD as of 10/4/2021) and grows consistently. If KIP-009 passes, the savings pool will grow even faster, since accruals will happen continuously rather than at repayment time.

Some amount of fees from interest could be passed back to kUSD holders, in the form of a savings rate. This could encourage holding of kUSD. The rate would be adjustable with governance.

Implementation

The implementation of a savings rate pool would look very similar to the implementation of the Liquidity Pool contract. Users would deposit kUSD in the pool, and receive an LP token called ibkUSD (Interest Bearing kUSD). The LP tokens would be redeemable for a ratable share in the pool, and thus would grow in value as the pool accrued interest. Users could redeem their LP tokens for their underlying kUSD at any time.

The pool could keep a counter verifying the last time it accrued interest. When a new interaction with the pool occurs, the newly accrued interest could be calculated as:

let totalPoolBalance = …
let interestRatePerPeriod = self.data.interestRatePerPeriod 
let lastInterestUpdateTime = self.data.lastInterestUpdateTime

# Calculate number of 60 periods elapsed 
let numberOfInterestPeriods = floor((currentTime - lastInterestUpdateTime) / 60)

# Update period state
self.data.lastInterestUpdateTime = lastInterestUpdateTime + (numberOfInterestPeriods * 60)

# Accrue new interest via linear approximation
let newTotalBalance = totalPoolBalance * (1 + (numberOfInterestPeriods * interestRatePerPeriod))
let newlyAccruedInterest = newTotalBalance - totalPoolBalance

Like Kolibri, interest compounding would use linear approximation rather than pure exponentiation, as michelson does not have an exponentiation function.

To actually retrieve the interest, the pool would send a request to the stability fund. The stability fund would need to be updated to handle this request, and to privilege requests to the savings pool.

This does introduce some unique challenges however. If the savings pool requests more kUSD than the stability fund had, then the request to deposit or withdraw would fail. This requires the governable interest rate to be set very carefully (See below). However, A special entry point on the contract could let users withdraw their contributions and forfeit interest. It is very likely that in this scenario that the DAO would step in to make these users whole, lest they loose faith in the Kolibri protocol.

Initial Interest Rate

The stability fund will fund the savings rate, so in practice we must have a savings rate set as:

0 < savings rate < (stability fee * stability fund split)

Or in practice, with a 19.5% stability fee and 90% split:

0 < savings rate < 17.55%

However, we’d also like value to continue to accrue in the stability fund (to ensure that the protocol can cover black swan events) and interest is only accrued at repayment time, rather than at accrual time. This means that over the long run, the protocol will earn the stability fee in interest, but in the short term, returns will be more volatile (at least until / when KIP-009 passes).

The developers suggest a rate of 3% APY for the pool. This value is chosen to be safe in the worst case using the current state of the system:

  • The current kUSD issued is 4.9M
  • The current stability pool size is 1.48k
  • All existing kUSD will be deposited into the pool
  • KIP-009 does not pass, and no existing kUSD is repaid and thus the stability fund will not accrue any interest

After one year, the protocol will need to pay out 147k kUSD (4.9M * 1.03). This obligation can be covered by the stability fund today and means the protocol would have one year before it became insolvent.

In reality, this is a worst case scenario. It is likely that not all kUSD will end up in the pool, and that the protocol will receive interest. Additionally, the protocol can make adjustments prior to one year which will help maintain solvency if the above assumptions do not hold.

Lastly, KIP-009 suggests a feature where interest is paid at accrual time, rather than at repay time. This would theoretically bound the interest rate of the savings pool between 0% and the current stability fee.

Reference Implementation

A rollup and summary of the code to be deployed is here: https://github.com/Hover-Labs/kolibri-contracts/pull/20. The code contains unit tests, and a migration script which has been tested extensively on both the Kolibri Sandbox and testnet.

This code is deployed on testnet at Kolibri.

Stability Fund Multisig

As part of the migration, a new stability fund contract will be deployed. The governance lambda will move any value in the stability fund that exists at submission time. However, due to the delay between submitting a proposal and its execution, more value will accrue in the stability fund due to loans being repaid.

In order to mitigate this problem, we propose setting the governor of the old stability fund contract to a new multisig. After migration, holders of the multisig will agree to transfer any residual value to the new stability fund. We propose using a 2 of 3 multisig, with 0 second timelock, held by the following entities:

  1. yoursoulismine, Community Member, Discord moderator and Harbinger Poster operator - edpkvVfi9djFLdHaHwAJLygUDYYPsv3M7JhJxYZEGrWCi6y1Q8rEDG
  2. Gabe Cohen - Kolibri community member, Co-founder at Ecomint - edpktrq8HSok3LaMHuK17kn8yShsC5AQnpb4WKkYApQcHZNAsewt5B
  3. Keefer Taylor, Hover Labs - edpkuLh768382911CBbWkCN9joZkaZinKKeqPeMnxSoUb3X4TV7GpJ

In addition, the new stability fund contains a new entry point, sendAll, which transfers all value in the stability fund to a new location. This new entry point removes the need for a trusted multisig contract in the future.


Changlelog:
12/9 - Revised the reference implementation section to point to up to date code, and added information about the proposed multisig to transfer value.

3 Likes

I’ve started a release (which I’ll call “Contracts 1.2”) which implements the KSR in the Kolibri-Contracts repo. If this proposal does get put up for vote, this code will form the base.

Code reviews and architectural critiques are encouraged.

1 Like

I have some thoughts on the KSR, and would suggest some changes.
(I’m aware that it’s a little late, but I totally missed it :upside_down_face:)

My objections are basically, that the KSR Pool would draw liquidity from the Kolibri Liquidity Pool, hence potentially weakening the system.
My assumption here is, that the larger the Liquidity pool, the healthier the ecosystem and that, there is no good enough or “safe” amount, as long as there are other pools drawing liquidity. (we already have the kUSD locked up in AMMs, which also should be maximised)

My suggestion would be, to simply pay the interest to the Liquidity Pool.
This would likely cause the Liquidity Pool to grow larger, and would have (at least) the same effect on the kUSD/USD peg/rate.

In return the Farms for QLkUSD and kUSD Farms should be closed and a new vote/proposal created, that decides on the distribution of the freed up coins.

@casa This is a great call-out. I think we were so close to each problem individually that we never actually considered combining them together :man_facepalming:!

My objections are basically, that the KSR Pool would draw liquidity from the Kolibri Liquidity Pool, hence potentially weakening the system.

My assumption here is, that the larger the Liquidity pool, the healthier the ecosystem and that, there is no good enough or “safe” amount, as long as there are other pools drawing liquidity. (we already have the kUSD locked up in AMMs, which also should be maximised)

I think that there’s not a strong risk here personally even if the LP liquidity drops and goes to the KSR, because if liquidity is fragmented between KSR and the liquidity pool and the LP is slightly underfunded to liquidate an oven, a strong economic incentive still exists to top up the LP and liquidate the undercollateralized oven (and with how transactions work on tezos you can literally pull your kUSD out of wherever it is, deposit it into the LP, liquidate the oven, and then move the liquidity back, gaining upside across the board while still performing the critical task of liquidation). Ultimately as long as there’s a sufficient debt ceiling to avoid a supply crunch, liquidators always have a real strong incentive to figure out a way to liquidate ovens.

That said, a larger liquidity pool is definitely a good thing (as would combining it with KSR functionality), but we also have some issues to fix in the current liquidity pool which is why I’d recommend we don’t do this in this iteration, but target this idea for a unified v2. Basically due to how the LP is currently designed it can’t liquidate very large ovens, which forces the protocol to have a higher debt ceiling than it should.

To fix these issues it requires reworking some of the inner workings though to also be able to collect and pay out XTZ in cases where a quipuswap swap is impossible (namely large trades incurring 33%+ slippage), and all that needs thought about, developed, and well tested.

I think once these issues are fixed within a new version of the LP, we can very easily unify these pools into one pool that gets a constant return (% of stability fee, the KSR) along with the upside of liquidations, which are impossible to predict before they occur, but definitely increase the pool value when they occur.

I will say that some of this opinion is admittedly shaded by the fact that things are fully developed and tested to our standards and on the verge of being ready to go to the DAO for a vote this week, so I’m hesitant to pump the brakes to add this functionality when this is a powerful tool that can help us better control the peg.

In the spirit of “Rough consensus and running code” I think it makes sense to roll forward with this KSR contract as planned, then work towards a goal of unifying these two pools in the future, because ultimately it’s a great end-state to achieve!

I’ve updated the proposal to contain links to the final code that will be deployed, and testnet.

I’ve also added details about a multisig that we’re going to have to use as part of the migration process to control a small amount of stability fund value that will be accumulated, as well as mitigations that are in the code to not have to do this in the future.