Obedient Lava Monkey
Medium
The failure to correctly update virtualUnderlyingBalance
in updateInterestRatesAndVirtualBalance
when virtual accounting is active will cause reserve desynchronization for reserves using virtual balances as the virtual balance can become out of sync with actual liquidity.
In ReserveLogic.sol, the updateInterestRatesAndVirtualBalance
function adjusts virtualUnderlyingBalance
only when liquidityAdded or liquidityTaken is greater than zero:
if (reserveCache.reserveConfiguration.getIsVirtualAccActive()) {
if (liquidityAdded > 0) {
reserve.virtualUnderlyingBalance += liquidityAdded.toUint128();
}
if (liquidityTaken > 0) {
reserve.virtualUnderlyingBalance -= liquidityTaken.toUint128();
}
}
This logic does not account for scenarios where borrowing or repayment affects the underlying liquidity but does not reflect as liquidityAdded
or liquidityTaken
. For example, when virtual balances are manually adjusted or updated indirectly, this omission can lead to desynchronized virtual balances.
Imagine a bank keeps a "virtual ledger" of its money, separate from the actual cash in its vault. If someone borrows or repays money in a way that doesn't directly update the virtual ledger, the ledger can become out of sync with the real cash. This mismatch causes the bank to miscalculate interest rates or think it has more or less money than it actually does.
- The reserve is configured with virtual accounting active.
- Borrowing or repayment indirectly affects the underlying liquidity but does not register
liquidityAdded > 0
orliquidityTaken > 0
.
- Virtual accounting logic relies on synchronization between
virtualUnderlyingBalance
and actual liquidity.
- User borrows or repays indirectly affecting liquidity.
- Virtual balance is not updated due to the lack of direct
liquidityAdded
orliquidityTaken
. - Protocol operates on desynchronized virtual balances, leading to incorrect interest rate calculations or liquidity accounting.
The protocol reserves using virtual accounting suffer from desynchronized balances, causing incorrect interest rate calculations and liquidity mismanagement.
Ensure virtualUnderlyingBalance
is always synchronized with actual liquidity changes by expanding the update logic:
if (reserveCache.reserveConfiguration.getIsVirtualAccActive()) {
reserve.virtualUnderlyingBalance = calculateActualUnderlyingBalance();
}