Aloe Protocol
  • Home
  • Deployed Contracts
  • Aloe II
    • ๐ŸฆOverview
    • ๐ŸงฎMathematics
      • Adaptive LTVs
      • Borrows
      • Referrals
      • Rewards
      • Health
    • โš™๏ธMechanisms
      • Borrower.modify
      • Borrower.warn
      • Borrower.liquidate
      • Oracle Defense
      • ERC4626
    • ๐Ÿ’กTutorials
      • Using the web app
      • Getting the oracleSeed
      • Creating a manager
      • Running a liquidator
      • Updating the oracle
      • Using referrals
    • ๐Ÿ› ๏ธCode
    • ๐Ÿ›Auditor Quick Start
  • Aloe Blend
    • ๐Ÿ€Overview
      • ๐Ÿš€Creating a Pool
    • ๐ŸงฎMathematics
    • โš™๏ธMechanisms
    • ๐Ÿง‘โ€๐ŸŒพSilos
    • ๐Ÿ› ๏ธCode
      • AloeBlend.sol
      • VolatilityOracle.sol
      • Factory.sol
      • GitHub Repository
Powered by GitBook
  1. Aloe II
  2. Mathematics

Borrows

The information provided by Aloe Labs, Inc. (โ€œwe,โ€ โ€œusโ€ or โ€œourโ€) on docs.aloe.capital (the โ€œSiteโ€) is for general informational purposes only. All information on the Site is provided in good faith, however we make no representation or warranty of any kind, express or implied, regarding the accuracy, adequacy, validity, reliability, availability or completeness of any information on the Site.

Under no circumstance shall we have any liability to you for any loss or damage of any kind incurred as a result of the use of the site or reliance on any information provided on the site. Your use of the site and your reliance on any information on the site is solely at your own risk.

Accounting

In Aloe II, the Lender is responsible for tracking borrows. This means two things:

  • recording the amount each address has borrowed

  • accounting for the growth of these borrows as interest accrues

The interest compounds continuously, so borrow growth should be modeled with the exponential function:

totalBorrowst=T=totalBorrowst=0โ‹…erT\text{totalBorrows}_{t=T}=\text{totalBorrows}_{t=0} \cdot e^{rT}totalBorrowst=Tโ€‹=totalBorrowst=0โ€‹โ‹…erT

Since there are no borrows at deployment time, and different users request borrows at different times, totalBorrowst=0\text{totalBorrows}_{t=0}totalBorrowst=0โ€‹ is purely hypothetical. When a user takes on some amount of newBorrows\text{newBorrows}newBorrows, we must update the hypothetical value:

totalBorrowst=T+newBorrows=(totalBorrowst=0+x)โ‹…erT\text{totalBorrows}_{t=T} + \text{newBorrows}=(\text{totalBorrows}_{t=0} + x) \cdot e^{rT}totalBorrowst=Tโ€‹+newBorrows=(totalBorrowst=0โ€‹+x)โ‹…erT

totalBorrowst=0โ‹…erT+newBorrows=totalBorrowst=0โ‹…erT+xerT\text{totalBorrows}_{t=0} \cdot e^{rT} + \text{newBorrows}=\text{totalBorrows}_{t=0} \cdot e^{rT} + xe^{rT}totalBorrowst=0โ€‹โ‹…erT+newBorrows=totalBorrowst=0โ€‹โ‹…erT+xerT

newBorrows=xerT\text{newBorrows}=xe^{rT}newBorrows=xerT

x=newBorrowserTx=\frac{\text{newBorrows}}{e^{rT}}x=erTnewBorrowsโ€‹

So when a user calls borrow, we add xxx to borrows-at-deployment-time, and when a user calls repay, we do the opposite: subtract from borrows-at-deployment-time. This addition and subtraction applies both to the user's borrows, and to the pool's total borrowBase.

We'd be done if r were constant, but it's not๏ผthe interest rate changes with time, as a function of utilization. Instead of an elegant exponential, we get a piecewise function:

totalBorrowst={totalBorrowst=0โ‹…er0ttโ‰คT0totalBorrowst=0โ‹…er0T0er1(tโˆ’T0)T0<tโ‰คT1totalBorrowst=0โ‹…er0T0er1(T1โˆ’T0)er2(tโˆ’T1)T1<tโ‰คT2...\text{totalBorrows}_{t}= \begin{cases} \text{totalBorrows}_{t=0} \cdot e^{r_0 t} & t \leq T_0 \\ \text{totalBorrows}_{t=0} \cdot e^{r_0 T_0} e^{r_1 (t - T_0)} & T_0 \lt t \leq T_1 \\ \text{totalBorrows}_{t=0} \cdot e^{r_0 T_0} e^{r_1 (T_1 - T_0)} e^{r_2 (t - T_1)} & T_1 \lt t \leq T_2 \\ ... \end{cases}totalBorrowstโ€‹=โŽฉโŽจโŽงโ€‹totalBorrowst=0โ€‹โ‹…er0โ€‹ttotalBorrowst=0โ€‹โ‹…er0โ€‹T0โ€‹er1โ€‹(tโˆ’T0โ€‹)totalBorrowst=0โ€‹โ‹…er0โ€‹T0โ€‹er1โ€‹(T1โ€‹โˆ’T0โ€‹)er2โ€‹(tโˆ’T1โ€‹)...โ€‹tโ‰คT0โ€‹T0โ€‹<tโ‰คT1โ€‹T1โ€‹<tโ‰คT2โ€‹โ€‹

The product of this chain of exponentials is the borrowIndex. For precision, it starts at 101210^{12}1012 (instead of 1) and it gets updated in the first call to the pool in a given block. Subsequent calls in the same block do nothing because block.timestamp is the same. The update looks like:

borrowIndex *= e ** (currentRate * secondsSinceLastUpdate)

In practice we do change-of-base and implement (1 + yieldPerSecond) ** T, but the concept is the same.

As for the coefficient, totalBorrowst=0\text{totalBorrows}_{t=0}totalBorrowst=0โ€‹, we scale that up by 2322^{32}232 and call it borrowBase. Individual users have their own personal borrowBases stored in the borrows mapping (we use the expression for xxx from earlier, but scale up by 2322^{32}232 and divide by borrowIndex instead of the plain exponential).

Value
Expression

Total Borrows

borrowBase * borrowIndex / (2**32 * 10**12)

User's Borrows*

borrows[user] * borrowIndex / (2**32 * 10**12)

*In the code, we subtract one from borrows[user] because the first unit is used for whitelisting; it's not real debt.

Interest Rate

The interest rate is a function of utilization, defined in RateModel. The default RateModel is a rational function.

The supply rate (earned by lenders) is always less than the borrow rate (paid by borrowers). Given utilization UUU and reserve factor fff, they are related like so:

ratesupply=(1โˆ’1f)โ‹…Uโ‹…rateborrow\text{rate}_{supply}=(1 - \frac{1}{f}) \cdot U \cdot \text{rate}_{borrow}ratesupplyโ€‹=(1โˆ’f1โ€‹)โ‹…Uโ‹…rateborrowโ€‹

Last updated 1 year ago

๐Ÿงฎ
The blue line shows the borrow APY, and the black line shows the supply APY (assuming a 12.5% reserve factor).