codehawks-2023-07-dsc-m07
[M-07] Lack of fallbacks for price feed oracle
Summary
Chainlink 가격 데이터가 오래된 경우 단순히 revert 한다. 하나의 가격 피드에만 의존한다면 한쪽에 장애가 발생했을 때 대처할 수 없다. 따라서 여러가지 오라클을 이용하여 대비하는 게 좋다.
Keyword
chainlink price oracle, business logic vul
Vulnerability
staleCheckLatestRoundData 함수에서는 Chainlink 가격 피드에서 담보 토큰의 가격 정보를 얻는다.
프로토콜에서는 가격 피드 데이터가 오래되면 revert 하여 잘못된 가격을 이용하지 않도록 방지한다.
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);
}Chainlink의 aggregator가 가격 업데이트에 실패하면 가격 피드가 업데이트 되지 않는다. 만약 토큰의 가격이 급락하는 때에 aggregator가 가격을 업데이트 하지 못했다면 어떨까?
담보의 가격이 떨어져 담보 비율이 200% 아래로 떨어지면 liquidate를 호출해 프로토콜이 저담보가 되는 것으로부터 막아야 한다. 하지만 Chainlink의 가격 정보가 업데이트 되지 않아 오래되었기 때문에 revert 된다.
따라서 가격 정보가 오래된 상황에 단순히 revert 하는 것보다 대체적인 방법을 제공하는 게 좋다.
Impact
Chainlink 가격 정보가 업데이트 되지 못한 경우, 프로토콜이 상황에 대처할 수 없다. 담보의 가격이 떨어지는 상황에 liquidate 를 호출할 수 없어 프로토콜이 파산할 수 있다.
Mitigation
여러가지 price oracle을 이용하여 실패 상황에 대비한다. 예를 들어 Chainlink 가격 피드에서 실패한 경우 Uniswap의 TWAP을 이용한다.
Memo
Chainlink 관련 취약점은 다 템플릿이 있는 것 같다. 중복은 많겠지만, 그래도 Chainlink는 자주 사용되므로 체크리스트를 두고 나올 때마다 확인을 해보면 좋겠다.
tags: bughunting, codehawks, smart contract, solidity, business-logic-vul, chainlink, price oracle, severity medium