Skip to content

Latest commit

 

History

History
96 lines (70 loc) · 3.01 KB

081.md

File metadata and controls

96 lines (70 loc) · 3.01 KB

Gentle Wintergreen Barracuda

Medium

Oracle Relay's Insufficient Price Feed Validation for ETH/USD Chainlink Feed

Summary

The OracleRelay.sol contract uses deprecated latestAnswer() without proper price validation for ETH/USD (0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85) Chainlink price feed on Optimism, which could result in using stale or incorrect price data for critical ETH price calculations.

Root Cause

https://github.com/sherlock-audit/2024-11-oku/blob/main/oku-custom-order-types/contracts/oracle/External/OracleRelay.sol#L19-L19

In OracleRelay.sol:18-22, the contract lacks proper price validation for the ETH/USD price feed:

function currentValue() external view override returns (uint256) {
    int256 latest = aggregator.latestAnswer();  // Deprecated function used for ETH/USD feed
    require(latest > 0, "chainlink: px < 0");
    return uint256(latest);
}

Internal pre-conditions

  1. Contract must be using the ETH/USD Chainlink feed (0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85)
  2. The price check require(latest > 0) must pass

External pre-conditions

  1. ETH price data from Chainlink must be stale or outside reasonable bounds
  2. The latest reported price must still be greater than zero to pass the basic check

Attack Path

  1. Monitor the ETH/USD price feed for:
    • Stale data due to feed issues
    • Extreme price movements
  2. When feed shows suspicious data:
    • Price is technically valid (>0) but unreasonable
    • Round is incomplete
    • Data is stale
  3. Execute transactions using the incorrect price data since:
    • No freshness validation exists
    • No reasonable min/max bounds checking
    • No round completion verification

Impact

  • No staleness check for ETH price data
  • Missing sanity bounds for reasonable ETH prices
  • No round completion validation
  • The scale of the impact depends on:
    • How far the reported price deviates from actual market price
    • Size of transactions relying on this price
    • Duration of price feed issues

PoC

No response

Mitigation

Update the function to include something similar to what is shown below.

function currentValue() external view override returns (uint256) {
    (
        uint80 roundId,
        int256 answer,
        ,
        uint256 updatedAt,
        uint80 answeredInRound
    ) = aggregator.latestRoundData();
    
    // Validate round data
    require(answeredInRound >= roundId, "Stale price round");
    require(updatedAt != 0, "Incomplete round");
    require(answer > 0, "Negative price");
    
    // ETH/USD specific bounds
    require(answer >= 100e8, "ETH price below min");
    require(answer <= 1_000_000e8, "ETH price above max");
    
    // Freshness check
    require(
        block.timestamp - updatedAt < PRICE_FRESHNESS_THRESHOLD,
        "Stale price data"
    );
    
    return uint256(answer);
}

The bounds suggested are reasonable considering the historical movements of ETH/USD but still just placeholders. Oku must decide on the min/max values relevant to their protocol.