Scaling and ATokens
Previously we explained how deposits were scaled against the liquidity index to reflect every user's unique starting point in the timeseries of interest accumulation.
That brings us to the topic of ATokens and the question of how they are minted - on the basis of the scaled value of deposit or otherwise.
ATokens
Atokens are interest-bearing tokens that represent a user's share in the underlying deposited assets. When users deposit funds into the Aave protocol, they receive Atokens in return, which represent their entitlement to a portion of the pool's reserves.
A depositor's balance of aTokens will increment over time as interest is accrued.
Example:
You deposit 100 DAI and are minted 100 aDAI token.
Over time, your aDAI balance will increment beyond 100, reflecting interest accrued.
When you look to withdraw in full, you will receive more than 100 DAI.
Therefore, the growth of aToken balance reflects the interest earned on deposits over a period.
Now we run into a contradiction. In the earlier example on scaling positions, we saw that a user who deposited 1000 DAI when the liquidity index was 1.1, had his deposit scaled to 909.
Does this mean that he is minted 909 aDAI? Yes and no:
user will see that he has 1000 aDAI in his wallet
however, the amount parameter passed into
mintwill be thescaledbalanceof 909
To make more sense of this, let's look at how balanceOf works in the context of aTokens.
AToken: balanceOf
balanceOfAave implements a modified version of the ERC-20 standard for its aTokens, such that the balance of aTokens increments without any transactions.
Let's examine the implementation for balanceOf:
Notice the use of override - it serves to override balanceOf functions declared within its inheritance tree, so that the parent functions do not get called.
A user's aToken balance is the multiplication of two components:
super.balanceOfPOOL.getReserveNormalizedIncome()
In a more digestible form, this basically translates to:
super.balanceOf(user) * POOL.getReserveNormalizedIncome(_underlyingAsset)
scaledBalance * currentLiquidityIndexExecution flow:

super.BalanceOf
super.BalanceOf Each user has a struct,
UserStateassociated with their address via the mapping_userStateThe
balanceelement within theUserStatestores user's scaled balancesuper.balanceOfreturns_userState[account].balance
super.BalanceOf returns the scaled balance for a user.
POOL.getReserveNormalizedIncome()
POOL.getReserveNormalizedIncome()
You might wonder what calculateLinearInterest does, we will explain this in a later section. For now you can operate on the understanding that getReserveNormalizedIncome returns the latest liquidity index, referred to as currentLiquidityIndex.
So in conclusion,
super.balanceOf(user) * POOL.getReserveNormalizedIncome(_underlyingAsset)
_userState[account].balance * currentLiquidityIndex
userState.balance * currentLiquidityIndex
"scaledBalance" * "latest liquidity Index"user deposits 1000 DAI, when Index = 1.1
scaledBalance = 909
_userState[account].balance = 909
AToken: Incrementation
The scaledBalance of a user is fixed, while the currentLiquidityIndex increments with every state-changing transaction, reflecting accrued interest. Due to this characteristic of the index, users' token balance increases with no action on their part.
AToken: mint
Earlier, we stated that instead of the deposit amount, the scaled amount is passed into the mint function. We will understand why from this section.
Execution flow
AToken::mint -> ScaledBalanceTokenBase::_mintScaled -> MintableIncentivizedERC20::_mint

The abovementioned scaling can be seen from the first line in _mintScaled. Subsequently, amountScaled is passed into _mint, which increments the user's balance which is captured in _userState[account].balance.

Execution flow: Visual Aid
Here is a more complete execution flow chart spanning the relevant portions across different contracts.
Last updated
Was this helpful?
