VaultNow Blog
Try free
Guides

Crypto Reconciliation: How to Match On-Chain Payments to Your Books

Wallet exports and ledgers share almost no common identifier. Nine break types, the identifiers that actually match, rate policy, gas, batch payouts and a month-end sequence that finishes.

By VaultNow Team 17 min read
Crypto Reconciliation: How to Match On-Chain Payments to Your Books
Aug 2026
On this page
  1. Why a wallet and a ledger disagree even when nothing went wrong
  2. The identifiers you can actually match on
  3. Which exchange rate, at which moment
  4. Gas belongs on its own line
  5. Moving your own money is not a payment
  6. Failed transactions still cost money
  7. One hash, thirty-eight obligations
  8. The three-way match, adapted
  9. A month-end sequence that finishes
  10. Controls that prevent breaks rather than explain them
  11. When the break is on the counterparty’s side
  12. Frequently asked questions

August closes on a Sunday. The wallet export has 63 outgoing USDT transfers. The accounting system has 58 supplier bills marked paid. Two of the extra five are payments that went out twice because the first attempt looked stuck. One is a test transfer of 1 USDT to a new vendor address. One is gas top-up moved from the treasury wallet to the operating wallet. And one is a payment the ops lead made on Friday evening and told nobody about.

Finding that takes four hours. Doing it every month takes 48 hours a year, and the four hours are not the real cost. The real cost is that until it is finished, the company cannot say what its cash position is.

Wallet balances and ledger balances drift apart for a reason that has nothing to do with carelessness. A bank statement and a ledger share a vocabulary: a payment reference, a beneficiary name, a value date. A blockchain and a ledger share almost nothing. The chain knows a hash, two addresses, a token contract and a block timestamp. The ledger knows a supplier, an invoice number, a currency and a period. Nothing on either side points at the other — the job of reconciliation is to build that pointer and then keep it.

Why a wallet and a ledger disagree even when nothing went wrong

Start with what the chain actually gives you. A transfer produces a transaction hash, a sender address, a recipient address, a token contract address, an amount in the token’s smallest unit, a block number and a block timestamp. That is the whole record. An ERC-20 transfer carries no memo field for a supplier reference, no beneficiary name for a bank to validate, and no rejection when the details do not match.

Now look at what your ledger needs to close a payable. It needs to know which supplier, against which invoice, in which reporting currency, on which date, with which portion of the amount treated as a fee. Four of those five are absent from the chain data. You supply them, or the row stays unmatched.

That gap produces a predictable set of breaks, and the useful move is to name them before they happen rather than investigate each one as a novelty.

Break

What the chain shows

What the ledger shows

Usual cause

Unmatched outflow

A confirmed transfer

Nothing

Payment made outside the approval process, or a bill not yet entered

Unmatched inflow

A confirmed receipt

Nothing

Customer paid early, paid without referencing an invoice, or overpaid

Amount off by a few units

4,999.94 USDT

5,000.00 USDT

Sender paid net of a withdrawal fee charged by their exchange

Amount off by a lot

500 USDT

5,000 USDT

Partial payment, or a decimal error at entry

One hash, many bills

A single transfer of 47,300 USDT

38 separate supplier bills

A batch payout settled as one on-chain movement

Duplicate

Two transfers, same amount, same address

One bill

Retry after a transfer looked stuck

Internal movement booked as spend

A transfer between two of your own addresses

An expense

Self-transfer treated as a payment

Failed transaction with a cost

Gas consumed, no token movement

Nothing

Reverted transfer, usually insufficient allowance or gas

Right amount, wrong network

Nothing on the network you checked

A bill marked paid

Sent as TRC-20 while the recipient watched an ERC-20 address

Most of those rows are structural rather than careless: they arise from how chain data and ledger data are shaped, and they will recur every month. If your process treats all nine as one-off anomalies to investigate individually, the close will take as long next month as it did this month.

The identifiers you can actually match on

Bank reconciliation works because a payment reference survives the journey. Chain reconciliation works when you deliberately create something that survives instead.

What banking uses

Chain equivalent

Reliability

Payment reference or remittance advice

None on the transfer itself

Absent

Beneficiary name

Recipient address

High, if you keep an address book

Value date

Block timestamp

High, and precise to the second

Statement line ID

Transaction hash

Absolute, and unique

Amount

Amount, to the token’s decimal precision

High

Currency

Token contract address

High, and this is what tells USDT from a lookalike

The transaction hash is the only identifier with no ambiguity at all — and it is the one bookkeeping processes most often fail to store. Write it into the payment record at the moment of sending. Not later, not from a screenshot. If the hash lives on the bill, every subsequent question about that payment has a one-step answer.

