code-423n4 / 2024-03-revert-lend-findings

6 stars 6 forks source link

`InterestRateModel::getRatesPerSecondX96` borrow rate to be calculated incorrectly when the utilization rate is equal to the kink #487

Closed c4-bot-2 closed 3 months ago

c4-bot-2 commented 4 months ago

Lines of code

https://github.com/code-423n4/2024-03-revert-lend/blob/main/src/InterestRateModel.sol#L58-L76

Vulnerability details

Impact

In getRatesPerSecondX96 function the calculation of the borrowRateX96 and supplyRateX96 when the utilizationRateX96 is equal to kinkX96.

When utilizationRateX96 is equal to kinkX96, the borrowRateX96 should be calculated using the multiplierPerSecondX96 and baseRatePerSecondX96 as follows:

borrowRateX96 = (utilizationRateX96 * multiplierPerSecondX96 / Q96) + baseRatePerSecondX96;

However, the current implementation calculates borrowRateX96 using the jumpMultiplierPerSecondX96 instead of multiplierPerSecondX96:

uint256 normalRateX96 = (kinkX96 * multiplierPerSecondX96 / Q96) + baseRatePerSecondX96;
uint256 excessUtilX96 = utilizationRateX96 - kinkX96;
borrowRateX96 = (excessUtilX96 * jumpMultiplierPerSecondX96 / Q96) + normalRateX96;

Since utilizationRateX96 is equal to kinkX96, excessUtilX96 will be zero, and borrowRateX96 will be equal to normalRateX96.

However, normalRateX96 is calculated using kinkX96 instead of utilizationRateX96, which is incorrect.

cause the borrow rate to be calculated incorrectly when the utilization rate is equal to the kink.

Proof of Concept

    function getRatesPerSecondX96(uint256 cash, uint256 debt)
        public
        view
        override
        returns (uint256 borrowRateX96, uint256 supplyRateX96)
    {
        uint256 utilizationRateX96 = getUtilizationRateX96(cash, debt);

        if (utilizationRateX96 <= kinkX96) {
            borrowRateX96 = (utilizationRateX96 * multiplierPerSecondX96 / Q96) + baseRatePerSecondX96;
        } else {
            uint256 normalRateX96 = (kinkX96 * multiplierPerSecondX96 / Q96) + baseRatePerSecondX96;
            uint256 excessUtilX96 = utilizationRateX96 - kinkX96;
            borrowRateX96 = (excessUtilX96 * jumpMultiplierPerSecondX96 / Q96) + normalRateX96;
        }

        supplyRateX96 = utilizationRateX96 * borrowRateX96 / Q96;
    }

Tools Used

Manual Review

Recommended Mitigation Steps

The calculation of borrowRateX96 when utilizationRateX96 is equal to kinkX96 should be updated to use multiplierPerSecondX96 instead of jumpMultiplierPerSecondX96. The corrected implementation should be:

if (utilizationRateX96 <= kinkX96) {
    borrowRateX96 = (utilizationRateX96 * multiplierPerSecondX96 / Q96) + baseRatePerSecondX96;
} else {
    uint256 normalRateX96 = (kinkX96 * multiplierPerSecondX96 / Q96) + baseRatePerSecondX96;
    uint256 excessUtilX96 = utilizationRateX96 - kinkX96;
    borrowRateX96 = (excessUtilX96 * jumpMultiplierPerSecondX96 / Q96) + normalRateX96;
}

This ensures that the borrow rate is calculated correctly when the utilization rate is equal to the kink.

Assessed type

Math

c4-pre-sort commented 4 months ago

0xEVom marked the issue as insufficient quality report

0xEVom commented 4 months ago

No stated impact

jhsagd76 commented 3 months ago

False, its <=

c4-judge commented 3 months ago

jhsagd76 marked the issue as unsatisfactory: Invalid