5/5
## The DeFi Dilemma: Tracking Balances with Ever-Changing Interest Rates In decentralized finance (DeFi), lending and borrowing protocols often feature variable interest rates that can change frequently, potentially with every block or even more granularly, compounding interest second by second. Directly updating every user's supplied balance or outstanding debt in real-time to reflect these continuous interest accruals would be computationally prohibitive on a blockchain. Such an approach would lead to exorbitant gas costs and network congestion, making the protocol impractical to use. DeFi protocols, therefore, require an efficient and scalable mechanism to accurately track user balances without constant on-chain updates for each user. ## Introducing Scaled Balances: A `Bank.sol` Primer To understand how DeFi protocols tackle this challenge, let's consider a simplified smart contract, `Bank.sol`. This example illustrates the foundational concept of "scaled" or "normalized" balances. The core idea is to avoid storing the raw, absolute value of a user's debt (or supplied assets). Instead, the contract stores a scaled representation of this debt. This is achieved through a key variable: * **`cumulativeRates`**: This global variable tracks the aggregate interest rate applied over time. As interest accrues, `cumulativeRates` increases, reflecting the total growth factor since the protocol's inception or a specific epoch. When a user interacts with the protocol: * **Borrowing:** Before a user's debt balance is updated, the `cumulativeRates` variable is brought up-to-date to reflect the latest interest. The amount the user wishes to borrow is then *divided* by the current `cumulativeRates` before being added to their stored, scaled debt. ```solidity // Conceptual logic from Bank.sol function borrow(uint256 amount) external { updateCumulativeRates(); // Ensures cumulativeRates reflects all accrued interest // debts[msg.sender] stores the scaled debt amount // Assuming 1e18 is used as a precision factor (e.g., RAY for Aave) debts[msg.sender] += (amount * 1e18) / cumulativeRates; } ``` * **Repaying:** Similarly, when a user repays, the `cumulativeRates` is updated. The repayment amount is also divided by the current `cumulativeRates` before being subtracted from their stored scaled debt. ```solidity // Conceptual logic from Bank.sol function repay(uint256 amount) external { updateCumulativeRates(); debts[msg.sender] -= (amount * 1e18) / cumulativeRates; } ``` With this mechanism, the `debts[msg.sender]` value—the stored scaled debt—does not need to be modified every second as interest accrues. The actual, current debt can be calculated at any point by multiplying the user's stored scaled debt by the current `cumulativeRates`. This calculation is typically performed off-chain for display purposes or on-chain when another transaction necessitates knowing the true balance. ## How Aave V3 Implements Scaled Balances with `ScaledBalanceTokenBase.sol` Aave V3, a leading DeFi lending protocol, employs a more sophisticated and precise version of this scaled balance technique. The core logic is encapsulated within a base contract named `ScaledBalanceTokenBase.sol`. In Aave V3: * When users supply assets (e.g., DAI), they receive corresponding **A-Tokens** (e.g., aDAI), which are interest-bearing tokens. * When users borrow assets, their debt is represented by **Variable Debt Tokens** (e.g., variableDebtDAI). Both A-Tokens and Variable Debt Tokens inherit crucial functionality from `ScaledBalanceTokenBase.sol`. This contract utilizes an **`index`** variable, which serves a similar purpose to `cumulativeRates` in our simplified `Bank.sol` example. * For A-Tokens (supplied assets), this is the **liquidity index**, tracking the cumulative interest earned by suppliers. * For Variable Debt Tokens (borrowed assets), this is the **variable debt index**, tracking the cumulative interest accrued on borrows. The minting (issuing new tokens upon supply/borrow) and burning (redeeming tokens upon withdrawal/repayment) operations are primarily handled by internal functions `_mintScaled` and `_burnScaled` within `ScaledBalanceTokenBase.sol`. ### The `_mintScaled` Function: Issuing Interest-Bearing and Debt Tokens The `_mintScaled` internal function is invoked when A-Tokens need to be minted (e.g., a user deposits collateral) or Variable Debt Tokens are issued (e.g., a user borrows an asset). 1. **Scaling the Amount:** The actual `amount` of the underlying asset being supplied or borrowed is scaled down. This is done by dividing the `amount` by the current `index` (either the liquidity index or the variable debt index, depending on the operation). Aave uses a high-precision division function, `rayDiv`, for this. ```solidity // Inside ScaledBalanceTokenBase.sol - _mintScaled function (conceptual representation) // uint256 amount: actual amount of the underlying asset // uint256 index: current cumulative interest rate index (liquidity or variable debt) uint256 amountScaled = amount.rayDiv(index); ``` This `amountScaled` is the normalized value that gets recorded. 2. **Updating User State:** The contract also records the current `index` at which this transaction occurs for the specific user (identified as `onBehalfOf`). This stored index is crucial because it marks the user's last interaction point, allowing for accurate interest calculation on their balance since that last event. ```solidity // Simplified representation of user state update (around 0:44 in video) // _userState is a mapping storing user-specific data. // additionalData (part of the user's state struct) stores the last interaction index. _userState[onBehalfOf].additionalData = index.toUint128(); ``` 3. **Minting Scaled Tokens:** Finally, the standard ERC20 `_mint` function is called, but with the `amountScaled` value. This means the user's balance of A-Tokens or Variable Debt Tokens directly reflects this scaled, normalized amount, not the raw underlying asset amount. ```solidity // Simplified representation of minting scaled tokens (around 1:04 in video) _mint(onBehalfOf, amountScaled.toUint128()); ``` ### The `_burnScaled` Function: Redeeming Assets and Repaying Debt The `_burnScaled` internal function is the counterpart to `_mintScaled`. It's called when A-Tokens are burned (e.g., a user withdraws their supplied collateral) or Variable Debt Tokens are burned (e.g., a user repays their loan). 1. **Scaling the Amount:** Similar to the minting process, the actual `amount` of the underlying asset being withdrawn or repaid is scaled down by dividing it by the current `index`. ```solidity // Inside ScaledBalanceTokenBase.sol - _burnScaled function (conceptual representation) // uint256 amount: actual amount of the underlying asset // uint256 index: current cumulative interest rate index uint256 amountScaled = amount.rayDiv(index); ``` 2. **Updating User State:** The user's last interaction `index` within their state is also updated to the current `index`. ```solidity // Simplified representation of user state update (around 1:07 in video) _userState[user].additionalData = index.toUint128(); ``` 3. **Burning Scaled Tokens:** The standard ERC20 `_burn` function is then called with this `amountScaled`, reducing the user's balance of the scaled tokens. ```solidity // Simplified representation of burning scaled tokens (around 1:35 in video) _burn(user, amountScaled.toUint128()); ``` ## Unpacking the Efficiency: The Mechanics of Scaled Balances The core mechanism of scaled balances offers significant efficiency gains for DeFi protocols: * **Scaled Balances Stored:** Both A-Tokens (representing user supplies) and Variable Debt Tokens (representing user borrows) store balances in this "scaled" or "normalized" form. The fundamental relationship is: `stored_scaled_balance = actual_underlying_amount / index_at_time_of_operation`. * **Interest Accrual via Index:** As time progresses, the relevant `index` (liquidity index for supplies, variable debt index for borrows) automatically increases to reflect accrued interest. This index is a global accumulator for interest across the entire pool for that asset. * **Calculating Current Actual Balance:** To determine a user's current, up-to-date balance of the underlying asset (including all accrued interest), the protocol can calculate it on-demand: `current_actual_balance = stored_scaled_balance * current_index`. This calculation is typically done in view functions for front-end display or when a user initiates a new transaction that depends on their precise current balance. * **Computational Efficiency:** This system elegantly sidesteps the need to iterate through all user accounts and update each balance individually whenever interest rates change or interest compounds. Only the global `index` needs to be updated to reflect interest accrual, making the system highly scalable and gas-efficient. ## From Theory to Practice: Aave V3's Scaled Balances in DeFi Lending The Aave V3 protocol's implementation within `ScaledBalanceTokenBase.sol` is a robust and highly precise application of the core concept demonstrated by the simpler `Bank.sol` example. In both scenarios, the process for handling user interactions (deposits, borrows, withdrawals, repayments) follows a consistent pattern: 1. The actual transaction `amount` (of the underlying asset) is taken. 2. This `amount` is divided by the current global `cumulativeRates` (in the `Bank.sol` example) or the relevant `index` (liquidity or variable debt index in Aave V3). 3. The resulting "scaled amount" is then used to update the user's stored balance, which itself is a scaled value. This scaled balance accounting method is a cornerstone of modern DeFi lending and borrowing protocols. It enables them to manage vast numbers of users and transactions efficiently, even with dynamically changing interest rates and frequent compounding, ensuring the integrity and scalability essential for on-chain financial operations.
In decentralized finance (DeFi), lending and borrowing protocols often feature variable interest rates that can change frequently, potentially with every block or even more granularly, compounding interest second by second. Directly updating every user's supplied balance or outstanding debt in real-time to reflect these continuous interest accruals would be computationally prohibitive on a blockchain. Such an approach would lead to exorbitant gas costs and network congestion, making the protocol impractical to use. DeFi protocols, therefore, require an efficient and scalable mechanism to accurately track user balances without constant on-chain updates for each user.
Bank.sol
PrimerTo understand how DeFi protocols tackle this challenge, let's consider a simplified smart contract, Bank.sol
. This example illustrates the foundational concept of "scaled" or "normalized" balances.
The core idea is to avoid storing the raw, absolute value of a user's debt (or supplied assets). Instead, the contract stores a scaled representation of this debt. This is achieved through a key variable:
cumulativeRates
: This global variable tracks the aggregate interest rate applied over time. As interest accrues, cumulativeRates
increases, reflecting the total growth factor since the protocol's inception or a specific epoch.
When a user interacts with the protocol:
Borrowing: Before a user's debt balance is updated, the cumulativeRates
variable is brought up-to-date to reflect the latest interest. The amount the user wishes to borrow is then divided by the current cumulativeRates
before being added to their stored, scaled debt.
Repaying: Similarly, when a user repays, the cumulativeRates
is updated. The repayment amount is also divided by the current cumulativeRates
before being subtracted from their stored scaled debt.
With this mechanism, the debts[msg.sender]
value—the stored scaled debt—does not need to be modified every second as interest accrues. The actual, current debt can be calculated at any point by multiplying the user's stored scaled debt by the current cumulativeRates
. This calculation is typically performed off-chain for display purposes or on-chain when another transaction necessitates knowing the true balance.
ScaledBalanceTokenBase.sol
Aave V3, a leading DeFi lending protocol, employs a more sophisticated and precise version of this scaled balance technique. The core logic is encapsulated within a base contract named ScaledBalanceTokenBase.sol
.
In Aave V3:
When users supply assets (e.g., DAI), they receive corresponding A-Tokens (e.g., aDAI), which are interest-bearing tokens.
When users borrow assets, their debt is represented by Variable Debt Tokens (e.g., variableDebtDAI).
Both A-Tokens and Variable Debt Tokens inherit crucial functionality from ScaledBalanceTokenBase.sol
. This contract utilizes an index
variable, which serves a similar purpose to cumulativeRates
in our simplified Bank.sol
example.
For A-Tokens (supplied assets), this is the liquidity index, tracking the cumulative interest earned by suppliers.
For Variable Debt Tokens (borrowed assets), this is the variable debt index, tracking the cumulative interest accrued on borrows.
The minting (issuing new tokens upon supply/borrow) and burning (redeeming tokens upon withdrawal/repayment) operations are primarily handled by internal functions _mintScaled
and _burnScaled
within ScaledBalanceTokenBase.sol
.
_mintScaled
Function: Issuing Interest-Bearing and Debt TokensThe _mintScaled
internal function is invoked when A-Tokens need to be minted (e.g., a user deposits collateral) or Variable Debt Tokens are issued (e.g., a user borrows an asset).
Scaling the Amount: The actual amount
of the underlying asset being supplied or borrowed is scaled down. This is done by dividing the amount
by the current index
(either the liquidity index or the variable debt index, depending on the operation). Aave uses a high-precision division function, rayDiv
, for this.
This amountScaled
is the normalized value that gets recorded.
Updating User State: The contract also records the current index
at which this transaction occurs for the specific user (identified as onBehalfOf
). This stored index is crucial because it marks the user's last interaction point, allowing for accurate interest calculation on their balance since that last event.
Minting Scaled Tokens: Finally, the standard ERC20 _mint
function is called, but with the amountScaled
value. This means the user's balance of A-Tokens or Variable Debt Tokens directly reflects this scaled, normalized amount, not the raw underlying asset amount.
_burnScaled
Function: Redeeming Assets and Repaying DebtThe _burnScaled
internal function is the counterpart to _mintScaled
. It's called when A-Tokens are burned (e.g., a user withdraws their supplied collateral) or Variable Debt Tokens are burned (e.g., a user repays their loan).
Scaling the Amount: Similar to the minting process, the actual amount
of the underlying asset being withdrawn or repaid is scaled down by dividing it by the current index
.
Updating User State: The user's last interaction index
within their state is also updated to the current index
.
Burning Scaled Tokens: The standard ERC20 _burn
function is then called with this amountScaled
, reducing the user's balance of the scaled tokens.
The core mechanism of scaled balances offers significant efficiency gains for DeFi protocols:
Scaled Balances Stored: Both A-Tokens (representing user supplies) and Variable Debt Tokens (representing user borrows) store balances in this "scaled" or "normalized" form. The fundamental relationship is: stored_scaled_balance = actual_underlying_amount / index_at_time_of_operation
.
Interest Accrual via Index: As time progresses, the relevant index
(liquidity index for supplies, variable debt index for borrows) automatically increases to reflect accrued interest. This index is a global accumulator for interest across the entire pool for that asset.
Calculating Current Actual Balance: To determine a user's current, up-to-date balance of the underlying asset (including all accrued interest), the protocol can calculate it on-demand: current_actual_balance = stored_scaled_balance * current_index
. This calculation is typically done in view functions for front-end display or when a user initiates a new transaction that depends on their precise current balance.
Computational Efficiency: This system elegantly sidesteps the need to iterate through all user accounts and update each balance individually whenever interest rates change or interest compounds. Only the global index
needs to be updated to reflect interest accrual, making the system highly scalable and gas-efficient.
The Aave V3 protocol's implementation within ScaledBalanceTokenBase.sol
is a robust and highly precise application of the core concept demonstrated by the simpler Bank.sol
example. In both scenarios, the process for handling user interactions (deposits, borrows, withdrawals, repayments) follows a consistent pattern:
The actual transaction amount
(of the underlying asset) is taken.
This amount
is divided by the current global cumulativeRates
(in the Bank.sol
example) or the relevant index
(liquidity or variable debt index in Aave V3).
The resulting "scaled amount" is then used to update the user's stored balance, which itself is a scaled value.
This scaled balance accounting method is a cornerstone of modern DeFi lending and borrowing protocols. It enables them to manage vast numbers of users and transactions efficiently, even with dynamically changing interest rates and frequent compounding, ensuring the integrity and scalability essential for on-chain financial operations.
An essential guide to Understanding Scaled Balances: Aave V3's Gas-Efficient Accounting - Learn why constantly updating DeFi user balances for variable interest is impractical and costly. Discover Aave V3's elegant solution in `ScaledBalanceTokenBase.sol`, using scaled amounts and a dynamic `index` for efficient, on-demand balance calculations.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Course Overview
About the course
Aave V3 core functionalities and key features
APY & APR, market forces, utilization rates, interest rate models
Reserves, ATokens, debt tokens, liquidity and borrow index
Aave smart contracts architecture
Supply, borrow, repay, withdrawal, liquidation
Compound interest
Reserve factors, liquidation pricing, credit delegation, LTV
Aave V3 flash loans
How to buy long and sell short using Aave V3
How to build a functional app to buy long, sell short, and close a position.
Last updated on July 25, 2025
Duration: 8min
Duration: 49min
Duration: 43min
Duration: 12min
Course Overview
About the course
Aave V3 core functionalities and key features
APY & APR, market forces, utilization rates, interest rate models
Reserves, ATokens, debt tokens, liquidity and borrow index
Aave smart contracts architecture
Supply, borrow, repay, withdrawal, liquidation
Compound interest
Reserve factors, liquidation pricing, credit delegation, LTV
Aave V3 flash loans
How to buy long and sell short using Aave V3
How to build a functional app to buy long, sell short, and close a position.
Last updated on July 25, 2025