Interest Model

Interest Rate Calculations

Definitions:

    u is the capital utilization rate of a certain token
    Compound Supply Rate: the real-time supply rate on the money market
    Compound Borrow Rate: the real-time borrow rate on the money market
    Compound Supply Rate Weight: the weight parameter of the Compound Supply Rate
    Compound Borrow Rate Weight: the weight parameter of the Compound Borrow Rate
    Compound Supply Ratio: the percentage of capital deployed on money market

Borrow Rate Model

BorrowAPR=CompoundSupplyRateWeights×CompoundSupplyRate+CompoundBorrowRateWeights×CompoundBorrowRate()+RateCurveConstant÷(1u)Borrow APR= Compound Supply Rate Weights \times Compound Supply Rate + Compound Borrow Rate Weights \times Compound Borrow Rate () + RateCurve Constant\div(1-u)
When
uu
>0.999,
RateCurveConstant÷(1u)=RateCurveConstant÷(10.999)=RateCurveConstant×1000Rate Curve Constant\div(1-u) = Rate Curve Constant \div(1-0.999)= RateCurveConstant\times1000
For assets that are not available on Compound or other money markets, Compound Supply Rate Weights=0, Compound Borrow Rate Weights=0,
In summary, there are two factors that decided the Borrow APR, the prevailing market rate that is available in the market and the capital utilization rate in the DeFiner protocol. Also, it's a non-linear model. The borrowing interest can adapt quickly if the utilization of the pool approaches a relatively high level.
Based on different parameter sets, we have three different strategies: Conservative Mode, Moderate Model, and Aggressive Model.
Parameters
Conservative Model
Moderate Model
Aggressive Model
Compound Supply
Rate Weight
0.1
0.3
0.9
Compound Borrow
Rate Weight
0.9
0.7
0.1
_RateCurveConstant
4
8
12
Below is how the borrow interest rate curve varies at different capital utilization levels based on three strategies.
Interest Model

Pseudocode:

1
function getBorrowRatePerBlock(address _token) public view returns(uint) {
2
if(isSupportedOnCompound) {
3
if (u>0.999) {
4
BorrowAPR= compoundSupplyRateWeights*(compoundSupplyRate) + compoundBorrowRateWeights*(compoundBorrowRate) + RateCurveConstant*(1000);
5
} else {
6
BorrowAPR= compoundSupplyRateWeights*(compoundSupplyRate) + compoundBorrowRateWeights*(compoundBorrowRate) + RateCurveConstant/(1-u);
7
}
8
} else {
9
if (u>0.999) {
10
BorrowAPR = RateCurveConstant*(1000);
11
} else {
12
BorrowAPR = RateCurveConstant/(1-u);
13
}
14
}
15
}
Copied!

Code:

1
function getBorrowRatePerBlock(address _token) public view returns(uint) {
2
uint256 capitalUtilizationRatio = getCapitalUtilizationRatio(_token);
3
// rateCurveConstant = <'3 * (10)^16'_rateCurveConstant_configurable>
4
uint256 rateCurveConstant = globalConfig.rateCurveConstant();
5
// compoundSupply = Compound Supply Rate * <'0.4'_supplyRateWeights_configurable>
6
uint256 compoundSupply = compoundPool[_token].depositRatePerBlock.mul(globalConfig.compoundSupplyRateWeights());
7
// compoundBorrow = Compound Borrow Rate * <'0.6'_borrowRateWeights_configurable>
8
uint256 compoundBorrow = compoundPool[_token].borrowRatePerBlock.mul(globalConfig.compoundBorrowRateWeights());
9
// nonUtilizedCapRatio = (1 - U) // Non utilized capital ratio
10
uint256 nonUtilizedCapRatio = INT_UNIT.sub(capitalUtilizationRatio);
11
12
bool isSupportedOnCompound = globalConfig.tokenInfoRegistry().isSupportedOnCompound(_token);
13
if(isSupportedOnCompound) {
14
uint256 compoundSupplyPlusBorrow = compoundSupply.add(compoundBorrow).div(10);
15
uint256 rateConstant;
16
// if the token is supported in third party (like Compound), check if U = 1
17
if(capitalUtilizationRatio > ((10**18) - (10**15))) { // > 0.999
18
// if U = 1, borrowing rate = compoundSupply + compoundBorrow + ((rateCurveConstant * 100) / BLOCKS_PER_YEAR)
19
rateConstant = rateCurveConstant.mul(1000).div(BLOCKS_PER_YEAR);
20
return compoundSupplyPlusBorrow.add(rateConstant);
21
} else {
22
// if U != 1, borrowing rate = compoundSupply + compoundBorrow + ((rateCurveConstant / (1 - U)) / BLOCKS_PER_YEAR)
23
rateConstant = rateCurveConstant.mul(10**18).div(nonUtilizedCapRatio).div(BLOCKS_PER_YEAR);
24
return compoundSupplyPlusBorrow.add(rateConstant);
25
}
26
} else {
27
// If the token is NOT supported by the third party, check if U = 1
28
if(capitalUtilizationRatio > ((10**18) - (10**15))) { // > 0.999
29
// if U = 1, borrowing rate = rateCurveConstant * 100
30
return rateCurveConstant.mul(1000).div(BLOCKS_PER_YEAR);
31
} else {
32
// if 0 < U < 1, borrowing rate = 3% / (1 - U)
33
return rateCurveConstant.mul(10**18).div(nonUtilizedCapRatio).div(BLOCKS_PER_YEAR);
34
}
35
}
36
}
Copied!

