Double-entry ledger and reconciliation: how a crypto exchange keeps its books
A crypto exchange records every deposit, trade, fee and withdrawal twice in a double-entry ledger, then checks the ledger every day against its wallets and bank accounts and investigates each break.
A crypto exchange keeps its books in a double-entry ledger: every deposit, trade, fee and withdrawal is written twice, once where the value comes from and once where it goes, so each asset always balances. A customer's balance is the sum of the entries on their account. Every day, reconciliation compares that ledger with the outside world (the blockchains, the custodian, the bank) and every difference, called a break, is investigated until it is explained.
A balance is an entry in the exchange's books
On a centralised exchange, the coins do not sit in a wallet with the customer's name on it. They sit in wallets the exchange controls, or with a custodian it appoints, mixed with everyone else's. What makes 0.2 BTC belong to one customer is a line in the exchange's own books.
So the books are the product. If a balance is wrong, the customer is owed the wrong amount, and nothing on the blockchain will say so. The deposit guide shows how one entry turns coins on chain into a balance, and what happens when you press Buy shows the entries behind a single order. This guide follows the books as a whole: every kind of movement, the corrections, and the daily check that the books are right.
Double entry: every movement written twice
A double-entry ledger never records a number on its own. Each entry has at least two lines, and the debits equal the credits, asset by asset. Bitcoin balances against bitcoin and euros against euros; a trade between the two is two balanced halves.
The accounts fall into three groups:
What the exchange holds. Its Bitcoin wallets, its client euro account at a bank. A debit adds to these.
What it owes. One account per customer per asset, plus accounts for money in transit, such as withdrawals approved but not yet sent. A credit adds to these.
What is its own. Fee income, and costs it pays, such as network fees. Income is a credit; a cost is a debit.
In a well-built ledger, a balance is not a number anyone overwrites. It is derived by adding up the entries, so every balance can be explained line by line, and the books for any past day can be rebuilt from the entries up to that day.
A worked example: deposit, trade and withdrawal
With illustrative numbers, follow customer A through three movements. Customer B had already paid in 12,000 euros by bank transfer, recorded the same way.
1. The deposit. A deposits 0.5000 BTC. Once it is confirmed, one entry records it: the Bitcoin wallets are debited 0.5000 and A's Bitcoin balance is credited 0.5000. The exchange holds more, and owes exactly that much more.
2. The trade and its fee. A sells 0.2000 BTC to B at 60,000 euros. The trade is two balanced halves and a fee:
Bitcoin: A's balance is debited 0.2000, B's is credited 0.2000.
Euros: B's balance is debited 12,000.00, A's is credited 12,000.00.
The fee, 0.1% (fees are the operator's choice): A's euro balance is debited 12.00 and the trading fee account is credited 12.00. In this example only A pays a fee.
No wallet and no bank account moves. A trade only changes who is owed what, and the fee is the moment some of what was owed to a customer becomes the exchange's own.
3. The withdrawal. A withdraws 0.1000 BTC and pays an illustrative withdrawal fee of 0.0005 BTC. It takes two entries:
When it is approved, A's balance is debited 0.1005, the withdrawals-in-flight account is credited 0.1000, and the withdrawal fee account is credited 0.0005.
When it is sent, withdrawals in flight is debited 0.1000, the network fee the exchange pays, 0.0002 BTC, is debited as a cost, and the Bitcoin wallets are credited 0.1002.
The in-flight account matters. Between approval and sending, A can no longer spend the coins, yet they are still in the wallets, and the books show both facts at once.

After the three movements, each asset balances on its own:
Bitcoin | Euros | |
|---|---|---|
Held (wallets, bank) | 0.3998 | 12,000.00 |
Owed to customers | 0.3995 (A 0.1995, B 0.2000) | 11,988.00 (A) |
The exchange's own | 0.0003 (fee 0.0005, less network 0.0002) | 12.00 |
What is held equals what is owed plus what is the exchange's own. If that equation ever fails for an asset, something was recorded wrongly, or something moved without being recorded.
Nothing is edited, only reversed
A posted entry is never changed or deleted. A mistake is corrected by a new entry that reverses it, with a reference to the entry it corrects and the reason, and the corrected figure follows from both.
Say a retried message posts A's 12.00 euro fee twice. A's balance shows 11,976.00 instead of 11,988.00. The fix is a reversing entry: the trading fee account is debited 12.00 and A's balance credited 12.00, citing the duplicate. All three fee lines stay in the books, and A's statement shows the charge and its reversal.

This is what makes the books worth trusting. Anyone reviewing them sees what happened, when, and who corrected it, instead of a number that silently changed. It also makes duplicates easy to catch: each trade or withdrawal ID should produce one set of postings, and a second set stands out.
You can see this in Marengo, our exchange, which keeps every balance in a double-entry ledger with reconciliation.

Reconciliation: the ledger against the outside world, every day
A ledger can balance perfectly and still be wrong, if it agrees with itself but not with reality. Reconciliation compares it with records the exchange does not write itself. A daily run usually covers:
The wallets. The ledger's wallet accounts against the balances on chain at a fixed block, for every address the exchange controls.
The custodian. Coins held by a custodian against the custodian's own statement.
The bank. The client euro account against the bank's statement for the same day.
Trades and postings. Every trade from the matching engine against the ledger, one set of postings each.
Coverage. Per asset, what is held against what is owed to customers, the comparison proof of reserves and proof of liabilities later publishes.
Both sides are taken at the same cut-off, for example midnight UTC, with the block height recorded for each chain. Most items match automatically by amount and reference: a transaction hash, a bank reference, a trade or withdrawal ID.

Breaks, and how one is investigated
A break is any difference that does not match. In the illustrative run above, three assets have one each, and they show the usual kinds:
Timing. The ledger booked a 0.1000 BTC withdrawal when it was sent at 23:59, but it was confirmed in a block after the cut-off. It clears on the next run by itself.
A missing entry. The chain shows 0.0040 ETH less than the ledger. The network fee of an internal sweep was never booked.
An unidentified item. The bank shows 1,000.00 euros the ledger does not have: a transfer arrived without the reference that says whose it is.
Others are a wrong amount, a duplicate, or a real loss. Each one is worked the same way:
Classify and age it. Record the type, the amount and the day it appeared. Ageing shows what has been open too long.
Trace it by reference. The transaction hash, the bank reference, the trade or withdrawal ID lead to the source of the difference.
Fix the books with a new entry. Never an edit, and approved by a second person.
Fix the cause. A bug, a missed fee or a process gap, so the same break does not return tomorrow.
Escalate what stays open. A break past its age limit, or any shortfall in customers' assets, goes to management and compliance.
For the euros, the 1,000.00 is first booked against the bank and an unallocated-receipts account, so the books match the bank while the item stays open. The payer's name matches verified customer C, who forgot the reference; a second entry, approved by a second person, moves it to C's balance. A transfer nobody can match within the operator's set time goes back to the sender. For the ether, the missing fee is booked as a cost, citing the sweep's hash, and the code that skipped it is fixed.

Why auditors and regulators ask for it
In the EU, the Markets in Crypto-Assets Regulation (MiCA) asks a provider that offers custody and administration of crypto-assets on behalf of clients to keep "a register of positions, opened in the name of each client", and its internal procedures must ensure that "any movement affecting the registration of the crypto-assets is evidenced by a transaction regularly registered in the client's register of positions" (Article 75(2)). A ledger where every balance is a sum of entries can serve as that register, with the entries as the evidence.
MiCA also requires records of "all crypto-asset services, activities, orders, and transactions", kept for five years and up to seven where the authority asks (Article 68(9)). Clients' funds other than e-money tokens go to a credit institution or a central bank by the end of the next business day, in an account "separately identifiable" from the provider's own (Article 70(3)). The regulation does not use the word reconciliation, but a daily run is how an operator shows that these registers and accounts agree with what is actually held. The MiCA checklist covers the rest of the licence. This is general information, not legal advice.
Auditors ask for the same thing for their own reasons. To sign off the accounts, they need to see that the balances exist and that nothing is missing, and a reconciled, append-only ledger lets them trace any balance to its entries and any entry to the chain or the bank.
Frequently asked questions
Is the ledger the same as the blockchain? No. The blockchain records the exchange's wallets, not who among its customers owns what. The ledger records every customer's share, and most movements, such as trades and fees, never touch the chain at all.
Why not just edit a wrong balance? Because the history would no longer explain the number. A reversing entry corrects the balance and keeps a record of what went wrong, when, and who fixed it.
How often should reconciliation run? Daily at least, and many exchanges run it more often for the busiest assets. The shorter the gap between runs, the smaller and easier to trace any break.
What happens if a break is a real shortfall? It is escalated at once. Customers' assets must be covered, so the operator investigates, restores what is missing and follows its own rules and its regulator's on reporting.
See it working
A ledger is easiest to judge on a working exchange: deposit, trade and withdraw, and see each balance follow. Open Marengo at marengo.paynoramic.com, read about the ledger module, or see how our white-label crypto exchange is built and handed over to the licensed operator who runs it.



