Algo Ssstablecoinsss

AI First Flight #2
Beginner FriendlyDeFi
EXP
View results
Submission Details
Impact: high
Likelihood: low
Invalid

Missing ZKsync Era L2 Sequencer Uptime Feed Check Permits Operations on Stale Prices Post-Outage

Summary

  • oracle_lib.vy directly queries Chainlink price feeds without checking the Chainlink L2 Sequencer Uptime Feed on ZKsync Era.

  • When an L2 sequencer recovers from an outage, transactions queued during the downtime execute against un-updated prices before new oracle rounds arrive.

  • Attackers can front-run price updates immediately after sequencer recovery to mint undercollateralized debt or unfairly liquidate borrowers.

Vulnerability Details

Description

oracle_lib.vy checks price staleness using latestRoundData() but does not integrate Chainlink's L2 Sequencer Uptime Feed:

@internal
@view
def _stale_check_latest_round_data(
price_price_address: address,
) -> (uint80, int256, uint256, uint256, uint80):
price_price: AggregatorV3Interface = AggregatorV3Interface(price_price_address)
@> (round_id, price, started_at, updated_at, answered_in_round) = staticcall price_price.latestRoundData()

On Layer 2 networks like ZKsync Era, if the sequencer goes down, oracle nodes cannot submit round transactions. When the sequencer restarts, it processes pending transactions and transactions submitted by MEV searchers before external oracle nodes can broadcast new price updates.

Without verifying the sequencer uptime feed and enforcing a post-restart grace period, transactions execute against pre-outage prices that no longer reflect actual spot market conditions.

Risk

Likelihood: Low

  • Occurs specifically during and immediately after ZKsync Era sequencer downtime or restart events.

Impact: High

  • Rapid price divergence during outages allows MEV searchers to front-run oracle update transactions upon sequencer recovery, draining protocol collateral or liquidating healthy borrowers.

Severity: Medium

Proof of Concept

During a 4-hour ZKsync Era sequencer outage, the spot price of ETH drops 20% on centralized exchanges. Upon sequencer restart:

  1. An attacker submits a transaction before Chainlink nodes submit an updated price transaction.

  2. The engine evaluates ETH collateral at the pre-outage price because latestRoundData() has not been updated yet, allowing maximum DSC minting against overvalued collateral.

  3. The attacker withdraws the borrowed DSC, leaving the engine with undercollateralized bad debt once the oracle update confirms.

Recommended Mitigation

Query Chainlink's L2 Sequencer Uptime Feed and enforce a grace period (e.g., 3600 seconds) after the sequencer resumes:

+SEQUENCER_UPTIME_FEED: constant(address) = 0x...
+GRACE_PERIOD_TIME: constant(uint256) = 3600
+
@internal
@view
def _stale_check_latest_round_data(
price_price_address: address,
) -> (uint80, int256, uint256, uint256, uint80):
+ # Query sequencer uptime feed and assert sequencer is up and grace period has elapsed
price_price: AggregatorV3Interface = AggregatorV3Interface(price_price_address)
...

Explanation: Rejecting oracle reads while the sequencer is down or during the post-restart grace period prevents stale transaction execution before price feeds stabilize.

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge about 1 hour ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!