Skip to content

Chainlink Feed Without Staleness / Round Check

SAFE-0102 Oracle / Price Checked automatically by the scanner
1

What goes wrong

latestRoundData() is consumed without validating updatedAt (freshness) and answeredInRound >= roundId (completeness). A stale or frozen feed keeps returning the last value; during a market crash or a feed outage the protocol prices assets at an outdated number and mis-collateralises positions.

2

The vulnerable pattern

proof of concept — how it is exploited
// If the feed freezes, the old price is used forever:
// feed.latestRoundData() -> (id, 2000e8, _, updatedAt = 3 days ago, _)
// contract accepts 2000e8 while the real price is 800.
// Attacker deposits at the stale-high valuation and drains the shortfall.
3

How to fix it

the pattern that is safe
(uint80 roundId, int256 answer,, uint256 updatedAt, uint80 answeredInRound) = feed.latestRoundData();
require(answer > 0, "bad price");
require(updatedAt != 0 && block.timestamp - updatedAt <= MAX_DELAY, "stale");
require(answeredInRound >= roundId, "incomplete round");
Always check updatedAt and answeredInRound (Chainlink best practice).
4

Where this has happened

Largest recorded losses in the same failure class — related, not the same bug:

Check your own contract for this

The SaferICO scanner runs 201 detectors over your Solidity source, SAFE-0102 among them. Paste an address or the source itself — a small per-scan fee, shown before you sign, or unlimited on any plan.

Run the scanner See how it is attacked Read the docs