Quant Memo
Core

Proof of Reserves and Exchange Solvency

Why a crypto exchange showing you a big wallet balance proves almost nothing about whether it can actually pay every customer back, and what a real proof-of-reserves audit has to check instead.

Prerequisites: Hashing, Merkle Trees and Block Headers

An exchange posts a screenshot of a wallet holding 200,000 bitcoin and calls it "proof of reserves." That screenshot proves the exchange controls a wallet with that balance for the ten seconds the screenshot was taken. It proves nothing about whether that wallet is borrowed for the photo, whether it's pledged as collateral to a lender who could seize it tomorrow, or — the number that actually matters — whether 200,000 bitcoin is enough to cover what the exchange owes its customers. Reserves alone answer "does the exchange have some assets." Solvency answers "does the exchange have enough assets to cover every liability," and that second question is the one that collapses exchanges when it's answered wrong.

Think of it like a bank showing you its vault is full of cash without ever showing you the ledger of how many depositors are owed money against that same vault. A vault stuffed with cash tells you nothing if ten times as many people have a claim on it.

The two sides that must both be checked

A real proof-of-reserves exercise has to establish two separate facts and then compare them:

Assets — proof of control. The exchange must demonstrate it actually controls the private keys to wallets holding the claimed coins, typically by signing a specific message with those keys (recall from public-key cryptography that only the key holder can produce a valid signature). This proves control, not ownership free of encumbrance — a wallet can be controlled by the exchange while also being pledged to a lender as collateral, in which case it isn't really available to cover customer withdrawals.

Liabilities — proof of what's owed. This is the harder half. The exchange publishes a Merkle tree built from every customer's balance: each customer is a leaf, and pairs of leaves are hashed together repeatedly up to a single root hash. A customer can be given their own leaf plus the small set of sibling hashes needed to recompute the root, letting them verify their balance was genuinely included in the total without the exchange revealing any other customer's balance.

root=H(H(H(b1,b2),H(b3,b4)),).\text{root} = H\Big(H\big(H(b_1, b_2), H(b_3, b_4)\big), \ldots\Big).

In words: customer balances get hashed together in pairs, repeatedly, until one single number — the root — summarizes every balance simultaneously. Change any single customer's balance and the root changes completely, so a published root is a commitment the exchange can't quietly edit later.

The comparison. Sum every leaf in the Merkle tree to get total liabilities. Compare that sum to the total of independently-verified, unencumbered wallet balances from the assets check. If assets ≥ liabilities across every asset type the exchange claims to hold 1:1, the exchange is solvent as of that snapshot.

Two worked examples

Example 1 — a Merkle inclusion check. Four customers hold balances of 3, 5, 2 and 7 units (in some hashed form). H(3,5)=h12H(3,5) = h_{12}, H(2,7)=h34H(2,7) = h_{34}, root =H(h12,h34)= H(h_{12}, h_{34}). If you're the customer with balance 2, the exchange gives you your own leaf plus h12h_{12} (your sibling pair's hash) and H(7)H(7)'s position so you can recompute H(2,7)H(2,7) yourself, then combine with h12h_{12} to reproduce the published root exactly. If your recomputed root matches the publicly posted one, your balance of 2 was genuinely counted — without you ever seeing the other three customers' numbers.

Example 2 — the solvency arithmetic that actually matters. An exchange's Merkle tree sums to 500,000 BTC owed to customers. Its signed wallet proof shows control of 480,000 BTC in cold storage plus 30,000 BTC in hot wallets, for 510,000 BTC of claimed assets. Looks solvent — until you learn 40,000 of the cold-storage BTC is pledged as collateral against a loan the exchange took out. Unencumbered assets are actually 510,00040,000=470,000510{,}000 - 40{,}000 = 470{,}000 BTC against 500,000 BTC owed: a 30,000 BTC shortfall, invisible in the naive "assets shown vs. liabilities claimed" comparison and only surfacing once encumbrances are checked.

liability Merkle tree root 35 27

solvency check claimed 510k unencumbered 470k owed 500k

The Merkle tree proves the liability total without exposing individual balances. But "claimed assets" only becomes a real solvency check once pledged or encumbered assets are stripped out and compared to the liability total, not the headline number.

What this means in practice

A credible proof-of-reserves report needs a third-party attestation of the unencumbered status of the assets, not just a signature proving control — control and freedom from claims are different facts. It also needs to be run repeatedly, not once, since balances and pledges both change daily. Several major exchange failures were preceded by proof-of-reserves marketing that satisfied the "control" test while quietly failing the "unencumbered and sufficient" test.

Proof of reserves has two separate halves — cryptographic proof the exchange controls certain wallets, and a Merkle-tree proof of what it owes customers — and solvency only follows if unencumbered assets from the first half exceed the liability total from the second.

The classic confusion is treating "proof of reserves" and "proof of solvency" as synonyms. A wallet balance screenshot, even a cryptographically signed one, says nothing about liabilities or encumbrances. Insolvent exchanges have published technically accurate proof-of-reserves reports right up until the day they froze withdrawals.

Related concepts

Practice in interviews

Further reading

  • Kraken, Proof of Reserves methodology whitepaper
  • Nic Carter, How to Verify Bitcoin Reserves Without Compromising Privacy (2022)
ShareTwitterLinkedIn