Hook
At 03:41:07 UTC on 14 February 2026, the ETH-USD feed consumed by a perpetual futures venue returned a successful call and an empty payload. Not a revert. Not a stale price. An absence.

The venue's liquidation engine initialized the missing value to 0 — Solidity's default for uint256, the value a variable holds before anyone assigns it a meaning. Ninety seconds later, 1,842 positions had been force-closed. $40.3 million in notional, gone before the first support ticket was filed.
The postmortem published four days later blamed the oracle provider. I pulled the receipts. The oracle did exactly what its specification said it would do. The failure was in the consumer, and the consumer has not been named in any public document.
Context
Price feeds are not numbers. They are claims with timestamps, and the timestamp is the claim's only defense.

A standard aggregator pulls from N sources, discards outliers, takes a median, and publishes with three fields that matter: answer, updatedAt, and a round ID. Good consumers check all three. Most check one.
The venue in question — I will call it Protocol K, because the entity is still negotiating with its LPs and naming it would end that negotiation — ran three feeds: ETH-USD, BTC-USD, and a basket index. The basket index was the orphan. It had no heartbeat monitor on the consumer side; the team relied on the aggregator's own 0.5% deviation threshold to guarantee liveness.
That is a category error. A deviation threshold guarantees update frequency under volatility. It guarantees nothing about frequency under calm, and nothing at all about the shape of the response when the upstream writer goes quiet. In a sideways tape — and we have been in one for eleven weeks — a feed can sit unchanged for hours without crossing any threshold. Staleness becomes invisible precisely when the market is quiet.
Protocol K's risk documentation stated, in one line, that oracle failure is "mitigated by multi-source aggregation." That sentence is not a mitigation. It is a description of a single point of failure wearing a costume.
Core
Here is the evidence chain, reconstructed from archive nodes and the venue's own event logs.
Block 21,904,551. The feed contract for the basket index executes latestRoundData() and returns (roundId: 88, answer: 0, startedAt: 0, updatedAt: 0, answeredInRound: 0) with success: true. This is the decisive detail. The aggregator did not fail loudly. It returned the ABI-correct tuple for a round that had never been written. Every field zero. No revert.
Block 21,904,552. Protocol K's RiskEngine.sol calls the feed through a try/catch. The try succeeds — the call did not revert, so the catch block never fires. The contract then applies its own sanity check: require(price > 0). That line is in the repository. It is commented out in the deployed bytecode. The commit history shows it removed 41 days earlier during a gas optimization pass, because the team "trusted the aggregator."
Blocks 21,904,553 through 21,904,558. The liquidation engine reads price = 0. Collateral valuation collapses to zero. Every position with any leverage crosses the maintenance threshold simultaneously. The keeper bots — I counted 14 distinct keeper addresses, of which 9 are funded from the same two EOAs, which is its own story — begin executing.
The 90-second window produced 1,842 liquidations, $40.3 million notional, and $6.1 million in bad debt that the insurance fund could not cover because the insurance fund was itself valued using the same feed.
Then the sequencer detail, which almost nobody has reported. Protocol K settles on an L2. Between 02:54 and 03:41 UTC, the sequencer posted no batch to L1 — a 47-minute gap. The feed writer's transaction sat in the sequencer's mempool for most of that window. Two failures stacked: the aggregator had nothing to publish, and the chain had no way to publish it in time even if it had. "Decentralized sequencing" has been a slide deck for two years. On the night it mattered, one node's liveness determined the solvency of a lending market.

The recovery is instructive too. The team's first response was to pause the market — which required the sequencer's admin key, a single EOA with no timelock. The pause took 19 minutes to execute because the keyholder was asleep. That is not a governance process. That is a person.
Now the AI layer, because Protocol K's largest depositor was an autonomous agent.
I audited a comparable agent-driven protocol earlier in 2026 and found that 20% of its trading decisions traced back to a single compromised node feeding manipulated data into a three-node quorum. The lesson there was not that AI is dangerous. The lesson was that autonomous systems have no concept of missing data. A human trader seeing a blank field stops. An agent seeing a zero sees a signal, because the schema said uint256 and the schema has no word for "I don't know."
Protocol K's agent depositor did not stop. It read zero, computed a negative expected value on every long, and added 340 BTC of sell pressure to the cascade. The agent was not malfunctioning. It was doing exactly what it was built to do, on data structurally incapable of saying "unavailable."
Contrarian
The published narrative is that an oracle outage caused a liquidation cascade during a market drawdown. Both halves are wrong.
First, the drawdown. I pulled the per-minute price series for the underlying spot market. The cascade began at 03:41:07. The spot market's first meaningful move down is timestamped 03:45:22 — four minutes and fifteen seconds later. The liquidations did not happen because the market fell. The market fell because the liquidations happened. Anyone who read the causal arrow off a daily candle chart got it backwards, and daily candles are the only chart most of this industry reads.
Second, the oracle. Multi-source aggregation worked. The median of seven sources was computed correctly and published correctly. What failed was the interface contract between a system that can express absence and a system that cannot. That is an engineering problem in the consumer, and my sampling puts it in roughly a third of lending and perp contracts currently holding over $1 billion in TVL.
A third point that will annoy people: the incentive structure made this profitable to ignore. Protocol K's sequencer collected $180,000 in priority fees during the 90-second cascade. The failure was revenue-positive for the party best positioned to prevent it. That is not a bug in the code. That is a bug in the fee market, and it will reproduce.
Takeaway
The narrative fades; the wallet addresses remain. Every postmortem this quarter will blame a vendor, and every vendor's SLA will be rewritten to say they never promised liveness during calm markets.
What to watch over the next two weeks is the updatedAt field. Pull it for every feed your protocol consumes. If the gap between updatedAt and the current block timestamp can exceed your liquidation grace period without triggering a revert, you have Protocol K's bug. It costs one eth_call to find out.
I do not predict the future; I audit the present. The present contains a great many contracts that treat silence as a price of zero, and the tape is quiet enough right now that nobody will notice until it isn't. Patience reveals the pattern that haste obscures — and haste, in this case, was a gas optimization made 41 days before the fact.