code-423n4 / 2023-07-tapioca-findings

15 stars 10 forks source link

Oracle price may return stale prices #909

Closed code423n4 closed 1 year ago

code423n4 commented 1 year ago

Lines of code

https://github.com/Tapioca-DAO/tapioca-periph-audit/blob/023751a4e987cf7c203ab25d3abba58f7344f213/contracts/oracle/Seer.sol#L56

Vulnerability details

Impact

If there was a crash in the price, valuations may be inflated due to Seer always returning the higher value.

Proof of Concept

In get() of Seer.sol, the Chainlink price and Uniswap TWAP are fetched, and the higher one is returned. Chainlink should (theoretically) return the latest price, and Uniswap will return a price within a twapPeriod. This is problematic because Chainlink provides the latest price, and TWAP, by definition, is a lagging price. The result from this discrepancy is incorrect valuation.

As an illustration, consider a token called LUNA at the price of \$500. Both oracles will return the correct price (\$500). If LUNA were to crash to \$0.01, Chainlink will report its present value (\$0.01), and Uniswap will return its TWAP (~\$50).

In the above scenario, since Seer returns a higher value, a user can take out a loan using inflated LUNA valuation, resulting in toxic debt for the protocol.

Tools Used

Manual

Recommended Mitigation Steps

Consider using a circuit-breaker to revert if there is a price discrepancy. Here's an example of how it may look.

contract Seer {
    uint256 deviationTolerance = 0.01 ether;

    function get(
        bytes calldata
    ) external virtual returns (bool success, uint256 rate) {
        (uint256 low, uint256 high) = _readAll(inBase);
        int256 difference = high - low;

        if (deviationTolerance < (difference / low) {
            revert DeviationToleranceExceeded();
        }

        ...
    }
}

Assessed type

Oracle

c4-pre-sort commented 1 year ago

minhquanym marked the issue as low quality report

minhquanym commented 1 year ago

Seems intended

c4-judge commented 1 year ago

dmvt marked the issue as unsatisfactory: Invalid