Vulnerability Details
Utilization rate should be the ratio of total borrowed amount to total supplied amount:
This formula which RAAC implements is used for calculating the risk ratio of a margin position, rather than the utilization rate for lending. It should not be the ratio of total borrowed amount divided by the sum of the total supplied amount and the total borrowed amount and it should return zero if no liquidity:
function calculateUtilizationRate(uint256 totalLiquidity, uint256 totalDebt) internal pure returns (uint256) {
if (totalLiquidity < 1) {
return WadRayMath.RAY;
}
uint256 utilizationRate = totalDebt.rayDiv(totalLiquidity + totalDebt).toUint128();
return utilizationRate;
}
impact
According to formula above, when all supplied amount are borrowed, the utilization rate should be 100%, but the RAAC's implementation results in only 50%. This will result in the calculated borrowing rate being underestimated, preventing the rate from reflecting market conditions accurately.
rateData.optimalUtilizationRate = WadRayMath.RAY.percentMul(80_00);
function calculateBorrowRate(
uint256 primeRate,
uint256 baseRate,
uint256 optimalRate,
uint256 maxRate,
uint256 optimalUtilizationRate,
uint256 utilizationRate
) internal pure returns (uint256) {
uint256 rate;
if (utilizationRate <= optimalUtilizationRate) {
uint256 rateSlope = primeRate - baseRate;
uint256 rateIncrease = utilizationRate.rayMul(rateSlope).rayDiv(optimalUtilizationRate);
rate = baseRate + rateIncrease;
} else {
uint256 excessUtilization = utilizationRate - optimalUtilizationRate;
uint256 maxExcessUtilization = WadRayMath.RAY - optimalUtilizationRate;
uint256 rateSlope = maxRate - primeRate;
uint256 rateIncrease = excessUtilization.rayMul(rateSlope).rayDiv(maxExcessUtilization);
rate = primeRate + rateIncrease;
}
}
Tools Used
Manual.
Recommendations
function calculateUtilizationRate(
uint256 totalLiquidity,
uint256 totalDebt
) internal pure returns (uint256) {
if (totalLiquidity < 1) {
return 0;
}
return totalDebt.rayDiv(totalLiquidity).toUint128();
}