code-423n4 / 2024-02-wise-lending-findings

11 stars 8 forks source link

Chainlink price validation does not check for Round completeness which may lead to stale price. #217

Closed c4-bot-8 closed 5 months ago

c4-bot-8 commented 5 months ago

Lines of code

https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseOracleHub/OracleHelper.sol#L556 https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/WiseOracleHub/OracleHelper.sol#L714

Vulnerability details

Details

The protocol uses a system to validate the prices returned from chainlink pricefeeds. It does this by checking the chainlink status through the WiseOracleHub.chainlinkIsDead function. This calls an internal function, the OracleHelper._chainlinkIsDead, which checks the round timestamp alongside confirming against a Unitwap price oracle. However, there is an important check skipped which is to check that the current round for the chainlink feed has been completed.

Impact

Stale price may be returned from the oracle which would affect every single aspect of the protocol requiring pricefeed data, which are some of the most significant aspects of the protocol system. Deposit, withdrawal, borrowing, lending, reward systems can be affected.

Proof of Concept

This issue may occur if the chainlink oracle can not find a consensus to start a new round for any number of reasons (node congestion, round abandoned by chainlink oracle), causing potentially stale price to be returned to the protocol.

Tools Used

Manual review

Recommended Mitigation Steps

  1. Add a check to ensure the answeredInRound > roundId for the latestRoundData returned by chainlink. This may require altering the OracleHelper.getLatestRoundId to return the latestRoundData.answeredInRound variable as well or querying both variables and carrying out this check within OracleHelper._chainlinkIsDead.

  function _chainLinkIsDead(
        address _tokenAddress
    )
        internal
        view
        returns (bool)
    {
  ...........................................

 -     uint80 latestRoundId = getLatestRoundId(
 -        _tokenAddress
 -      );

+    (
+        int80 roundId,,,,uint80 answeredInRound
+       ) = priceFeed[_tokenAddress].latestRoundData();

+      if(answeredInRound < roundId) {
+             revert; }

...........................................
    }

Assessed type

Oracle

GalloDaSballo commented 5 months ago

See Bot M-03

c4-pre-sort commented 5 months ago

GalloDaSballo marked the issue as insufficient quality report

c4-judge commented 5 months ago

trust1995 marked the issue as unsatisfactory: Out of scope