Math Behind The Magic — Defi Yield

Breaking down the mechanics behind Aave’s yield

Ciaran Mcveigh
10 min readJun 25, 2020

Defi: the land of opportunity. A place where you can earn up to 8–10% interest on your crypto without handing over custody of your private keys, it sounds like magic doesn’t it? I can assure you it’s not.

This article will examine the mechanics of those magical 8–10% yields and provide you with a better understanding of how they are derived. Today we’ll take a look at the Aave Defi protocol, a crypto lending platform that has taken the crypto world by storm since launching in January 2020 and now has over $144 million worth of crypto deposited with them.

Aave a Defi Protocol

A quick primer on Aave and what they do. Let’s imagine you own some crypto, maybe you currently have it on an exchange or a hardware wallet. Your crypto is an asset, Aave enables it to become an interest-bearing asset. With Aave, you can earn interest on your crypto by depositing your cryptocurrencies into an Aave “reserve pool”. These are pools of liquidity in the form of smart contracts that Aave uses to finance loans.

These smart contracts mean that you aren’t entrusting Aave with your crypto but are instead entrusting the code that they have written. You receive tokens representing the crypto that was deposited. These tokens work like bonds with a programmatic guarantee of consistent interest payments and return of the principal amount upon redemption.

By depositing along with others into a pool depositors create liquidity so that others can borrow from that pool. The one requirement of people borrowing from these pools is that they must provide collateral. The collateral is in the form of other cryptocurrencies and needs to be over collateralized.

This means that borrowers need to provide more collateral than the loan amount. This ensures that the loaned “USD (Dollar) value” can be recovered in the event of volatile crypto markets. If the collateral no longer represents the required value relative to the USD value of the loan, the borrower’s collateral can be liquidated i.e. sold on the open market to repay the outstanding loan.

As an example, let’s say I have some Ether ($200) and want to borrow some Dai (a USD pegged stable coin). If the collateralisation ratio was 200% I could put up my $200 worth of Ether as collateral and in return borrow $100 worth of Dai. I have to pay the accumulated interest on the loan and the borrowed Dai to get my Ether back.

You can borrow at a stable interest rate or a variable interest rate in the same way you can have a fixed or variable rate mortgage. The stable rate will generally work out more costly than the variable rate but provides certainty and hedges against volatility risk.

So we have depositors who pool their crypto together and borrowers who take out loans from that pool on either a variable or stable rate. For us to understand how the yield rate (savings/deposit rate) is calculated we first need to understand some key pieces of data. These include the total amount borrowed, the utilization rate of the pool and the borrowing rates, both variable and stable.

For the total borrowed from a reserve pool, we can use this simple calculation:

AmountBorrowedWithStableRate + AmountBorrowedWithVariableRate

Each crypto has its own pool. Let's use the Dai reserve pool as an example. The total borrowed figure can be compared to the overall liquidity of the pool to determine the utilization rate. The utilization rate represents how much of a pool has been loaned out. For example, if I have a pool with $100 of Dai and $80 of those Dai have been borrowed that represents a utilisation rate of 80%.

To determine how much depositors (liquidity providers) should be compensated (the saving rate) we need to see how much those borrowers are currently paying us in interest.

For variable rate borrowers, this is an easy calculation we take the amount borrowed on the variable rate and multiply it by the variable interest rate to get a “weighted variable rate” or a snapshot of expected returns for the year from variable-rate borrowers.

Dai a stable coin pegged to the US Dollar

Let’s use our example above, since Dai is pegged to USD I will represent everything in dollars (reminder: $1 = 1 Dai). Above we have $100 in the pool with $80 borrowed, let’s say that $50 are variable rate borrows and the remaining $30 are stable rate borrows. The current variable interest rate will be 4% APR (Annual Percentage Rate) and the stable rate will be 8% APR. So to calculate our “weighted variable rate” we do:

VariableBorrowed * CurrentVariableRate = WeightedVaraibleRate 
$50 * 4% = $2
50 * 0.04 = 2

