StableDebtToken
https://docs.aave.com/developers/v/2.0/the-core-protocol/debt-tokens
Last updated
https://docs.aave.com/developers/v/2.0/the-core-protocol/debt-tokens
Last updated
We will examine stableDebtToken contract in this section. Note that debt tokens cannot be transferred and therefore do not have their related functions.
This function is called in .cache, and we will explain each component.
Inherited from IncentivizedERC20.sol
Essentially a getter function for the internal storage variable _totalSupply
On _totalSupply:
Reflects total stable debt, accounting for interest accrued from inception till _totalSupplyTimestamp
.
Does not account for interest accrued from _totalSupplyTimestamp
to now.
Represents total stable debt, accounting for interest accrued since inception till _totalSupplyTimestamp
.
_totalSupply
is incremented on mint
, decremented on burn
.
Example: a stable borrow is taken some time after _totalSupplyTimestamp
_totalSupply += stableBorrowAmount + unbooked interest
_totalSupply
is incremented to account for the incoming borrow as well as the interest accrued in the period since _totalSupplyTimestamp
.
Assigned to currPrincipalStableDebt, in .cache
_totalSupply
is declared in IncentivizedERC20
_totalSupplyTimestamp
is declared in StableDebtToken
Calculates total stable debt, accounting for interest accrued to date.
avgRate
is _avgStableRate
principalSupply is _totalSupply
calculates interest compounded from _totalSupplyTimestamp
till now (block.timestamp
)
_totalSupplyTimestamp
: Timestamp of the last update of _totalSupply
updated in mint
& burn
Assigned to currTotalStableDebt
, in .cache
Why do we calculate interest from _totalSupplyTimestamp
?
Every time mint
or burn
is called, _totalSupply
is updated such that it accounts for the interest accrued since previous update till now, as well as the mint
/burn
amount.
For example, at the start of mint
From this, we can see that _totalSupply
is updated with the interest accrual from previous timestamp till now.
Since this occurs on each function call that would modify _totalSupply
, the definition of principalStableDebt is to distinguish from accounted interest and floating, unaccounted interest.
internal storage variable
weighted average rate, calculated across all stable borrows
Simply put, assume there are 3 stable borrows at differing times:
1: 100 DAI at 1%
2: 200 DAI at 2%
3: 300 DAI at 3%
weighted average rate = (100 * 1%) + (200 * 2%) + (300 * 3%) / (100 + 200 + 300) = 2.3%
_avgStableRate = 2.3%
ReserveCache contains the following:
currPrincipalStableDebt => super.totalSupply()
currTotalStableDebt => _calcTotalSupply(avgRate)
currAvgStableBorrowRate => _avgStableRate
stableDebtLastUpdateTimestamp => _totalSupplyTimestamp
Also
nextAvgStableBorrowRate = currTotalStableDebt
nexTotalStableDebt = currAvgStableBorrowRate
The balance for any address is calculated to account for interest accrued since the last interaction.
each user's stable rate is stored at _user[account].additionalData
_timestamps[account]
stores the timestamp of their last interaction
Declared on StableDebtToken.sol.
_calcTotalSupply(_avgStableRate)
super.TotalSupply()
returns _totalSupply
; accounts for interest from inception till _totalSupplyTimestamp
.
_calcTotalSupply
will compound this with the recently accrued interest, from _totalSupplyTimestamp
till now.
Therefore, totalSupply
returns the total stable debt, accounting for all interest to date.
Let's examine mint, from the pretext that is has been called via executeBorrow
.
mint
is called via the interface IStableDebtToken
, reserve.currentStableBorrowRate
is passed as a param.
variable is cached to avoid unnecessary calls to storage: currentStableRate
calculates the increase in balance due to compounding interest, for a specific user, since the previous
_totalSupply
is updated to be previousSupply + amount
previousSupply
reflects total stable debt and recently accrued interest as explained in totalSupply
hence, _totalSupply
is incremented to account for both unbooked interest and incoming borrow.
reserve.currentStableBorrowRate
is passed as rate
.
From now till the next future interaction, interest will compound at the nextStableRate.
This is reflected in balanceOf, in _calculateBalanceIncrease section.
increments user's balance by amount
makes a call to _incentivesController, should it be defined
The maximum 128-bit integer, is a number that is not usefully written out in words or in all of its 39 digits: 340282366920938463463374607431768211455
Here it is in words:
three hundred forty undecillion, two hundred eighty-two decillion, three hundred sixty-six nonillion, nine hundred twenty octillion, nine hundred thirty-eight septillion, four hundred sixty-three sextillion, four hundred sixty-three quintillion, three hundred seventy-four quadrillion, six hundred seven trillion, four hundred thirty-one billion, seven hundred sixty-eight million, two hundred eleven thousand, four hundred fifty-five
nextSupply
currentAvgStableRate
This function is typically called through repay, when the user wishes to repay all or some of his stable debt.
_calculateBalanceIncrease
currentBalance
accounts for latest interest, updated to block.timestamp
balanceIncrease
: increase in interest, acrrued between last update and now
previousSupply = totalSupply()
get total supply of stable debt
calculated via _calcTotalSupply(_avgStableRate)
get user's stable rate: _userState[from].additionalData
if (totalSupply <= amount)
:
A discrepancy arises, such that there is no debt to repay; this is possible because total debt accrues seperately from each user's individual debt.
if there is discrepancy, simply reset total supply & avgStableRate to 0.
user's debt, which he try repaying is the remainding global debt.
Else
:
update _totalSupply = previousSupply - amount
[store in local variable nextSupply
]
Discrepancy:
Similar to before, there might be a discrepancy arising due to global rate and user's rate being tracking independently.
To identify if such a discrepancy exists:
if userRate * userBalance > avgRate * totalSupply
, reset both totalSupply and avgStableRate.
note that totalSupply
has been updated, less the amount to burn
Otherwise, update avgRate as per nextAvgStableRate
calculation.
nextAvgStableRate
: [(avgRate * totalSupply) - (userRate * userBalance)] / (totalSupply - amount)
if amount == user's updated balance:
reset user's stabel rate
reset user's lastUpdatedTimestamp -> no more debt. repaid in full. else:
just update user's lastUpdatedTimestamp
Global _totalSupplyTimestamp
is updated as well
Depends if accrued interest > user input
if(balanceIncrease > amount): mint the difference
else: burn the difference