Skip to content

Latest commit

 

History

History
90 lines (57 loc) · 2.98 KB

File metadata and controls

90 lines (57 loc) · 2.98 KB

Fast Khaki Raccoon

Medium

_updateExchangeRate math is wrong, bad oracles are treated as good

Summary

The bellow math performs one crucial mistake, it calculates the divergence, by using the higher value - highExchangeRate as denominator.

https://github.com/sherlock-audit/2025-01-peapods-finance/blob/main/fraxlend/src/contracts/FraxlendPairCore.sol#L552-L554

        // 1e5 * (highExchangeRate - lowExchangeRate) / highExchangeRate
        uint256 _deviation = (
            DEVIATION_PRECISION * (_exchangeRateInfo.highExchangeRate - _exchangeRateInfo.lowExchangeRate)
        ) / _exchangeRateInfo.highExchangeRate;

This will cause values that should be equal or bigger than maxOracleDeviation to still be smaller than it, further allowing borrowing when the system should be stopped due to a faulty oracle.

https://github.com/sherlock-audit/2025-01-peapods-finance/blob/main/fraxlend/src/contracts/FraxlendPairCore.sol#L555-L557

        if (_deviation <= _exchangeRateInfo.maxOracleDeviation) {
            _isBorrowAllowed = true;
        }

This bug is best shown with an example or two.

Example1 (simple one to demonstrate the math):

$$ \frac{\text{highExchangeRate} - \text{lowExchangeRate}}{\text{highExchangeRate}} = \frac{15 - 10}{15} = 33.3\% $$

From this example we have secluded that the difference between 10 and 15 would cause a 33.3% divergence, not taking into account that 5 is 50% of 10.

Example2 (realistic one):

prerequisite values
lowExchangeRate 100k
highExchangeRate 105.25k
maxOracleDeviation 5%

$$ \frac{\text{highExchangeRate} - \text{lowExchangeRate}}{\text{highExchangeRate}} = \frac{105.25k - 100k}{105.25k} = 4.98\% $$

Here even though the value difference between 100k and 105.25k is 5.25k we still pass the bellow 5% maxOracleDeviation and thus operate as normal allowing borrowers to borrow.

Root Cause

Dividing by the highExchangeRate rather than the low one.

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

There is no attack path per say, just a faulty environment where the bug would happen on occasion. Perhaps the attack would be a user to borrow at times when borrowing should be disabled, but isn't due to the faulty math.

Impact

Oracles will function normally even when the deviation exceeds _exchangeRateInfo.maxOracleDeviation. Invariant is broken. The system allows users to borrow under a state where it's checks should stop borrowing:

https://github.com/sherlock-audit/2025-01-peapods-finance/blob/main/fraxlend/src/contracts/FraxlendPairCore.sol#L555-L557

        if (_deviation <= _exchangeRateInfo.maxOracleDeviation) {
            _isBorrowAllowed = true;
        }

PoC

No response

Mitigation

Consider dividing by the low one to make the system more secure and avoid possible failures. Alternative would be to use the average between the two.