The second identifier worth building is the address book. An address that appears in your outflows and is not in your address book is either a new supplier or a problem, and both deserve attention. Once addresses carry supplier names inside your own systems, the unmatched-outflow, unmatched-inflow and internal-movement rows above resolve on sight.

The third is the token contract address. Amount and ticker are not enough. Two tokens can both call themselves USDT, and one of them can be worthless. Matching on the contract address is what makes a receipt real.

Which exchange rate, at which moment

This is where reconciliation stops being a data problem and starts being an accounting one, and it is one of the places auditors push hardest.

A stablecoin transfer is not a dollar transfer. A payment of 5,000 USDT is a payment of 5,000 units of a token that usually trades near a dollar and sometimes does not. Your books are kept in a reporting currency, so a rate is applied, and the rate has to come from somewhere defensible.

Three questions decide it. Which price source. Which moment. Which policy for the difference.

Source. Pick one and write it down. A single exchange’s spot price, an index, or your own settlement rate if you convert immediately. Any of these can be defended. Switching between them month to month cannot.

Moment. The candidates are the invoice date, the payment initiation time, the block timestamp of confirmation, and the time you converted to fiat. The block timestamp has the advantage of being verifiable by anyone who looks at the chain, which is a property no other candidate has.

Difference. If you invoice in a fiat amount and settle in tokens, the gap between the invoice-date rate and the settlement rate has to land somewhere. Most companies book it to foreign exchange gain or loss. That treatment is only coherent if the policy says so in advance, because the alternative is a growing pile of small unexplained differences that eventually add up to a number somebody asks about.

The related question of how to write the rate lock into the document itself is covered in the crypto invoicing guide, and the underlying record-keeping framework sits in crypto bookkeeping.

Basis is a separate obligation from rate policy, and it has a hard requirement behind it. Treas. Reg. §1.1012-1(j) requires basis to be tracked per wallet or account from 1 January 2025. Rev. Proc. 2024-28 is an optional transitional safe harbour for allocating unused basis from before that date, and it is not the source of the requirement. Getting that pairing backwards is common in published commentary and it matters, because a safe harbour you decline to use does not relieve you of a regulation.

Gas belongs on its own line

A transfer costs the token amount plus a network fee, and those two numbers behave differently. The token amount settles a payable. The network fee is an operating cost you incurred to settle it — a different thing, on a different line.

Booking them together produces a payable that keeps refusing to close cleanly, because the supplier was owed 5,000 and your bank line says 5,000 plus a fee. Booking them separately produces a clean payable and a gas expense account that tells you something useful at year end.

The size of that account is worth checking against current conditions rather than against what you remember. On 27 August 2026, Ethereum base gas sat at 0.039 gwei with ETH at $2,044, and a USDT ERC-20 transfer cost about $0.03. On the same reading, a USDT TRC-20 transfer cost $2.15 to $4.50, the range depending on whether the destination address already held USDT. That is Ethereum at roughly a seventieth to a hundred-and-fiftieth of Tron’s cost, which inverts the ordering most cost tables still print.

Two cautions on that. Ethereum gas is volatile: the same measurement taken on 26 August 2026 read 0.77 gwei, twenty times higher. And the network your recipient can actually receive on is a constraint you do not get to optimise away. The trade-offs between the two are set out in ERC-20 vs TRC-20.

For reconciliation purposes, the practical rule is that gas gets recorded in the token it was paid in and converted at the same moment as the transfer it belongs to. Recording gas in dollars only, with no record of the ETH or TRX amount, breaks the ETH and TRX wallet reconciliation instead. The problem moves — it does not disappear.

Moving your own money is not a payment

Companies that run more than one wallet generate internal transfers constantly: treasury to operating, operating to a payout wallet, hot to cold. Every one of those appears in an export as an outflow from one address and an inflow to another.

The IRS position in its digital asset guidance is that moving assets between wallets you own is not a disposition, “except to the extent of any digital assets you use, or are withheld, to pay for transaction services to effect the transfer”. The move itself creates no gain or loss; the fee leg is treated separately. What it creates is two ledger rows that cancel, and a reconciliation process that has to recognise them as a pair.

The way to make that automatic is to maintain a list of your own addresses and mark any transfer whose counterparty is on that list as internal before the matching step runs. Companies that skip this discover it at audit, when the expense account contains six figures of money that never left the business.

Two wallets. That is usually all it takes for the problem to appear, and the fix costs nothing if it is built at the start.

