# 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

$$Borrow APR= Compound Supply Rate Weights  \times Compound Supply Rate + Compound Borrow Rate Weights \times Compound Borrow Rate () + RateCurve Constant\div(1-u)$$&#x20;

When  $$u$$ >0.98,

$$Rate Curve Constant\div(1-u) = Rate Curve Constant \div(1-0.98)= RateCurveConstant\times50$$&#x20;

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.&#x20;

| Parameters                                | Conservative Model | Moderate Model | Aggressive Model |
| ----------------------------------------- | :----------------: | :------------: | :--------------: |
| <p>Compound Supply </p><p>Rate Weight</p> |         0.1        |       0.3      |        0.9       |
| <p>Compound Borrow </p><p>Rate Weight</p> |         0.9        |       0.7      |        0.1       |
| \_RateCurveConstant                       |          3         |        6       |        10        |

Below is how the borrow interest rate curve varies at different capital utilization levels based on three strategies.&#x20;

![Interest Model](https://3860106678-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M90HVDtuOJ52CU9quj-%2F-Mi_XkGMekoERwpHoIMG%2F-Mi_XvGXEi1tR-kDte77%2Fimage.png?alt=media\&token=45f88805-9782-4133-92cb-8b73e96064a9)

#### Pseudocode:

```
function getBorrowRatePerBlock(address _token) public view returns(uint) {    
    if(isSupportedOnCompound) {
        if (u>0.999) {
            BorrowAPR= compoundSupplyRateWeights*(compoundSupplyRate) + compoundBorrowRateWeights*(compoundBorrowRate) + RateCurveConstant*(1000);
        } else {
            BorrowAPR= compoundSupplyRateWeights*(compoundSupplyRate) + compoundBorrowRateWeights*(compoundBorrowRate) + RateCurveConstant/(1-u);
        } 
    } else {
        if (u>0.999) {
            BorrowAPR = RateCurveConstant*(1000);
        } else {
            BorrowAPR = RateCurveConstant/(1-u);
        }
    }
}
```

#### Code:

```
function getBorrowRatePerBlock(address _token) public view returns(uint) {
    uint256 capitalUtilizationRatio = getCapitalUtilizationRatio(_token);
    // rateCurveConstant = <'3 * (10)^16'_rateCurveConstant_configurable>
    uint256 rateCurveConstant = globalConfig.rateCurveConstant();
    // compoundSupply = Compound Supply Rate * <'0.4'_supplyRateWeights_configurable>
    uint256 compoundSupply = compoundPool[_token].depositRatePerBlock.mul(globalConfig.compoundSupplyRateWeights());
    // compoundBorrow = Compound Borrow Rate * <'0.6'_borrowRateWeights_configurable>
    uint256 compoundBorrow = compoundPool[_token].borrowRatePerBlock.mul(globalConfig.compoundBorrowRateWeights());
    // nonUtilizedCapRatio = (1 - U) // Non utilized capital ratio
    uint256 nonUtilizedCapRatio = INT_UNIT.sub(capitalUtilizationRatio);

    bool isSupportedOnCompound = globalConfig.tokenInfoRegistry().isSupportedOnCompound(_token);
    if(isSupportedOnCompound) {
        uint256 compoundSupplyPlusBorrow = compoundSupply.add(compoundBorrow).div(10);
        uint256 rateConstant;
        // if the token is supported in third party (like Compound), check if U = 1
        if(capitalUtilizationRatio > ((10**18) - (10**15))) { // > 0.999
            // if U = 1, borrowing rate = compoundSupply + compoundBorrow + ((rateCurveConstant * 100) / BLOCKS_PER_YEAR)
            rateConstant = rateCurveConstant.mul(1000).div(BLOCKS_PER_YEAR);
            return compoundSupplyPlusBorrow.add(rateConstant);
        } else {
            // if U != 1, borrowing rate = compoundSupply + compoundBorrow + ((rateCurveConstant / (1 - U)) / BLOCKS_PER_YEAR)
            rateConstant = rateCurveConstant.mul(10**18).div(nonUtilizedCapRatio).div(BLOCKS_PER_YEAR);
            return compoundSupplyPlusBorrow.add(rateConstant);
        }
    } else {
        // If the token is NOT supported by the third party, check if U = 1
        if(capitalUtilizationRatio > ((10**18) - (10**15))) { // > 0.999
            // if U = 1, borrowing rate = rateCurveConstant * 100
            return rateCurveConstant.mul(1000).div(BLOCKS_PER_YEAR);
        } else {
            // if 0 < U < 1, borrowing rate = 3% / (1 - U)
            return rateCurveConstant.mul(10**18).div(nonUtilizedCapRatio).div(BLOCKS_PER_YEAR);
        }
    }
}
```

#### Deposit Rate Model

$$Deposit Rate= CompoundSupplyRatio\times CompoundSupplyRate +BorrowRate\times u$$&#x20;

For assets that are not available on Compound or other money markets, Compound Supply Rate Weights=0, Compound Borrow Rate Weights=0

#### PseudoCode

```
function getDepositRatePerBlock(address _token) public view returns(uint) {    
    uint borrowRatePerBlock = getBorrowRatePerBlock(_token);
    uint capitalUtilRatio = getCapitalUtilizationRatio(_token);
    
    if(!isSupportedOnCompound) {
        DepositAPR = borrowRatePerBlock * capitalUtilRatio;
    } else {
        DepositAPR = borrowRatePerBlock * capitalUtilRatio + CompoundSupplyRate*(u);
    }
}
```

#### Code:

```
function getDepositRatePerBlock(address _token) public view returns(uint) {
    uint256 borrowRatePerBlock = getBorrowRatePerBlock(_token);
    uint256 capitalUtilRatio = getCapitalUtilizationRatio(_token);
    if(!globalConfig.tokenInfoRegistry().isSupportedOnCompound(_token))
        return borrowRatePerBlock.mul(capitalUtilRatio).div(INT_UNIT);
    
    return borrowRatePerBlock.mul(capitalUtilRatio).add(compoundPool[_token].depositRatePerBlock
        .mul(compoundPool[_token].capitalRatio)).div(INT_UNIT);
}
```

### 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&#x20;

**Formular:**

$$Deposit Interest Rate Per Block = BorrowAPR\div BlocksPerYear$$&#x20;

$$Deposit Interest Per Block = (Deposit Principle+Deposit Storage Interest) \times Deposit Interest Rate Per Block$$&#x20;

$$DepositInterest(block\_t)=DepositInterest(block\_t -\_1))+DepositInterestPerBlock$$&#x20;

**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.**&#x20;
