Skip to content

oracle price from Chainlink might be stale due to all assets price feeds sharing the same maxChainlinkOracleTimeDelay #33

Open

Description

@code423n4

Lines of code

https://github.com/code-423n4/2023-01-ondo/blob/main/contracts/lending/OndoPriceOracleV2.sol#L77
https://github.com/code-423n4/2023-01-ondo/blob/main/contracts/lending/OndoPriceOracleV2.sol#L277-L301

Vulnerability details

Impact

maxChainlinkOracleTimeDelay is shared across all assets price feeds from Chainlink. This will cause some assets price feeds to have stale prices if the maxChainlinkOracleTimeDelay is set to a high value, and cause some assets price feeds to revert frequently if maxChainlinkOracleTimeDelay is set to a low value.

Proof of Concept

maxChainlinkOracleTimeDelay determines whether the oracle price returned from Chainlink is stale, synonomous to what other protocol calls a heartbeat.

  uint256 public maxChainlinkOracleTimeDelay = 90000; // 25 hours

The initial maxChainlinkOracleTimeDelay is 90000, 25 hours. This is not an issue as setMaxChainlinkOracleTimeDelay can override this value. The issue arises from the fact that all assets price feeds from Chainlink use the same maxChainlinkOracleTimeDeplay. Setting it to 3 hours might result in stale prices as some price feeds have heartbeats of 20 mins. Setting it to 20 mins will cause other price feeds with slower heartbeats to revert frequently due to the small tolerance that their slower heartbeats cannot meet.

  function getChainlinkOraclePrice(
    address fToken
  ) public view returns (uint256) {
    require(
      fTokenToOracleType[fToken] == OracleType.CHAINLINK,
      "fToken is not configured for Chainlink oracle"
    );
    ChainlinkOracleInfo memory chainlinkInfo = fTokenToChainlinkOracle[fToken];
    (
      uint80 roundId,
      int answer,
      ,
      uint updatedAt,
      uint80 answeredInRound
    ) = chainlinkInfo.oracle.latestRoundData();
    require(
      (answeredInRound >= roundId) &&
        (updatedAt >= block.timestamp - maxChainlinkOracleTimeDelay),
      "Chainlink oracle price is stale"
    );
    require(answer >= 0, "Price cannot be negative");
    // Scale to decimals needed in Comptroller (18 decimal underlying -> 18 decimals; 6 decimal underlying -> 30 decimals)
    // Scales by same conversion factor as in Compound Oracle
    return uint256(answer) * chainlinkInfo.scaleFactor;
  }

Tools Used

Manual Review

Recommended Mitigation Steps

Recommend setting different maxChainlinkOracleTimeDelay for different price feeds.

Activity

  1. added
    2 (Med Risk)Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
    bugSomething isn't working
    on Jan 13, 2023
  2. added a commit that references this issue on Jan 13, 2023
  3. trust1995 commented on Jan 22, 2023

    @trust1995

    I think it's an excellent recommendation but is a little shy of Med severity.

  4. added
    QA (Quality Assurance)Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
    downgraded by judgeJudge downgraded the risk level of this issue
    and removed
    2 (Med Risk)Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
    on Jan 22, 2023
  5. c4-judge commented on Jan 22, 2023

    @c4-judge
    Contributor

    trust1995 changed the severity to QA (Quality Assurance)

  6. c4-judge commented on Jan 22, 2023

    @c4-judge
    Contributor

    trust1995 marked the issue as grade-b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Q-53QA (Quality Assurance)Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntaxbugSomething isn't workingdowngraded by judgeJudge downgraded the risk level of this issuegrade-b

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions