Interest & Liquidation Model

Detailed breakdown of Interest Model, Collateralization Ratio & Liquidations

Interest

We store two indices for each asset; we call them the ‘deposit interest accrual index’ and ‘borrow interest accrual index’ for each asset. These values generally increase over time, starting at 1 at the initialization of the protocol.

  • Definition of ‘deposit interest accrual index’

    Suppose a user deposited 1 of asset A at initialization of the protocol. The deposit interest accrual index of Asset A at time t can be thought of as the amount of asset A that this user would be allowed to withdraw at time t.

    If user 2 deposited 200 of asset A at initialization of the protocol, and the deposit accrual index of asset A is 1.05 at time t, then the user can withdraw 210 of asset A at time t.

  • Definition of ‘borrow interest accrual index’

    Suppose a user borrowed 1 of asset A at initialization of the protocol. (Presumably they also deposited some asset to make this borrow possible). The borrow interest accrual index of Asset A at time t can be thought of as the amount of asset A that this user would be allowed to repay at time t in order to return to not having any outstanding borrowed value.

    If user 2 borrowed 200 of asset A at initialization of the protocol, and the borrow accrual index of asset A is 1.05 at time t, then the user would have to repay 210 of asset A at time t in order to return to flat and not owe any more of asset A.

We implement this mechanism by storing the accrual index along with the users balance every time the users vault state is being updated. Using the accrual index at the time of deposit and the current accrual index we can compute how much interest (deposit or debt) has been accrued since the vaults last update. The formula for the amount with interest is:

storedAmount * currentAccrualIndex / accrualIndexAtLastUpdateTime

Specifically, for each user, we store, for each asset:

  • the deposit amount with all interest accrued up to the time of the last vault update

  • the deposit accrual index at the time of the last vault update

  • the borrowed amount with all interest accrued up to the time of the last vault update

  • the borrow accrual index at the time of the last vault update

Example

  • User deposits 100 WETH at protocol start. The accrual index is 1.0. We store the users deposit (100 WETH) and the deposit accrual index at the time of the update (1.0). Assume that due to other users actions there is some accumulated interest for WETH and the accrual index now equals 1.05. User wants to withdraw all of their deposit with accrued interest. Their max withdrawable amount is depositAmount * currentDepositAccrualIndex / depositAccrualIndexAtUpdate = 100 WETH * 1.05 / 1.00 = 105 WETH

  • User wants to borrow 1000 USDC. The borrow accrual index at the time of the borrow is 2.75. We store the users debt (1000 USDC) and the borrow accrual index at the time of the vault update (2.75). Assume that after a year some interest is accrued on the users debt and the borrow accrual index for USDC now equals 3.3. The user owes a total of borrowAmount * currentBorrowAccrualIndex / borrowAccrualIndexAtUpdate = 1000 USDC * 3.3 / 2.75 = 1200 USDC

  • Assume the scenario from the previous example. User borrowed 1000 USDC when the borrow accrual index was 2.75 and the current accrual index is 3.3. The users total debt is 1200 USDC. User wants to repay 600 USDC. We first compute their total debt from current and stored accrual indices as in the example above. The total debt is 1200 USDC. The user then repays 600 USDC. We now store the updated total borrow amount (600 USDC) and the updated accrual index at the time of last vault update (3.3).

All that remains to decide is how these interest accrual indices change over time. Deciding this is what determines the interest rate model.

We chose an approach where both for the borrows and deposits the accumulated interest increases the the debt and deposits continuously. Meaning the interest on your debt is subject to the borrow interest as well. The same is true for the deposits. The interest on your deposit is subject to the deposit interest. In other words, the interest is compounded for both your debt and deposits.

The interest accrual indices are handled by HubInterestUtilities.updateAccrualIndices() function.

We can state that the APY is calculated as a result of second-compounding a yearly rate R. The yearly rate R is a result of applying a piecewise interest rate function that depends on the momentary pool utilization at the time of the accrual index computation.