Failed transactions still cost money

A transaction that reverts consumes gas and moves no tokens. On the chain it is a real transaction with a real cost and a status flag. In most wallet exports it either appears with a zero token amount or does not appear at all, depending on the tool.

The result is a native-token balance that drops with no corresponding transfer to explain it. If your ETH wallet is short by an amount you cannot trace, reverted transactions are the first place to look.

We found no ruling, regulation or notice addressing the treatment of that gas directly as at 27 August 2026, so any confident statement about it is an extrapolation rather than a citation. For reconciliation the point is narrower: capture the hash, the status, the gas consumed and the payment it was attempting, and the balance stops being unexplained.

One hash, thirty-eight obligations

Batch payouts are the reconciliation problem that most tooling handles worst. A single on-chain event settles many separate obligations, and a one-to-one matcher has nothing to say about it.

The fix is to stop trying to match at the transaction level and match at the batch level instead. The batch file you uploaded is the reconciliation key. It contains recipient addresses and amounts. The chain contains the same addresses and amounts. Matching the file against the chain result gives you a per-recipient outcome, and the ledger entries then hang off the file rather than off the hash.

That gives you four things a hash alone does not:

  1. A per-row status, so a batch where 36 of 38 rows landed is not reported as a success.

  2. An amount that ties to the sum of the individual obligations rather than to a single lump.

  3. A place to record the gas allocation, if you allocate gas across recipients rather than to a single expense line.

  4. An audit trail that shows who approved the file, which is the control that matters most.

The mechanics of running the batch itself, including the platform comparison, sit in the mass crypto payout system guide. What matters here is that the file survives as a document. A batch payout with no retained file is a lump sum with no explanation.

The three-way match, adapted

Purchase order, goods receipt, invoice. The classic control does transfer to on-chain payment, with one addition and one substitution.

The addition is the address confirmation. Before the first payment to any counterparty, the address is confirmed through a channel other than the one the invoice arrived on. Invoice fraud in crypto payments is address substitution, and it works because a 42-character string rarely gets re-read. A confirmation by voice, or against an address already on file from a previous relationship, closes most of it. Pre-send screening closes another part of it, and the mechanics of that are in cryptocurrency address screening.

The substitution is that the payment leg is evidenced by a hash rather than a bank statement line. That is an improvement, because the hash is verifiable by a third party without your cooperation. An auditor can confirm that a transfer of a stated amount from your address to a stated address occurred in a stated block, without asking you for anything. Few conventional payment records offer that.

What the hash does not evidence is who controlled the receiving address, and that remains a documentation question rather than a chain question. The contract, the invoice and the address confirmation together carry it. The clause language for that is in the crypto contractor agreement.

A month-end sequence that finishes

The order matters, because each step removes noise from the next one.

1. Pull the full transaction list per address, not the balance. Balances tell you the answer; transactions tell you how you got there. Pull every address the company controls, including ones with tiny balances.

2. Tag internal transfers first. Any transfer where both sides are your own addresses is marked and set aside. This usually removes the largest single block of rows.

3. Separate native-token movements from token movements. Gas top-ups, gas spend and reverted transactions live in the native-token ledger. Mixing them with USDT movements is what makes month-end feel unmanageable.

4. Match on hash where the hash was recorded. Every row where the hash is already on the bill closes immediately. The proportion of rows that close at this step is a direct measure of how well the payment process is working.

5. Match remaining rows on address plus amount plus date window. Most of what survives step 4 closes here.

6. Apply the rate policy to what is left and post. One rate source, one moment, applied consistently.

7. List the unmatched rows with a named owner and a date. A break with no owner is a break that reappears next month.

8. Check dust and unsolicited inflows separately. Small unexpected receipts are not revenue and should not be booked as revenue. They are also occasionally a targeting technique, and an address that receives one is worth a second look before its next outbound payment.

The measure of whether this is working is not whether the balance ties. It is what proportion of rows closed at step 4. Where nearly every payment carries its hash from the moment of sending, the close is short. Where the hash is reconstructed afterwards from a block explorer, the same reconstruction happens every month, permanently.

Controls that prevent breaks rather than explain them

Reconciliation quality is decided before the payment, not after it.

A single place where payments originate. Breaks multiply with the number of people who can send from a wallet without leaving a record. Concentrating outbound payments in one system with named approvers removes most of the “payment nobody knew about” category. Role separation matters more than tooling here: the person who adds a payee should not be the person who releases the payment.

An address book rather than copy-paste. Reusing a stored address rather than pasting a fresh one removes both the substitution risk and the unmatched-counterparty break.

