Skip to content

Latest commit

 

History

History
95 lines (68 loc) · 2.68 KB

080.md

File metadata and controls

95 lines (68 loc) · 2.68 KB

Gentle Wintergreen Barracuda

Medium

Oracle Relay's Missing Sequencer Status Check

Summary

If Optimism's sequencer goes down, attackers can exploit outdated prices by sending transactions through an alternate channel due to missing safety checks in the oracle system.

Root Cause

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

In OracleRelay.sol there is no implementation of Optimism's sequencer uptime feed (0x371EAD81c9102C9BF4874A9075FFFf170F2Ee389), making the contract vulnerable during sequencer downtime.

Internal pre-conditions

  1. Contract must be deployed on Optimism L2
  2. Contract must be actively using Chainlink price feeds

External pre-conditions

  1. Optimism's sequencer becomes temporarily offline
  2. The L1 delayed inbox remains operational
  3. Price deviation occurs during sequencer downtime

Attack Path

  1. Attacker monitors Optimism's sequencer status
  2. When sequencer goes offline:
    • Chainlink oracle stops updating
    • Prices become stale
  3. Attacker identifies favorable prices
  4. Attacker submits transaction through L1 delayed inbox
  5. Transaction executes with stale price data due to no sequencer status check

Impact

  • Users can execute transactions with stale prices during sequencer downtime
  • No protection against L1 delayed inbox exploits
  • Scale of loss depends on:
    • Duration of sequencer downtime
    • Price movement during downtime
    • Transaction sizes allowed

PoC

No response

Mitigation

Implement Optimism sequencer status checks:

// Add sequencer feed interface
interface ISequencerFeed {
    function latestRoundData() external view returns (
        uint80 roundId,
        int256 answer,
        uint256 startedAt,
        uint256 updatedAt,
        uint80 answeredInRound
    );
}

contract OracleRelay is IOracleRelay {
    ISequencerFeed public immutable sequencerUptimeFeed;
    uint256 private constant GRACE_PERIOD_TIME = 3600; // 1 hour

    constructor(address _underlying, IAggregator _aggregator) {
        sequencerUptimeFeed = ISequencerFeed(0x371EAD81c9102C9BF4874A9075FFFf170F2Ee389);
        // ... existing constructor logic
    }

    function currentValue() external view override returns (uint256) {
        // Check Optimism Sequencer status first
        (
            ,
            bool isActive,
            uint256 startedAt
        ) = sequencerUptimeFeed.latestRoundData();
        
        require(isActive, "Sequencer down");
        require(
            block.timestamp - startedAt > GRACE_PERIOD_TIME,
            "Grace period not elapsed"
        );

        // ... rest of the price feed logic
    }
}