Algo Ssstablecoinsss

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

Missing Chainlink L2 Sequencer Uptime Feed check on ZKsync Era allows transactions with stale prices during sequencer downtime

Root + Impact

Description

The protocol is explicitly deployed to ZKsync Era (Layer 2), where Chainlink price feeds rely on the L2 Sequencer to post updates.

According to Chainlink documentation for L2 deployments, protocols must check the Chainlink L2 Sequencer Uptime Feed before consuming price data. In oracle_lib.vy, _stale_check_latest_round_data only queries the token price aggregator directly. If the ZKsync sequencer goes offline and comes back online, transactions may be executed against stale prices before the price feeds can update, allowing MEV bots and malicious actors to deposit depreciated collateral, mint DSC, or front-run liquidations unfairly.

@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()

Risk

Likelihood:

Occurs whenever the ZKsync L2 sequencer experiences an outage, restart, or network congestion event while Chainlink feeds are paused.

Impact:

Medium. Exploitation of stale oracle prices during sequencer downtime and recovery grace periods, leading to unfair liquidations or unbacked DSC minting.

Proof of Concept

During sequencer outages on ZKsync Era, oracle_lib does not query the sequencer uptime feed, accepting stale prices and allowing liquidations or mints before prices update.

def test_missing_sequencer_check():
# oracle_lib.vy directly calls latestRoundData() on price feed
# without checking if ZKsync sequencer is active or within grace period
pass

Recommended Mitigation

Integrate Chainlink's Sequencer Uptime Feed in oracle_lib and revert if the sequencer is down or if the grace period after recovery has not elapsed.

+ # Check Chainlink ZKsync Sequencer Uptime Feed
+ # (round_id, status, started_at, updated_at, answered_in_round) = sequencer_feed.latestRoundData()
+ # assert status == 0 and block.timestamp - started_at > GRACE_PERIOD_TIME
(
round_id, price, started_at, updated_at, answered_in_round
) = staticcall price_price.latestRoundData()
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!