Skip to content

Latest commit

 

History

History
87 lines (63 loc) · 3.2 KB

077.md

File metadata and controls

87 lines (63 loc) · 3.2 KB

Orbiting Goldenrod Jaguar

Medium

Deprecated Chainlink latestAnswer() usage will lead to stale prices impacting protocol's oracle-dependent operations

Summary

Using stale prices from deprecated latestAnswer() could cause incorrect price calculations when creating, modifying orders, or filling stop-limit orders into bracket orders, affecting the price-based parameters for automated trading operations.

Root Cause

According to Chainlink's documentation, latestAnswer() is deprecated because it only returns the price, while latestRoundData() provides essential metadata:

  • roundId: The round ID of current price data
  • answer: The current price
  • startedAt: Timestamp of when the round started
  • updatedAt: Timestamp of when the round was updated
  • answeredInRound: The round ID in which the answer was computed

Using latestAnswer() misses critical validations:

  1. Cannot verify if price is stale (no updatedAt)
  2. Cannot check round consistency (no roundId and answeredInRound)
  3. No way to validate data freshness (no timestamps) The current implementation only checks if the price is positive: https://github.com/sherlock-audit/2024-11-oku/blob/ee3f781a73d65e33fb452c9a44eb1337c5cfdbd6/oku-custom-order-types/contracts/oracle/External/OracleRelay.sol#L18-L22
function currentValue() external view override returns (uint256) {
    int256 latest = aggregator.latestAnswer();
    require(latest > 0, "chainlink: px < 0");
    return uint256(latest);
}

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

No response

Impact

Consider the following scenario on Optimism network, where network congestion could cause price update delays:

  1. Initial State:

    • ETH price on Chainlink Oracle: $4000
    • Real market price: $4000
    • User wants to create a stop-limit order:
      • Stop price: $3600 (10% drop)
      • Take profit: $4400 (10% rise)
  2. Market Volatility Event:

    • Real market price crashes to $3000 (-25%)
    • Due to network congestion on Optimism, Chainlink Oracle still shows $4000
    • Price delay: ~5 minutes
  3. Impact:

    • Order parameters are calculated using stale $4000 price
    • Stop-loss at $3600 fails to trigger despite price at $3000
    • Take-profit at $4400 is now 46% above market price
    • When Oracle finally updates, orders execute at much worse prices
    • Users face larger losses than their 10% stop-loss threshold

PoC

https://etherscan.io/address/0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419#code 'latestAnswer()' function to find deprecation notice https://docs.chain.link/data-feeds/api-reference#latestrounddata

Mitigation

    function currentValue() external view override returns (uint256) {
        - int256 latest = aggregator.latestAnswer();
        - require(latest > 0, "chainlink: px < 0");

        + (uint80 roundID, int256 latest, , uint256 timeStamp, uint80 answeredInRound) = aggregator.latestRoundData();
        + require(answeredInRound >= roundID, "chainlink: roundID < answeredInRound");
        + require(timeStamp != 0, "chainlink: timestamp is zero");
        + return uint256(latest);
    }