The formula is: APY = (1 + R/sec_in_year)^sec_in_year – 1

Interest model

We chose a piecewise interest (PiecewiseInterestRate) model with only 3 kinks (effectively 2 linear functions separated by the second kink). The borrow interest rate rises slowly along with liquidity utilization (total borrows / total deposits) until the utilization hits the second kink. Then the borrow rate starts to rise rapidly. The kink's thresholds as well as the borrow rates are configured per asset and adjusted continuously based on the current market conditions.

Borrow interest distribution

  • 40% of the borrow interest is distributed directly to the depositors, proportionally to their deposits

  • The remaining 60% goes to the treasury from which it's distributed as rewards for vlSYNO stakers, TSYNO stakers and protocol fees

    • The 60% is defined in the reserve factor BaseInterestRate.reserveFactor

Collateralization ratios

In order to keep protocol solvent we introduced supply and borrow factors. Because assets have different volatility, every asset has an individual set of supply and borrow factors.

Collateralization ratios are stored per asset in AssetRegistry.assetInfos in a HubSpokeStructs.AssetInfo struct.

Supply factor

Effectively decreases your deposits power to collateralize your loans. If supply factor is 0.9, your $1000 worth of deposit can collateralize up to $900 worth of a loan.

In the code it's stored under HubSpokeStructs.AssetInfo.collateralizationRatioDeposit.

Supply factor = 1 / collateralizationRatioDeposit

Borrow factor

Effectively increases your loan weight. If borrow factor is 0.8, your $800 worth of loan weights $1000 in terms of your portfolio health $800 / 0.8 = $1000 .

In the code it's stored under HubSpokeStructs.AssetInfo.collateralizationRatioBorrow.

Borrow factor = 1 / collateralizationRatioBorrow

How do supply and borrow factors act together?

  • If you deposit $1000 worth of token A

  • Token A supply factor is 0.9

  • Token B borrow factor is 0.8

  • You can borrow $720 worth of token B ($1000 * 0.9 * 0.8 = $720)

Beware that such a loan would put your collateralization ratio at exactly 100%, meaning that any price movement do your detriment will make a part of you position liquifiable.

Collateralization ratio

You collateralization ratio is ratio between your effective deposits power and effective loans weights and changes over time as the $ values of your deposits and loans change.

Example:

  • Your A token deposit is worth $1000, supply factor is 0.9

  • Your B token deposit is worth $500, supply factor is 0.8

  • Your C token loan is worth $300, borrow factor is 0.75

  • Your C token loan is worth $400, borrow factor is 0.85

Your effective deposits power is $1300 ($1000 * 0.9 + $500 * 0.8 = $1300)

Your effective loan weight is $870.58 ($300 / 0.75 + $400 / 0.85 = $870.59)

Your collateralization ratio is 149% (1300 / 870.58 * 100% = 149%)

Liquidations

In terms of liquidations, your whole portfolio acts as one. When your portfolio goes underwater (your collateralization ratio falls below 100%) any volunteer is allowed to liquidate a part of your loans in order to bring it back to healthy collateralization.

A liquidator can choose which of your loans they want to liquidate and which collateral they want to receive in return.

Each asset has a maxLiquidationPortion and a maxLiquidationBonus that determines how much of that asset can be repaid in a liquidation and how much of that asset can be claimed as payment + reward to the liquidator.

The other limitation is that after liquidation the collateralization ratio of your portfolio cannot exceed max health factor (LiquidationCalculator.maxHealthFactor). If max health factor is 1.25, liquidation can bring your portfolio up to 125% collateralization ratio. This protects your portfolio from being overliquidated and provides a buffer to prevent immediate subsequent liquidations.

Liquidation bonus (specified per asset) is paid to the liquidator from your collateral (deposit). It's in your best interest to repay the loan yourself or to recollateralize it with a deposit, before it's liquidated.

In order to perform a liquidation a liquidator can call Hub.liquidation() function.

Last updated