Deposit Rate Model

DepositRate=CompoundSupplyRatio×CompoundSupplyRate+BorrowRate×uDeposit Rate= CompoundSupplyRatio\times CompoundSupplyRate +BorrowRate\times u
For assets that are not available on Compound or other money markets, Compound Supply Rate Weights=0, Compound Borrow Rate Weights=0

PseudoCode

1
function getDepositRatePerBlock(address _token) public view returns(uint) {
2
uint borrowRatePerBlock = getBorrowRatePerBlock(_token);
3
uint capitalUtilRatio = getCapitalUtilizationRatio(_token);
4
5
if(!isSupportedOnCompound) {
6
DepositAPR = borrowRatePerBlock * capitalUtilRatio;
7
} else {
8
DepositAPR = borrowRatePerBlock * capitalUtilRatio + CompoundSupplyRate*(u);
9
}
10
}
Copied!

Code:

1
function getDepositRatePerBlock(address _token) public view returns(uint) {
2
uint256 borrowRatePerBlock = getBorrowRatePerBlock(_token);
3
uint256 capitalUtilRatio = getCapitalUtilizationRatio(_token);
4
if(!globalConfig.tokenInfoRegistry().isSupportedOnCompound(_token))
5
return borrowRatePerBlock.mul(capitalUtilRatio).div(INT_UNIT);
6
7
return borrowRatePerBlock.mul(capitalUtilRatio).add(compoundPool[_token].depositRatePerBlock
8
.mul(compoundPool[_token].capitalRatio)).div(INT_UNIT);
9
}
Copied!

Interest Accounting System

Definitions:
    Deposit principle: the crypto assets that users deposited
    Deposit interest: interest that the depositor earned
    Deposit storage interest: the interest that depositor accrued
    Deposit accrual interest: the deposit interest that has not accrued
    Deposit Interest per block: interest that user earned for every block
    BlocksPerYear: annual expected blocks of the blockchain
Formular:
DepositInterestRatePerBlock=BorrowAPR÷BlocksPerYearDeposit Interest Rate Per Block = BorrowAPR\div BlocksPerYear
DepositInterestPerBlock=(DepositPrinciple+DepositStorageInterest)×DepositInterestRatePerBlockDeposit Interest Per Block = (Deposit Principle+Deposit Storage Interest) \times Deposit Interest Rate Per Block
DepositInterest(blockt)=DepositInterest(blockt1))+DepositInterestPerBlockDepositInterest(block_t)=DepositInterest(block_t -_1))+DepositInterestPerBlock
BorrowAPR will be updated in the contract if there were any users who have deposits of the token performs a transaction
The interest earned between the last transaction block of the user and the latest transaction block will be accrued if the user performed a transaction and will be added to the Deposit Storage Interest.
Last modified 10d ago