A test transfer policy with a rule for what happens next. Test transfers are sensible and they generate unmatched rows. Decide in advance whether they are expensed, netted against the first real payment, or booked to a clearing account, and apply that rule every time.

A retained batch file for every bulk run. Covered above, and worth repeating because it is the habit that pays back fastest.

A monthly comparison of on-chain balance to ledger balance per address, not in aggregate. Aggregate balances hide offsetting errors. Per-address comparison surfaces them in the month they occur.

Tooling helps to the extent that it keeps these in one place. Running payouts, invoicing and address screening through a single dashboard, with team permissions set so that entry and release are separate roles, means the reconciliation key exists before the payment does. VaultNow was built around that ordering: bulk payouts of up to 100 transactions from a CSV or address book, invoicing, and screening in the same place, at $0.50 per transaction plus gas.

When the break is on the counterparty’s side

Sometimes the chain and your books agree and the supplier still says they were not paid. Three explanations cover most cases.

The first is a network mismatch: you sent on one network, they watched an address on another. Whether that is recoverable turns on whether the recipient holds the private key, and the three outcomes are set out in crypto payouts.

The second is a restricted destination. USDT’s contract carries a blacklist, and tokens sent to a blacklisted address land there and cannot be moved on. Screening before sending is what catches this.

The third is that the counterparty is looking at the wrong address, which is more common than it sounds when a company rotates deposit addresses.

In all three cases the hash is the artefact that ends the argument. You can point at a block, an amount and a destination. What you cannot do is reverse it. There is a narrow analogue in conventional payments: under UCC 4A-402(c) and (d), where a funds transfer is not completed, the sender is entitled to a refund with interest, and UCC 4A-207 addresses payment orders where the beneficiary name and account number disagree. On-chain settlement has no equivalent of either. That asymmetry is the strongest argument for spending time on the address before the payment rather than on the reconciliation afterwards.

Frequently asked questions

What is crypto reconciliation?

Matching every on-chain movement in and out of the wallets a company controls against the entries in its accounting records, so that each transfer is tied to a supplier, an invoice, a rate and a period, and any remaining difference has a named explanation.

How do you reconcile a crypto wallet?

Export the full transaction list for each address rather than the balance, mark internal transfers between your own addresses, separate native-token movements from token movements, match on transaction hash where it was recorded, match the rest on address plus amount plus date, apply your rate policy, and list what remains with an owner and a due date.

Why doesn’t my wallet balance match my books?

The frequent causes are internal transfers booked as expenses, gas recorded in the wrong currency, reverted transactions that consumed gas without moving tokens, batch payouts settled as one hash against many bills, and payments made outside the approval process.

What exchange rate should I use for crypto transactions?

One source and one moment, chosen in advance and applied consistently. The block timestamp of confirmation has the advantage of being independently verifiable. The difference between the invoice-date rate and the settlement rate is generally taken to foreign exchange gain or loss, and the policy should say so before it happens.

Do I need to track cost basis per wallet?

Treas. Reg. §1.1012-1(j) requires basis to be tracked per wallet or account from 1 January 2025. Rev. Proc. 2024-28 is an optional transitional safe harbour for allocating basis unused before that date, not the source of the requirement.

How do you reconcile a batch payout?

Match at the batch-file level rather than the transaction level. The uploaded file holds recipient addresses and amounts; the chain holds the same. Comparing them gives a per-recipient outcome, and the ledger entries hang off the file. Retain the file, including who approved it.

Is transferring crypto between my own wallets a taxable event?

The IRS digital asset guidance treats a move between wallets you own as not a disposition, “except to the extent of any digital assets you use, or are withheld, to pay for transaction services to effect the transfer”. The move itself produces no gain or loss; the fee leg is separate. In reconciliation the transfer is tagged as internal before matching runs, and the fee is booked as gas.

How should gas fees be recorded?

As a separate expense line from the payable being settled, in the token they were paid in, converted at the same moment as the transfer they belong to. Recording gas in fiat only breaks the reconciliation of the ETH or TRX wallet instead.


Do one thing this week: add a transaction-hash field to your payment record and make it required at the moment of sending. Nothing else on this page delivers as much for as little. Next month, measure what proportion of rows closed on hash alone, and use that number to decide what to fix after that. If payments, invoices and address screening already run through a single dashboard with entry and release split across roles, as they do in VaultNow, the hash is captured for you and the measurement starts at a much higher number.

This article is general information, not legal, tax or accounting advice. Positions are stated as at 27 August 2026 and rules change. Check your own facts with your own adviser.

Read next