Summary
Users will be charged a higher or lower fee than they should be when the Set prime rate is called this will affect the debt index in the contract.
Vulnerability Details
Lack of a state update before setting Primerate will cause issues
* @notice Sets the prime rate of the reserve
* @param newPrimeRate The new prime rate (in RAY)
*/
function setPrimeRate(uint256 newPrimeRate) external onlyPrimeRateOracle {
ReserveLibrary.setPrimeRate(reserve, rateData, newPrimeRate);
}
see
* @notice Sets a new prime rate for the reserve.
* @param reserve The reserve data.
* @param rateData The reserve rate parameters.
* @param newPrimeRate The new prime rate (in RAY).
*/
function setPrimeRate( ReserveData storage reserve,ReserveRateData storage rateData,uint256 newPrimeRate) internal {
if (newPrimeRate < 1) revert PrimeRateMustBePositive();
uint256 oldPrimeRate = rateData.primeRate;
if (oldPrimeRate > 0) {
@audit>>> uint256 maxChange = oldPrimeRate.percentMul(500);
@audit>>> uint256 diff = newPrimeRate > oldPrimeRate ? newPrimeRate - oldPrimeRate : oldPrimeRate - newPrimeRate;
@audit>>> if (diff > maxChange) revert PrimeRateChangeExceedsLimit();
}
@audit>>> rateData.primeRate = newPrimeRate;
@audit>>>update before also updateInterestRatesAndLiquidity(reserve, rateData, 0, 0);
emit PrimeRateUpdated(oldPrimeRate, newPrimeRate);
}
Updating before will make the contract updated first before apply a change in fee, max deviation can be as high as 5% for the prime change
* @notice Updates the interest rates and liquidity based on the latest reserve state.
* @dev Should be called after any operation that changes the liquidity or debt of the reserve.
* @param reserve The reserve data.
* @param rateData The reserve rate parameters.
* @param liquidityAdded The amount of liquidity added (in underlying asset units).
* @param liquidityTaken The amount of liquidity taken (in underlying asset units).
*/
function updateInterestRatesAndLiquidity(ReserveData storage reserve,ReserveRateData storage rateData,uint256 liquidityAdded,uint256 liquidityTaken) internal {
if (liquidityAdded > 0) {
reserve.totalLiquidity = reserve.totalLiquidity + liquidityAdded.toUint128();
}
if (liquidityTaken > 0) {
if (reserve.totalLiquidity < liquidityTaken) revert InsufficientLiquidity();
reserve.totalLiquidity = reserve.totalLiquidity - liquidityTaken.toUint128();
}
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(
@audit>>> 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 calculateBorrowRate(
uint256 primeRate,
uint256 baseRate,
uint256 optimalRate,
uint256 maxRate,
uint256 optimalUtilizationRate,
uint256 utilizationRate
) internal pure returns (uint256) {
if (primeRate <= baseRate || primeRate >= maxRate || optimalRate <= baseRate || optimalRate >= maxRate) {
revert InvalidInterestRateParameters();
}
uint256 rate;
if (utilizationRate <= optimalUtilizationRate) {
@audit>> uint256 rateSlope = primeRate - baseRate;
@audit>> uint256 rateIncrease = utilizationRate.rayMul(rateSlope).rayDiv(optimalUtilizationRate);
rate = baseRate + rateIncrease;
} else {
uint256 excessUtilization = utilizationRate - optimalUtilizationRate;
uint256 maxExcessUtilization = WadRayMath.RAY - optimalUtilizationRate;
@audit>> uint256 rateSlope = maxRate - primeRate;
@audit>> @audit>> uint256 rateIncrease = excessUtilization.rayMul(rateSlope).rayDiv(maxExcessUtilization);
@audit>> rate = primeRate + rateIncrease;
}
return rate;
}
Impact
This will affect the debt index of the lending contract
Tools Used
Manual Review
Recommendations
Update the state before changing the prime rate