Moving crypto between your own wallets and exchanges is not a sale, and therefore not a taxable event. Yet this is exactly where a lot of crypto tax software goes wrong: an outgoing and an incoming transaction are booked as two separate events, resulting in phantom gains and an incorrect cost basis. Cryptotax recognises these internal transfers automatically and keeps your original purchase price intact, across all your accounts.
💡 What is transfer matching?
When you send crypto from one account to another - from Kraken to your MetaMask, from a hot wallet to your Ledger, or via a bridge from Ethereum to Base - you are not selling anything. You still own the same coins. Under the Belgian capital gains tax, a move between your own addresses is not a realisation, so no taxable capital gain arises.
The problem is that the blockchain and the exchange export do not show this as a single movement. You see 0.5 ETH disappear in one place and 0.5 ETH appear in another. Transfer matching is the automatic linking of those two legs into a single non-taxable internal transfer, so your cost basis flows correctly to your new account.
🔍 The problem: phantom gains
Without matching, an internal move is treated as a sale on one account, followed by a purchase on the other. The result is a capital gain that never existed, and a cost basis that is set to the market price at the time instead of your real purchase price.
Suppose: you bought 1 ETH for €1,000. Later, when ETH is worth €2,000, you move that ETH from your exchange to your own wallet.
| Scenario | Taxable capital gain now | Cost basis after the move |
|---|---|---|
| Without transfer matching | €1,000 (phantom gain) | €2,000 (too high) |
| With transfer matching | €0 | €1,000 (original preserved) |
Without matching you therefore pay tax on €1,000 of profit you have not realised, and your future calculation is wrong: because your new basis is set at €2,000, you later report too little profit on the actual sale. With matching your basis stays €1,000 and the capital gain is only calculated when you actually sell.
⚙️ How Cryptotax recognises internal transfers
Our engine combines multiple data points across all your connected wallets and exchanges. Only when enough signals match do we link two transactions as an internal transfer. Strict criteria prevent us from accidentally hiding a real sale.
- Timing - We look for an outgoing and an incoming movement within a logical time window. On-chain transfers are almost instant, exchange withdrawals can take longer.
- Amount - The sent and the received amount must match, taking into account gas and network fees deducted along the way.
- Asset - It must be the same asset: ETH to ETH, USDC to USDC, including wrapped and cross-chain equivalents.
- On-chain data - Transaction hashes and contract interactions are read to recognise bridge patterns and direct transfers.
Gas fees are booked separately as a transaction cost, not as part of the transfer. If a leg is not recognised automatically - for example because the receiving account is not connected - then we flag the transaction so you can confirm it manually.
🌐 Cross-chain: cost basis continuity with bridges
A bridge moves the same coin to another chain, for example ETH from Ethereum to Arbitrum or Base. That is not a sale. Cryptotax links the deposit and withdrawal leg of a bridge into a single continuity flow, so your original purchase price stays intact, regardless of which chain your asset is on.
- The legs are matched on timing and value, and matched events share the same continuity context.
- Bridge fees are linked to that same flow, so everything remains auditable.
- We recognise commonly used bridges such as Across, Hop, Stargate, Orbiter and Circle CCTP across Ethereum, Base and Arbitrum.
Does a protocol immediately bridge to a different asset as well (you send ETH, you receive USDC)? Then that is indeed a taxable swap, and we treat it as such. You can read more about this in Bridging and cross-chain fees.
🔀 Which situations we link automatically
| Scenario | Example | Tax treatment |
|---|---|---|
| Exchange to wallet | Kraken withdrawal to your MetaMask | No sale, basis preserved |
| Wallet to wallet | Hot wallet to your Ledger | No sale, basis preserved |
| Wallet to exchange | Deposit to sell or stake | No sale, basis preserved |
| Cross-chain bridge | ETH from Ethereum to Base or Arbitrum | No sale, basis preserved |
| Withdrawal to CSV deposit | Exchange withdrawal that you import elsewhere as a CSV | Linked across accounts |
Because we link transfers across all your accounts, this also works when your sources complement each other: a withdrawal from an exchange connected via API that you receive again on another platform via a CSV export is recognised as the same movement. This keeps one continuous cost basis, the same logic that our FIFO lot matching also uses.
🧾 Summary
| Aspect | How Cryptotax handles it |
|---|---|
| Internal transfer | Not a taxable event, recognised automatically |
| Cost basis | Original purchase price is preserved |
| Sources | All wallets and exchanges together, cross-account |
| Cross-chain | Bridge legs linked via continuity flow |
| Not recognised? | Transaction flagged for manual confirmation |
✅ Try it today
Want to be sure that moves between your own accounts are not reported as a sale? Connect your wallets and exchanges for free and see in your dashboard how transfer matching keeps your cost basis intact. The more accounts you connect, the more completely we recognise your internal transfers. Also see how we show the linked lots in your tax report.
⚠️ Disclaimer: This article is purely informative and not individual tax advice. For specific cases: consult a recognised Belgian tax specialist or request a ruling from the Office for Advance Tax Rulings.