Summary
The ReserveLibrary.updateInterestRatesAndLiquidity()
function retrieves utilizationRate
from calculateUtilizationRate()
incorrectly, because it passes incorrect params.
Vulnerability Details
The ReserveLibrary.updateInterestRatesAndLiquidity()
function passes improper value(reserve.totalUsage
) to calculateUtilizationRate()
as param.
It should pass computedDebt
instead of reserve.totalUsage
. The following ReserveLibrary.getBorrowRate()
, ReserveLibrary.getLiquidityRate()
passes totalDebt
as param.
This could result inconsistency in calculation of rateData.currentUsageRate
and rateData.currentLiquidityRate
.
function updateInterestRatesAndLiquidity(ReserveData storage reserve,ReserveRateData storage rateData,uint256 liquidityAdded,uint256 liquidityTaken) internal {
...
uint256 totalLiquidity = reserve.totalLiquidity;
uint256 totalDebt = reserve.totalUsage;
uint256 computedDebt = getNormalizedDebt(reserve, rateData);
uint256 computedLiquidity = getNormalizedIncome(reserve, rateData);
@> uint256 utilizationRate = calculateUtilizationRate(reserve.totalLiquidity, reserve.totalUsage);
rateData.currentUsageRate = calculateBorrowRate(
rateData.primeRate,
rateData.baseRate,
rateData.optimalRate,
rateData.maxRate,
rateData.optimalUtilizationRate,
utilizationRate
);
rateData.currentLiquidityRate = calculateLiquidityRate(
utilizationRate,
rateData.currentUsageRate,
rateData.protocolFeeRate,
totalDebt
);
updateReserveInterests(reserve, rateData);
emit InterestRatesUpdated(rateData.currentLiquidityRate, rateData.currentUsageRate);
}
function getBorrowRate(ReserveData storage reserve,ReserveRateData storage rateData) internal view returns (uint256) {
uint256 totalDebt = getNormalizedDebt(reserve, rateData);
>> uint256 utilizationRate = calculateUtilizationRate(reserve.totalLiquidity, totalDebt);
return calculateBorrowRate(rateData.primeRate, rateData.baseRate, rateData.optimalRate, rateData.maxRate, rateData.optimalUtilizationRate, utilizationRate);
}
function getLiquidityRate(ReserveData storage reserve,ReserveRateData storage rateData) internal view returns (uint256) {
uint256 totalDebt = getNormalizedDebt(reserve, rateData);
>> uint256 utilizationRate = calculateUtilizationRate(reserve.totalLiquidity, totalDebt);
return calculateLiquidityRate(utilizationRate, rateData.currentUsageRate, rateData.protocolFeeRate, totalDebt);
}
Impact
The rateData.currentUsageRate
and rateData.currentLiquidityRate
vairable will be updated incorrectly.
Tools Used
Manual Review
Recommendations
Pass computedDebt
to calculateUtilizationRate()
as second param.
function updateInterestRatesAndLiquidity(ReserveData storage reserve,ReserveRateData storage rateData,uint256 liquidityAdded,uint256 liquidityTaken) internal {
...
uint256 totalLiquidity = reserve.totalLiquidity;
uint256 totalDebt = reserve.totalUsage;
uint256 computedDebt = getNormalizedDebt(reserve, rateData);
uint256 computedLiquidity = getNormalizedIncome(reserve, rateData);
// Calculate utilization rate
- uint256 utilizationRate = calculateUtilizationRate(reserve.totalLiquidity, reserve.totalUsage);
+ uint256 utilizationRate = calculateUtilizationRate(reserve.totalLiquidity, computedDebt);
...
}