Next, we need to work out our “weighted stable rate”, this calculation is a little more complicated as borrowers may have taken out their loans at different times and as a result, received different interest rates. Again this happens every day with house mortgages, the rate you’ll be offered today will be different to the rate you were offered one year ago.

Given we could have multiple stable rates we need to take an average to get a single figure that represents how much we’ll receive in interest per year. Using our example we have $30 in stable-rate loans, let’s say $20 worth was taken out today at the 8% APR quoted above and the other $10 was taken out 2 months ago when the stable rate was 2% APR. To calculate the average we need to combine these 2 numbers. We need to take into consideration how much is borrowed at each rate to get a representative result. We have $30 in stable-rate loans, therefore the $20 at 8% represents 66.66% of the total stable rate loans and the $10 at 2% represents 33.33%. See the calculation below to get the “Average Stable Rate”.

Average Stable Rate(8% * 66.66%) + (2% * 33.33%) = 6%OR((8% * $20) + (2% * $10)) / $30 = 6%

With this single figure of 6% to represent the rate of all stable loans we can use the same logic that was used with the variable rate loans to calculate the “weighted stable rate”.

StableBorrowed * AverageStableRate = WeightedStableRate 
$30 * 6% = $1.80
50 * 0.04 = 1.80

Now we have all the pieces required to calculate our “savings rate”, the savings rate calculation uses the weighted rates along with the total amount borrowed and the utilisation of the pool. The first part is as follows:

(WeightedVariableRate + WeightedStableRate) / TotalBorrowed

This calculation referred to as the “overall borrow rate”, it essentially represents a “Return on Investment” (ROI) figure, ROI is calculated using:

Source, https://www.investopedia.com/articles/basics/10/guide-to-calculating-roi.asp

Our “weighted stable rate” and “weighted variable rate” represent our net return i.e. what you have leftover once you have subtracted the initial investment. So if we lend out $80 for a year and get back $83.80 then we have received a net $3.80 in interest after we have subtracted the original loan amount of $80. Therefore in that scenario $3.80 represents our net return on investment.

They use that figure against the “cost of investment” or in our case the total amount borrowed out, $80. The multiplication of 100% is just to get it from decimal format ie 0.04 into a readable percentage ie 4%.

Let’s plug in our numbers and see what we get:

(WeightedVariableRate + WeightedStableRate) / TotalBorrowed
(2 + 1.80) / 80 = 0.0475 = 4.75%

Thus the overall borrow rate is 4.75%. However, there is one last calculation to get our savings rate. We need to multiply the overall borrow rate by the utilization rate (how much of the pool is borrowed). In this scenario, the utilization rate is 80% or 0.8 since we have a pool of $100 and $80 is borrowed.

0.0475 * 0.8 = 0.038 = 3.8%

We can therefore conclude that a depositor would get an interest rate of 3.8% for any deposits in the Dai pool. It’s worth noting that the saving rate is variable too as the inputs to the calculations are constantly changing. As an example, if I deposit $10 the utilization rate will now be 80/110 = 72.73% (changed from 80%) since the pool size has gone from $100 to $110. This, in turn, will change our savings rate. Having said this please note that normally the deposited amount relative to the pool will be small enough to not have a huge impact.

So now you know how the savings rate is calculated, let’s see it in action using real data from the Aave website and its API endpoint. Here’s a screenshot of the Aave website, specifically of the rates offered for Dai.

Let’s see what we can extract from this:

TotalBorrowed = $3,100,000
Utilisation = $3,100,000 / $4,400,000 = 0.7045 = 70.45%
VaraiableRate = 6.48%
StableRate = 8.19%
SavingRate = 4.60% (This is what we want to calculate)

We have some useful data but we’re still missing some key items like how much of the total borrowed is stable and how much is variable. To get this we can use the API. For those who don’t know what an API is, just think of it as a place where you can request additional data. You can request data through “the graph” API for Aave. Below is the JSON response I received for the Dai Pool.

Source, https://thegraph.com/explorer/subgraph/aave/protocol-multy-raw

