Worked example · 2026-09
Liquid Network — unbacked L-BTC passed consensus, so the federation's 11-of-15 signers approved a peg-out that was valid in every way they were built to check — Liquid Network (Blockstream) / Bitcoin sidechain — 2026-09-06
Summary
Liquid Network is a Bitcoin sidechain run by a federation of functionaries. BTC is locked on Bitcoin and L-BTC is issued 1:1 on Liquid; exiting requires a peg-out, in which the federation's 11-of-15 signers release real BTC from the reserve. Liquid uses Confidential Transactions, so amounts are hidden behind Pedersen commitments and validated by range proofs. Peg-outs are gated by Peg-out Authorization Keys (PAKs); SideSwap, a peg-out partner, holds a whitelisted PAK and builds peg-outs on customers' behalf from its own wallet.
On 2026-09-06 a transaction created L-BTC that was never backed by BTC. Because amounts are confidential, the extra coins were invisible to every observer — as one analysis put it, when the verification is wrong, nobody can see the difference. The unbacked L-BTC was routed through SideSwap's normal peg-out flow. SideSwap "had no way to tell those coins from any other L-BTC." At 14:28:56 UTC the federation paid 3,996.01834922 BTC to a fresh Bitcoin address.
Blockstream confirmed the bug was in Elements and that no keys were compromised, without publishing the defect. On 2026-09-11 SlowMist published a full analysis that names it: the range-proof verification cache built its key by concatenating variable-length fields without length prefixes, so two different argument sets could produce the same key. Two setup transactions in block 4,050,335 (13:52:10) placed valid rangeproofs and commitments on-chain, seeding node caches with a crafted payload; the third transaction, one block later, reused the colliding key with different field boundaries, and on the cache hit the nodes skipped both the cryptographic verification and the minimum-value check, accepting an unbacked commitment as proven. 3,998.5 L-BTC came from nothing. The cache optimisation dates to 2016.
The patch history needs stating precisely, because the intuitive reading of it is wrong. The 2026-08-03 upstream commit (212c43f4) added the missing fields to the cache key but did not protect their boundaries — it was an incomplete fix and would not have prevented this attack. Its cherry-pick to the 23.3.x branch (PR #1599) merged at 17:21 UTC on 2026-09-06, about three hours after the peg-out, which is why the first published accounts read it as a fix that shipped late. The defect was actually closed by Elements 23.3.4 on 2026-09-08, which added length prefixes to the cache key and shipped a -norangeproofcache emergency switch. The release running during the attack, 23.3.3 (2026-04-13), contained neither. No CVE has been assigned. OAK records the mechanism as operator-corroborated and independently attested (Blockstream: Elements bug, no keys compromised; SlowMist: the specific cache-key collision).
The signature of a consensus bug was visible in public infrastructure before anyone diagnosed it: block 4,050,336 was accepted by Blockstream's explorer and rejected by mempool.space, whose chain tip stopped at 4,050,335. Two nodes running what should be the same rules reached different verdicts on the same block.
Timeline (UTC, 2026-09-06 unless noted)
| When | Event | OAK ref |
|---|---|---|
| 2026-04-13 | Elements 23.3.3 released — the shipped build lacking the later cache fix | (standing T9.014 surface) |
| 2026-08-03 | Upstream commit 212c43f4 adds the missing fields to the range-proof cache key — but no length prefixes, so the collision stays reachable |
(partial fix, and unshipped) |
| 13:52:10 | Two setup transactions in block 4,050,335 place valid rangeproofs and commitments on-chain, seeding node caches with the crafted payload | T9.014 — cache seeding |
| 13:53:10 | Third transaction in block 4,050,336 reuses the colliding cache key with different field boundaries; verification and minimum-value checks are skipped; 3,998.5 unbacked L-BTC created | T9.014 exploitation |
| 13:53:10 | Blockstream's explorer accepts block 4,050,336, mempool.space rejects it and stalls at 4,050,335 | T9.014 — consensus divergence, observable in public |
| ~14:05 | 4,000 L-BTC sent into SideSwap's peg-out service; SideSwap builds the peg-out with its own whitelisted PAK | (legitimate path, unbacked input) |
| 14:06:10 | Peg-out transaction in Liquid block 4,050,349 | T9.014 exploitation |
| 14:28:56 | Bitcoin block 965,783: federation pays 3,996.01834922 BTC from bc1qdlld6a…uhwxxr; 11-of-15 HSMs sign — whitelist check and burn-amount check both pass |
(quorum met, invariant unchecked) |
| 16:01:28 / 16:48:45 | Two follow-on peg-out batches process (2.65138358 and 3.99601658 BTC) | (continued drain) |
| 18:23:18 | An independent researcher flags the transaction publicly | (external detection) |
| 18:30:10 | Bitcoin block 965,818: recipient's OP_RETURN — "we are whitehats. contact us on chain"; 1,000 sats sent to the federation wallet to guarantee visibility | (disposition signal) |
| 17:21 | PR #1599 cherry-picks the cache fix into the 23.3.x branch — ~3 hours after the peg-out confirmed |
(patch lands post-hoc) |
| 20:25 | Blockstream statement: Elements bug, no keys compromised, bridge nodes disabled | (operator response, T+5h56m) |
| 2026-09-07 | Blockstream publishes a signed message confirming bridge nodes are patched and safe for funds to be returned; 3,400 BTC (~85%) returned to the federation peg wallet; 598.50 BTC retained, with on-chain messages demanding a 10% bounty, which Blockstream refuses | (partial recovery, open dispute) |
| 2026-09-08 | Elements 23.3.4 released — length prefixes added to the cache key, plus a -norangeproofcache emergency switch |
(the actual fix ships, T+2d) |
| 2026-09-10 | Liquid resumes block production in a controlled restart, without user transactions, while functionaries update nodes; peg-in and peg-out stay suspended | (staged recovery) |
| 2026-09-11 | SlowMist publishes the cache-key collision analysis; Blockstream's CEO commits to covering the 1:1 peg, with no restoration date given | (mechanism attested) |
What defenders observed
- The multisig was never the control it appeared to be. Every published defence of Liquid's security model rests on 11-of-15 hardware functionaries. That quorum answered its two questions correctly and released 95% of the reserve, because the question that mattered — is this L-BTC real? — was answered upstream by consensus code and simply passed through. A quorum downstream of a broken check ratifies the break.
- Confidential Transactions removed the observer of last resort. In a transparent chain, an inflation bug shows up as arithmetic anybody can redo. Under Pedersen commitments the amounts are hidden by design, so a verification failure produces no visible artefact at all. Privacy at the value layer means the supply invariant must be enforced by explicit accounting, because it can no longer be spot-checked by inspection.
- Client disagreement was the earliest available alarm and nobody was wired to it. Two independent explorers disagreed about block 4,050,336 roughly 13 minutes before the peg-out. Cross-implementation validity divergence is the canonical T9.014 detection surface, it was firing in public, and it was noticed only when a researcher looked, at 18:23 — four hours after the money left.
- The patch that looked like the missed fix was not the fix.
212c43f4landed 2026-08-03, the production release was from April, and the cherry-pick merged three hours after the money left — a perfect deployment-latency story, and the deployment gap is real. But the exploited defect was in the field boundaries, which that commit never addressed; only 23.3.4 (2026-09-08) closed it. Patch availability, patch deployment and patch sufficiency are three different states, and a review stopping at the first two would have concluded — wrongly — that shipping on schedule would have saved the reserve. - A reserve-parity check is cheap, external, and would have fired. Circulating L-BTC versus BTC held in the federation address is two numbers from two chains. Enforced as a pre-signing condition inside the functionaries, it makes a consensus inflation bug non-monetisable through the peg-out path regardless of what the consensus code believes.
- The peg-out partner was structurally unable to help. SideSwap did nothing wrong and could not have: its whitelisted PAK is an authorisation instrument, not a validation one, and it had no means to distinguish backed from unbacked L-BTC. Delegated peg-out authority scales the blast radius of a consensus bug without adding a check anywhere.
Public references
[defiprimeliquid2026]— DeFiPrime, "The Liquid Network Exploit: $320M Pegged Out, Every Key Intact" (block heights, UTC timeline, the range-proof cache key analysis, HSM check semantics, explorer divergence, commit212c43f4and PR #1599): https://defiprime.com/liquid-network-peg-out-exploit[cryptobriefingliquid2026]— Crypto Briefing, "Blockstream confirms bridge nodes patched, funds safe to return after $320M Liquid Network exploit" (2026-09-07; PGP-signed Bitcoin messages, return conditioned on patching): https://cryptobriefing.com/blockstream-liquid-network-exploit-funds-return/[cryptoslateliquid2026]— CryptoSlate, "A whitehat hacker is holding $320 million in drained Bitcoin until developers prove they patched a fatal network flaw": https://cryptoslate.com/a-whitehat-hacker-is-holding-320-million-in-drained-bitcoin-until-developers-prove-they-patched-a-fatal-network-flaw/[shatteredliquid2026]— Shattered, "Liquid Network Hack: $320M Bitcoin Sidechain Exploit" (peg-out mechanics, PAK whitelist, unverified white-hat status as of 2026-09-07): https://shattered.io/liquid-network-320-million-hack-2026/[cryptotimessept2026]— The Crypto Times, "Crypto Hacks Reached $322M in September's First Week" (2026-09-07; Liquid as >99% of the week's reported total): https://www.cryptotimes.io/2026/09/07/crypto-hacks-cross-322m-in-septembers-first-week-as-liquid-network-alone-loses-320m/[cryptotimesslowmistliquid2026]— The Crypto Times, "SlowMist Exposes Liquid Network Flaw: How a Cache Collision Minted 3,998 Unbacked L-BTC" (2026-09-11; cache key concatenating variable-length fields without length prefixes; setup transactions in block 4,050,335 at 13:52:10 seeding the cache; cache hit skipping verification and minimum-value checks; Elements 23.3.4 on 2026-09-08 adding length prefixes and-norangeproofcache; the 2026-08-03 patch adding fields but not boundaries; restart 2026-09-10): https://www.cryptotimes.io/2026/09/11/slowmist-exposes-liquid-network-flaw-how-a-cache-collision-minted-3998-unbacked-l-btc/[cryptoeconomyslowmistliquid2026]— Crypto Economy, "SlowMist Uncovers Liquid Network Flaw That Minted 3,998 Unbacked L-BTC" (2016-era optimisation; 3,400 BTC returned the next day; 598.5 BTC retained with messages demanding a 10% bounty, refused): https://crypto-economy.com/slowmist-uncovers-liquid-network-flaw/[coindeskliquidreturn2026]— CoinDesk, "White hat hackers return most of $320M Bitcoin taken from Liquid Network" (2026-09-08; 3,400 BTC (~$269M) returned to the federation wallet): https://www.coindesk.com/markets/2026/09/08/white-hat-hackers-return-most-of-usd320m-bitcoin-taken-from-liquid-network[defiantliquidreturn2026]— The Defiant, "Liquid Attacker Broadcasts Return Of 3400 BTC, Keeps 598" (598.50 BTC retained, ~15% of 3,998.50 BTC; PGP-signed OP_RETURN negotiation; return conditioned on a signed patch confirmation): https://thedefiant.io/news/security/liquid-attacker-broadcasts-return-of-3400-btc-keeps-598[spaziocryptoliquid2026]— Spazio Crypto, "Liquid Network: 4,000 BTC Exit in $320M Software Bug Exploit" (reserve before/after, federation halt): https://en.spaziocrypto.com/security/liquid-network-4000-btc-reserve-crisis-blockstream-sidechain-halted/
Discussion
T9.014 has been the corpus's thinnest well-defined Technique: one canonical anchor from 2010 (the Bitcoin value overflow bug), one unexploited disclosure (Zcash Orchard, 2026-06), and a pipeline of near-misses. Liquid is the first fully-exploited consensus bug in the corpus since 2010 and the first outside Bitcoin Core itself, which makes it the anchor the Technique's promotion criteria were written for. The two full-exploit anchors rhyme structurally — an arithmetic/validation defect in the client that defines consensus, producing coins that violate the supply invariant — and diverge in a way worth recording: in 2010 the fraudulent 184.5 billion BTC was visible to anyone who read the block, and the fix landed in about five hours. In 2026 the fraudulent supply was cryptographically hidden, the bug was diagnosed from the outside, and the money was gone before anyone framed the question.
What generalises beyond Liquid is the layering error, not the cache bug. Liquid's public security story is a federation: hardware modules, geographic distribution, a signing threshold. Everything in that story was intact. The federation was never validating whether the sidechain's money supply was sound — it was validating that a request was well-formed and whitelisted, and inheriting soundness from consensus. Any system with this shape — a signing quorum, bridge committee, or attestation set that acts on a request whose validity was decided upstream — has the same property: the quorum's guarantee is capped by the weakest check it does not perform. Contributors documenting incidents in this class should record, explicitly, which invariant the signers checked and which one they assumed, because the gap between those two is where the loss lives.
The patch story deserves its own note for the T9.014 record, and it is a correction to the obvious version of it. A commit touching the vulnerable cache sat in the upstream tree for 34 days, its cherry-pick merged three hours after the money left, and the deployed release predated it by four months — which is a complete and compelling account of the incident that the forensic analysis then took apart, because that commit added fields without protecting their boundaries and the attack ran through the boundaries. The deployment gap is real and remains the structural problem: for a chain whose consensus is one client, "the fix exists" and "the fix is running" are separated by an interval an attacker can read off a public repository. But "a fix exists" is a claim about the exploited path, and it needs checking against that path. Contributors reconstructing a patch timeline should record what a commit actually changed, not only when it landed — the first is what decides whether an incident was preventable, and it is the part that gets skipped.