Liquid Network hack: how Blockstream's Bitcoin sidechain lost 4,000 BTC
At 18:30 UTC on 6 September a Bitcoin tx carrying 3,996 BTC also carried a note: 'we are whitehats. contact us on chain'. Four hours earlier the Liquid federation had signed that bitcoin away in a single peg-out, every key intact. We traced the wallet back to two small peg-ins, through a day of practice on Liquid, and forward through the six messages the two sides have written into blocks since. This piece is updated as new messages land.
| Update log (UTC) | What changed |
|---|---|
| 7 Sep, 07:20 UTC | Audit pass. Corrected the day names (6 September was a Sunday) and the message count, which is six. No new message from either side; the balance is unmoved. Dust and memecoin spam keep arriving at the wallet. |
| 7 Sep, 06:30 UTC | First posting, checked at block 965,891. The last on-chain message from either side is Blockstream's "Yes, thank you." The whitehat balance is unmoved and nothing from it sits in the mempool. Liquid has carried no user txs since one in the morning. |
01 — The message"we are whitehats. contact us on chain"
Late on Sunday afternoon UTC a Bitcoin tx confirmed that spent two coins back to the same wallet, one of them the whole peg-out, and sent 1,000 sats to the federation's peg wallet. Wedged between those outputs was an OP_RETURN, the small field where anyone can write a note into a block. The note read: "we are whitehats. contact us on chain".
The on-chain sleuth ErgoBTC had already seen it in the mempool seven minutes earlier and posted the question everyone was about to ask: "Liquid got got?"
Four hours before that, the federation had signed away 3,996 BTC in a single peg-out, more than nine tenths of all it held. Nothing about the tx looked forced. Eleven of the fifteen functionaries signed it, the way they sign every peg-out. The request came through SideSwap, a Liquid member whose peg-out key is on the whitelist. Every key did exactly what it was built to do, and the bitcoin left anyway.
02 — The premiseWhat Liquid is, and what a peg-out means
Liquid is a Bitcoin sidechain built by Blockstream. You lock bitcoin in the federation's multisig on the main chain, a peg-in, and the same amount of L-BTC appears on Liquid, where blocks arrive every minute and amounts are hidden by confidential transactions. Send L-BTC back to the peg, a peg-out, and the federation releases the bitcoin. Fifteen companies run the functionary boxes that sign blocks and hold the keys, and any 11 of them can move the bitcoin. Exchanges use Liquid to settle with each other, Tether issues USDT on it, and a handful of firms run peg-in and peg-out desks for anyone who does not want to deal with the federation directly. SideSwap is one of those desks. It charges 0.1 percent.
The promise under all of that is short. There is never more L-BTC than there is bitcoin in the peg wallet. On Saturday the wallet was full. By Sunday evening it was nearly empty.
Bitquery indexes the whole Bitcoin chain, and the Liquid chain is public too, so we did not have to take anybody's word for what happened. We pulled every tx the whitehat wallets made on both chains, rebuilt the peg-out from the federation's side, and read the messages both parties wrote into blocks, checking Blockstream's PGP sigs against its own key. What follows is that record: where the L-BTC came from, how it left, what the two sides have said to each other, and what Liquid looks like while it waits. One limit belongs up front. Amounts on Liquid are hidden and Blockstream has not named the bug, so the mint itself can be found in the record but not fully explained by it.
03 — The rehearsalTwo bitcoin in, a day of practice
The wallet that would drain the peg started with about 2 BTC of its own. Two peg-ins on the Friday, a little over a bitcoin each, arrived on Liquid as L-BTC by Saturday morning. Both were funded from a pile of small taproot coins, 24 in one and 39 in the other, which reads like a wallet that had been stacking sats for a while rather than a fresh CEX withdrawal. None of the funding wallets carries a label in our database or in MetaSleuth's.
Then the wallet went to work. From Saturday lunchtime UTC until Sunday afternoon it hopped through dozens of fresh addresses, then settled on two and made 92 txs from them on Liquid. Most were tiny: one input, three outputs, a 41-sat fee. They came in bursts, with a lull over night and a final short run around noon on Sunday. Anyone watching the mempool would have seen a busy wallet doing nothing much.
Seventy of those txs had one thing in common that ordinary wallets never produce. Each carried an OP_RETURN output with the asset written in plain, L-BTC, but the amount hidden. And 68 of them carried the same hidden amount and the same range proof, byte for byte, dropped into blocks across 14 hours.
| The planted output, decoded | Value |
|---|---|
| Script | OP_RETURN with one zero byte. Unspendable by design. |
| Asset | L-BTC, written in the clear |
| Amount | Hidden. The commitment is the curve's base point, which is what you get when you commit to zero with the simplest possible blinding key. |
| Range proof | 4,166 bytes, identical in all 68 copies |
| Copies | 68, between Liquid blocks 4,049,384 and 4,050,246 |
| Cost | 41 sats per transaction |
Confidential transactions lean on range proofs. A hidden amount is fine as long as a proof shows it is not negative, because a negative output is how you print money. Nodes check thousands of these proofs and cache the ones they have already passed, so they do not do the work twice. Planting one proof 68 times over 14 hours looks like an effort to make sure every node on the network had that exact proof sitting in its cache. What the wallet then did with it is the one step the public record does not show.
04 — The exitOne transaction on Liquid, one on Bitcoin
The wallet ran three dry runs before the real thing: small peg-outs through SideSwap on Sunday morning UTC. Those were real L-BTC, or at least the federation treated them that way, and they proved the route worked end to end. SideSwap's payouts from all three were gathered into one coin of about 2.5 BTC and sent to a fresh Bitcoin address just after 14:00 UTC. That address is the one now holding all of it.
The mint came at 13:53 UTC, in a Liquid tx with one input, three outputs and a fee of 58 sats. It is the only tx in the wallet's whole history whose range proof is a different length from every other one it made. Both spendable outputs went to SideSwap within seven minutes. SideSwap swept them into its hot wallet, and its peg-out desk asked the federation for the full amount, plus a second, smaller peg-out for its own fee.
| The cash-out, minute by minute (UTC, 6 September) | What happened |
|---|---|
| 11:30 and 11:39, Liquid | Two dry-run peg-outs through SideSwap, 0.95 and 1.71 BTC |
| 11:48, Bitcoin block 965,764 | The federation pays both |
| 13:16, Bitcoin block 965,770 | A third dry run paid, 0.55 BTC |
| 13:53, Liquid block 4,050,336 | The mint. One input, three outputs, fee 58 sats, range proof 4,234 bytes against the usual 4,174 |
| 13:54 and 14:00, Liquid | Both spendable outputs reach SideSwap's hot wallet |
| 14:01, Bitcoin block 965,780 | Dry-run payouts gathered into 2.4975 BTC at the whitehat address |
| 14:06, Liquid block 4,050,349 | SideSwap requests a peg-out of 3,996.018 BTC, plus 3.996 BTC for its 0.1 percent fee |
| 14:28:56, Bitcoin block 965,783 | The federation pays. In the same block SideSwap forwards 3,995.99999857 BTC to the whitehat address |
Then the federation paid, in one big tx that pulled together most of the coins the peg wallet had. The fee was pocket change.
| The federation's peg-out, block 965,783 | BTC |
|---|---|
| 83 inputs, all from the peg wallet | 4,019.4443 |
| Size and fee | 122 kilobytes, 34,097 sats, about $27 to move $318 million |
| To SideSwap's payout address, the customer's peg-out | 3,996.0183 |
| To SideSwap, its 0.1 percent fee | 3.9960 |
| To a third address, an unrelated customer's peg-out | 2.6514 |
| Back to the peg wallet as change, in ten equal pieces | 16.7782 |
| Peg wallet before and after | 4,205.29 to 202.63 |
In the same block SideSwap forwarded the customer's bitcoin, less its fee, to the address that had taken the dry-run payout half an hour earlier. The federation processed two more small peg-outs that afternoon before the bridge was switched off. That is how the peg wallet arrived at the balance it holds now.
05 — The conversationSix messages, all of them in blocks
Most hackers who want to talk open a Telegram account. This one wrote into Bitcoin, and Blockstream, after one short public note, decided to answer there too. Every message so far is a tx that pays 1,000 sats to the other side and carries the text in an OP_RETURN. We decoded all of them from the raw blocks, and the txids are in the record at the end.
| Time (UTC) and sender | Message |
|---|---|
| 6 Sep 18:30 Whitehat | "we are whitehats. contact us on chain" |
| 6 Sep 19:31 Blockstream | "Please contact security@blockstream.com" |
| 7 Sep 01:49 Blockstream | A short ciphertext encrypted to the whitehat's public key, plus a detached PGP signature from security@blockstream.com. We verified it. Signed at 01:14 UTC. |
| 7 Sep 02:20 Whitehat | "sending most back to bc1qdlld6…suhwxxr, is that ok" |
| 7 Sep 03:30 Whitehat | "Please fix the bug first. The chain is under risk at latest commit right now. Make sure every node is patched. Then we will transfer the money back safely after confirming the fix." Followed by a PGP message encrypted to Blockstream's key, which only Blockstream can read, all in one OP_RETURN. |
| 7 Sep 03:30, same block Blockstream | "Yes, thank you." PGP clear-signed at 03:16 UTC, so it answers the 02:20 question and not the demand that landed in the same block. We verified it. |
Three details in the raw txs say more than the words. Blockstream's first reply came from a fresh address funded out of a two-key wallet with a long recovery timeout, the same form Blockstream's own Green wallet uses. Its second message was encrypted to the public key the whitehat had exposed by spending, in the Electrum ECIES format, and signed with the key whose fingerprint ends 6844 A2D6. We fetched that key from blockstream.com, imported it, and both sigs verify against "Blockstream Security Reporting". Change one character of either text and the check fails.
The whitehat's txs carry a tell of their own. Each sets a locktime just below the current height, the anti-fee-sniping habit of Bitcoin Core's wallet family, and each sweeps up every scrap of dust that others had sent to the address since the last message. That is why the second message has 15 inputs. By the time of the third, two dozen dust payments had arrived from outsiders wanting to be read: a Signal handle, a New York lawyer offering pro bono help with "a clean return", a wallet app plugging itself four times, a Monero swap desk promising no freezes, a second swap site openly pitching itself for laundering, and a memecoin. The whitehat spent all of it as fee change.
Not everyone reads the label the wallet gave itself. Charles Guillemet, Ledger's CTO, wrote on X that draining a bridge and then asking for on-chain contact "doesn't look like usual white hats practices". He added that criminal crews do not usually try to contact their victims either, and floated the idea of "people with good intentions that intensively played with recent LLMs and are not used to responsible disclosures".
06 — The bugWhat the code says, and what it does not
SideSwap said within hours that "the L-BTC came from an Elements bug, not from any SideSwap system", and Liquid said no key was compromised. Elements is the open-source software every Liquid node runs. Neither company has said which bug. The repo, though, has a public history, and one line in it is hard to ignore.
| Elements, the range proof cache fix | When |
|---|---|
| Commit by a Blockstream engineer: "fix: range proof cache bind to asset and scriptpubkey" | 3 Aug |
| Pull request opened to fix "range proof verification cache keying" | 31 Aug |
| Merged to the main branch | 2 Sep |
| Backported to the 23.x line | 3 Sep |
| Latest release, 23.3.3, which does not contain the fix | 13 Apr |
| The mint on Liquid | 6 Sep, 13:53 UTC |
| Fix merged into the release branch "in preparation for 23.3.4rc2" | 6 Sep, 17:21 UTC |
| A release that contains it | None, at posting |
Before that change, a node remembered a range proof it had checked by the proof and the hidden amount alone. After it, the node also remembers which asset and which output script the proof was checked against. That is the same corner of the code the 68 planted outputs were aimed at. It fits what we see on chain, and it falls short of proof. The whitehat's own message says the chain "is under risk at latest commit right now", which reads as a claim that the fix in the repo is not the whole fix. We cannot test that claim. We can say the release everyone was running on Sunday did not have the patch, and that no release with it existed at the time of posting.
07 — Where it standsA paused chain and a five-cent peg
Liquid announced on Sunday evening that its bridge nodes were off and the chain was "effectively paused", and asked CEXs to stop L-BTC deposits and withdrawals. Blocks kept coming every minute, because the signers still make them, but nothing goes in. User txs fell from about 190 an hour on Sunday afternoon to two in the hour after midnight, and none since one in the morning UTC on Monday.
The bitcoin is where it was. The whitehat address holds all it received in one coin, the peg-out plus the dry-run payout plus the dust from others, and has spent nothing except message fees. Nothing sits in the mempool from it. The federation's peg wallet holds 197 BTC.
That number is the one that matters to everyone else. The minted L-BTC was destroyed when SideSwap pegged it out, so Liquid's own explorer still shows a supply that matches the wallet. The honest L-BTC did not go anywhere. Roughly 4,200 of it is still in CEX accounts and wallets, backed by those 197 BTC, which is about five cents of bitcoin per L-BTC until the coins come back. Tether's USDT on Liquid and the other issued assets are not touched by this, because they were never backed by the peg wallet in the first place.
08 — What we are watchingOpen threads
The whitehat has promised to return "most" of the money once the bug is fixed and every node is patched. Nobody has said what "most" means, and the gap between most and all is somebody's loss. Blockstream has said yes to the return and nothing about the bug. There is no patched release. The three dry-run peg-outs, and SideSwap's fee, are real bitcoin paid for L-BTC that never existed, and whether they are part of "most" is another open question. And Elements runs more than Liquid. If the bug is where the code history points, any sidechain on the same code had the same hole on Sunday.
We are re-reading both wallets as blocks arrive and will add each new message to the log at the top of this piece.
Read the same blocks
Every figure here came from public blocks on Bitcoin and Liquid: raw txs, OP_RETURN outputs, the federation's inputs and change, and the whitehat wallet's full history. Bitquery's Bitcoin archive and the MCP server let you ask the same questions in plain English.
Anyone who wants to check a number here can pull the same records. We took the same route through the Coldcard theft, the Aquifer drain on Solana and the $120 million Tectonic exploit, and the OP_RETURN habit that carried this negotiation is the subject of what people write into Bitcoin blocks. Teams that do this work under a mandate use our crypto investigation services and the money flow tools behind them.
| The record | Address or transaction |
|---|---|
| The whitehat wallet, holding 3,998.5 BTC | bc1ql4mfu6…yqjlte |
| The Liquid federation's peg wallet | bc1qdlld6…suhwxxr |
| Blockstream's message address | bc1qn8mgsm…2mfqym |
| The federation's 3,996 BTC peg-out, 14:28:56 UTC 6 Sep | 8db751a6…a7b140 |
| SideSwap forwarding 3,995.99999857 BTC to the customer, same block | 85d2ca15…645043 |
| The 2.4975 BTC dry-run payout, 14:01 UTC | afff7f39…61443b |
| Peg-in one, 1.0825 BTC, 4 Sep 03:11 UTC | f156fc7e…1c9a52 |
| Peg-in two, 1.0660 BTC, 4 Sep 16:36 UTC | 4aa0ce4f…f2858e |
| Liquid: peg-in one claimed, 4 Sep 19:47 UTC | 3628cc2c…72b389 |
| Liquid: one of the 68 planted outputs, 6 Sep 12:21 UTC | 3d00b94c…6bd6e8 |
| Liquid: the mint, block 4,050,336, 13:53 UTC | f24a4b17…0a183f |
| Liquid: SideSwap's sweep, 14:00 UTC | c6ea588a…d72267 |
| Liquid: the 3,996.018 BTC peg-out request, 14:06 UTC | ce4caece…e988f2 |
| Liquid: SideSwap's 3.996 BTC fee peg-out, same block | 731f8fdf…e47d8a |
| Blockstream's PGP key | 1176 542D A98E 71E1 3372 2EF7 4AC8 CC88 6844 A2D6 |
This piece covers the Bitcoin wallets bc1ql4mfu6aundtkksxklfajs2h3t9nzcd6gyqjlte, bc1qdlld6antmv4xug242ed83q7k4rqw50cwfns38szx4qu2f4jwaxxsuhwxxr and bc1qn8mgsmxx42j3fflqfkh0cqhdd6mj4h9q2mfqym, and the Liquid wallets ex1q7kgx4ptje7px48tn0nsmc6se5pngdp3smpqa2w and ex1qlh0wspc3m57h6rzm25f7z3qssskcqcghsg76hm, from 4 September 2026 to the time of the last update in the log above. Bitcoin figures come from Bitquery's archive and were cross-checked against a public block explorer. Liquid figures were decoded from raw blocks.
Amounts on Liquid are hidden by confidential transactions. Statements about which Liquid tx created the L-BTC rest on the wallet's tx structure, timing and proof sizes, and on where its outputs went, not on the amounts themselves. Blockstream has not named the bug, and the link drawn here between the planted outputs and the range proof cache fix is a fit, not a confirmation.
The word whitehat is the wallet's own description of itself. Its use here is not a judgement about the people behind it. Nothing in the record identifies them.
SideSwap is named because the peg-out passed through its service. Its own statement that its key was not compromised fits all we found. The dollar figure uses a bitcoin price of about $79,700 on 6 September.
Blockstream's messages were verified by importing the key published at blockstream.com/pgp.txt and running gpg against the exact bytes decoded from the OP_RETURN outputs. Others have reported the same result on their own.
Trace the next one on your own data
Every number here came from public blocks, pulled through Bitquery's archive of Bitcoin and 40+ other networks: txs, OP_RETURN outputs, address histories and the money flows between them. The same data powers exchange risk desks and on-chain investigators.