codehawks-2023-07-dsc-m02

[M-02] DSC protocol can consume stale price data or cannot operate on some EVM chains

보고서

Summary

체인별, 토큰별로 Chainlink price oracle이 업데이트 되는 주기가 다르다. 따라서 일괄적으로 3시간의 유효기간을 이용하는 것은 옳지 않다.

Keyword

chainlink price oracle

Vulnerability

프로토콜에서는 chainlink 가격 오라클이 업데이트 된 지 3시간이 지나면 가격 정보가 오래된 것으로 판단하고 revert 한다.

@>  uint256 private constant TIMEOUT = 3 hours; // 3 * 60 * 60 = 10800 seconds
 
    function staleCheckLatestRoundData(AggregatorV3Interface priceFeed)
        public
        view
        returns (uint80, int256, uint256, uint256, uint80)
    {
        (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
            priceFeed.latestRoundData();
 
        uint256 secondsSince = block.timestamp - updatedAt;
@>      if (secondsSince > TIMEOUT) revert OracleLib__StalePrice();
 
        return (roundId, answer, startedAt, updatedAt, answeredInRound);
    }

하지만 3시간은 이더리움, 폴리곤, BNB, 옵티미즘 체인에서는 너무 길다. 반면 아비트럼과 아발란체에서는 3시간은 너무 짧아 프로토콜이 작동할 수 없다.

ETH/USD 오라클을 예로 살펴보자. 각 체인별 오라클이 업데이트 되는 주기는 대략 다음과 같다.

또한 동일 체인에서도 담보 토큰마다 하트비트(Chainlink 가격을 업데이트하는 주기)가 다를 수 있다. 예를 들어 이더리움의 DAI/USD의 하트비트는 최대 1시간인 반면, USDT/USD의 하트비트는 최대 24시간이다.

Impact

유효기간을 너무 크게 설정하면 잘못된 담보 토큰의 가격을 이용할 수 있다. 반면 유효기간을 너무 짧게 설정하면 DSC 프로토콜이 작동하지 않을 수 있다.

Mitigation

TIMEOUT 상수 대신 따라서 담보 토큰 별 유효기간을 따로 설정할 수 있게 mapping 데이터에 저장하도록 한다.

또한 특정 담보 토큰의 유효기간을 업데이트 할 수 있도록 setter를 추가한다.


tags: bughunting, codehawks, smart contract, solidity, chainlink, price oracle, severity medium