Liquid has confidential transactions that hide the amounts for improved privacy. A bug in how these transactions are validated caused inflation of Liquid BTC (L-BTC) and allowed hackers to empty the entire side chain.
Liquid nodes don't see the amounts of a confidential transaction, so to make sure that the transaction is still valid and doesn't cause inflation nodes check something called a balance proof and a range proof.
The balance proof establish that sum of the input amounts equal the output amounts, i.e., that "x L-BTC going in and x L-BTC going out". But there's a catch. Only relying on a balance proof isn't enough. You also need the range proof.
The range proof establishes that a hidden output amount falls within a positive range. That means a valid output must be at least 1 L-sat and at most 2^64 − 1 L-sats. Range proofs make sure that you can't mint "negative L-BTC".
Why is this even necessary? Remember, the amounts are hidden and a hidden negative amount would allow extra positive outputs to balance against it. Without a range proof, a transaction could say "I've put 1 L-BTC in, and I'm taking two outputs out: one with 4000 L-BTC and one with -3999 L-BTC)."
This is going to cause a disaster in a little bit.
Once the balance proof, the range proof, and other validations pass, a transaction is regarded as valid and can pass consensus. However, because especially the range proof is computationally expensive, Liquid nodes cache the result of a successful range proof in memory. Essentially, the node remembers "I saw this range proof before and it was valid, all good!".
In order to recognize the same range proof later on, you need to assign a label to it. This is called a cache key. This cache key is the actual cause of the bug.
The way this cache key was constructed allowed two different transactions to collide on their cache key. Essentially, one valid transaction (1 L-BTC in, 1 L-BTC out) had the same cache key as an invalid transaction (1 L-BTC in, 4000 L-BTC out).
Here's the hack: the attackers submitted the valid transaction (1 L-BTC in, 1 L-BTC out) first. Liquid nodes verified this transaction successfully, created a cache key called REKT and stored it in their cache. Then the attackers carefully crafted a second invalid transaction with (1 L-BTC in, 4000 L-BTC out) that created the same cache key REKT.
Instead of validating the second transaction and realizing that it printed money out of thin air, Liquid nodes found it in their cache and said "hey I saw this transaction before, everything is fine" and that caused the inflation.
The attackers then took their 4000 L-BTC and withdrew 4000 BTC onto the Bitcoin base chain.
https://poster.place/nevent1qqsw2d3ycpwfgm4lskma0ga5xkcxkyjppn82e22md2dcapwgl7l9awgmhdlpc
