Lone Wintergreen Rattlesnake
Medium
The inconsistency in utilization rate calculations between _addInterest and _calculateInterest functions, and the actual addInterest where one subtracts borrowed amounts from available assets while the other doesn't, This inconsistency leads to incorrect utilization rate calculations and can result in interest accrual issues.
In _addInterest()
:
function _addInterest()
internal
returns (
bool _isInterestUpdated,
uint256 _interestEarned,
uint256 _feesAmount,
uint256 _feesShare,
CurrentRateInfo memory _currentRateInfo
)
{
// Pull from storage and set default return values
_currentRateInfo = currentRateInfo;
// store the current utilization rate as previous for next check
uint256 _totalAssetsAvailable = _totalAssetAvailable(totalAsset, totalBorrow, true);
_prevUtilizationRate = _totalAssetsAvailable == 0 ? 0 : (UTIL_PREC * totalBorrow.amount) / _totalAssetsAvailable;
// Calc interest
InterestCalculationResults memory _results = _calculateInterest(_currentRateInfo);
}
The vault calls the internal function _totalAssetAvailable
to get the total assets available, but this function after getting the total assets substracts totalBorrow.amount
from it, while this is a descrepancy issue as the calculation use to get _utilizationRate
in _calculateInterest()
and addInterest()
differs:
uint256 _totalAssetsAvailable = totalAsset.totalAmount(address(externalAssetVault));
uint256 _newUtilizationRate =
_totalAssetsAvailable == 0 ? 0 : (UTIL_PREC * totalBorrow.amount) / _totalAssetsAvailable;
as this doesnt substract totalBorrow.amount
which means manually calling addInterest()
sometimes will skip:
uint256 _currentUtilizationRate = _prevUtilizationRate;
uint256 _totalAssetsAvailable = totalAsset.totalAmount(address(externalAssetVault));
uint256 _newUtilizationRate =
_totalAssetsAvailable == 0 ? 0 : (UTIL_PREC * totalBorrow.amount) / _totalAssetsAvailable;
uint256 _rateChange = _newUtilizationRate > _currentUtilizationRate
? _newUtilizationRate - _currentUtilizationRate
: _currentUtilizationRate - _newUtilizationRate;
if (
_currentUtilizationRate != 0
&& _rateChange < _currentUtilizationRate * minURChangeForExternalAddInterest / UTIL_PREC
) {
emit SkipAddingInterest(_rateChange);
} else {
(, _interestEarned, _feesAmount, _feesShare, _currentRateInfo) = _addInterest();
}
as _currentUtilizationRate
will always be > _newUtilizationRate
The inconsistency in utilization rate calculations between functions leads to systematically higher _currentUtilizationRate compared to _newUtilizationRate, potentially, causing frequent skipping of interest accruals, as LendingAssetVault.sol also relied on this function to update vaults interest, making the function unreliable, with interest only accruing through external user-triggered functions.
Update both functions to use the standardized calculation