Paynoramic launches Marengo, a white-label crypto exchange you can try before you buy.Meet Marengo, our white-label exchange. See the exchange.

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 deposit of 0.5000 BTC as one ledger entry, debiting the Bitcoin wallets and crediting customer A, and a daily reconciliation at 00:00 UTC matching the ledger's 0.5000 with the chain's 0.5000, under the headline "How an exchange keeps its books

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.

How a crypto exchange keeps its books, from one deposit, trade and withdrawal in a double-entry ledger to the daily reconciliation and a break · Watch on YouTube

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.

Three journal entries for customer A, with illustrative numbers: a deposit of 0.5000 BTC, a sale of 0.2000 BTC to customer B for 12,000.00 EUR with a 12.00 EUR fee, and a withdrawal of 0.1000 BTC with a 0.0005 BTC fee and a 0.0002 BTC network fee; every entry balances, and after them the books hold

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.

Correcting a duplicated fee by reversal, illustrative: the original fee of 12.00 EUR, the same fee posted again by a retried message, and a reversing entry that returns 12.00 EUR to customer A and cites the duplicate; A's balance goes from 11,988.00 to 11,976.00 and back to 11,988.00, and all three

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.

Two real screens from Marengo's backoffice: the six lines of one trade entry, each with its account, asset, amount and balance after, with BTC and USDT each summing to zero and marked balanced; and the reconciliation page, whose ledger checks are that every asset sums to zero, held balances equal op

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:

  1. The wallets. The ledger's wallet accounts against the balances on chain at a fixed block, for every address the exchange controls.

  2. The custodian. Coins held by a custodian against the custodian's own statement.

  3. The bank. The client euro account against the bank's statement for the same day.

  4. Trades and postings. Every trade from the matching engine against the ledger, one set of postings each.

  5. 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.

A daily reconciliation at 00:00 UTC, illustrative: USDT matches at 503,200.00 on both sides; BTC shows 152.4180 in the ledger and 152.5180 on chain, a timing break from a withdrawal sent at 23:59 and confirmed after the cut-off; ETH shows 820.4000 against 820.3960, a missing entry for a sweep's netw

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:

  1. Classify and age it. Record the type, the amount and the day it appeared. Ageing shows what has been open too long.

  2. Trace it by reference. The transaction hash, the bank reference, the trade or withdrawal ID lead to the source of the difference.

  3. Fix the books with a new entry. Never an edit, and approved by a second person.

  4. Fix the cause. A bug, a missed fee or a process gap, so the same break does not return tomorrow.

  5. 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.

Investigating a break in five steps: classify and age it, trace it by reference, fix the books with a new entry approved by a second person, fix the cause, and escalate what stays open; worked for an unidentified 1,000.00 EUR transfer, parked in unallocated receipts, matched to customer C by the pay

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.

Written by

Paynoramic's Head of IT

Head of IT at Paynoramic, responsible for the module library every platform is built from. Has worked on payment, banking and workforce platforms for companies including American Express, Teya and Indeed Flex, and for a global card issuer-processor. Writes about what a fintech or crypto launch needs beyond the software: licensing, certification and the real cost.