A lot of the fields in the JSON Response should look familiar, totalBorrowsStable, totalBorrowsVariable, utilizationRate etc. The numbers may look strange, this is because Aave uses something called “Ray Math”. The simplest way to describe this is that you make the numbers very big for the math part to reduce rounding errors and then convert it back to decimal for the users to see on the website. Read more about it here. Below I’ve extracted the relevant fields we require and converted the numbers to decimal for us to complete our example. This conversion is simply dividing the number by 1000000000000000000000000000 (1e27) or by 1000000000000000000 (1e18) depending on the field.

{
"name": "Dai Stablecoin",
"totalBorrowsStable": "191727",
"totalBorrowsVariable": "2886067",
"variableBorrowRate": "0.0648", (~6.48%)
"stableBorrowRate": "0.0819", (~8.19%)
"averageStableBorrowRate": "0",
"utilizationRate": "0.7040", (~70.4%)
"totalLiquidity": "4371729",

"liquidityRate" : "0.0460" (~4.6%) (What we want to calculate)
}

Let’s see if our new data from the API matches what we saw on the website. We just need to do one quick calculation first, totalBorrowStable plus totalBorrowVariable will give us our total borrowed in this case its,

totalBorrowed = totalBorrowsStable + totalBorrowsVariable
totalBorrowed = $191,727 + $2,886,067 = $3,077,794

So now let’s compare,

WEBSITE                          |                              APIvariableBorrowRate = 6.48%       |        variableBorrowRate = 6.48%
stableBorrowRate = 8.19% | stableBorrowRate = 8.19%
totalBorrowed = $3,100,000 | totalBorrowed = $3,077,794
totalLiquidity = $4,400,000 | totalLiquidity = $4,371,729

We can see there are some slight discrepancies in our data however these are only due to rounding issues. The numbers we have are close enough for us to feel confident that the API data is reflective of what we see as a user on the website.

We have one final item to address before we do the calculation. From the API you may have noticed we get the field,

"averageStableBorrowRate": "0"

This makes no sense, we have $191,727 borrowed on the stable rate and its currently at 8.19% so how can the “average stable borrow rate” be 0. It can’t and it isn’t. I’ve spoken to the Aave team and discovered this is a temporary issue with retrieving that specific piece of data from “the graph” API. The team are working on resolving it at some point in the future. If you want to get the “average stable borrow rate” you can by requesting the data directly from the blockchain using a web3 client. To keep things simple for this article, I won’t go into the details of how this is done but have retrieved the value which you can see below:

"averageStableBorrowRate": "74317207158561776311730176"Which when converted to decimal equates to,"averageStableBorrowRate": "0.0743" (~7.43%)

We can see a slight difference between this value 7.43% and our current stable rate, 8.19%. This is expected as we have combined all the stable rate loans together. Let’s do the math.

First, we need to calculate our weighted variable and stable rates,

VariableBorrowed * CurrentVariableRate = WeightedVaraibleRate 
$2,886,067 * 6.48% = $187,017
2886067 * 0.0648 = 187017
StableBorrowed * CurrentStableRate = WeightedStableRate
$191,727 * 7.43% = $14,245
191727 * 0.0743 = 14245

Now we can use these values to get our “overall borrow rate”,

(WeightedVariableRate + WeightedStableRate) / TotalBorrowed
($187,017 + $14,245) / $3,077,794 = 0.0654 (~6.54%)
(187017 + 14245) / 3077794 = 0.0654

Then we use this value multiplied by the utilisation rate to get our savings rate,

overallBorrowRate * utilizationRate = savingsRate
6.54% * 70.4% = 4.60%
0.0654 * 0.704 = 0.0460

Finally, we have a savings rate, when we compare it to both the API and the website it matches! All three showed a “savings rate” of ~4.60%, congratulations you made it.

Hopefully, this article has helped you gain a better understanding of the underlying math in Defi, you should now have a solid grasp of how the Aave saving rate is calculated and have seen it demonstrated against a real-world example. You now know the math behind the magic!

For those versed in javascript feel free to have a look at this code snippet https://jsfiddle.net/nabvdjzq/ which runs through the calculation above.

As always any feedback is welcome and please let me know if I’ve made any mistakes. Stay tuned for part 2 where I will break down the mechanics of calculating the Aave borrow rates.

--

--