Category: XML Templates Last Updated: 2026-02-12 Applies To: EU DAC8 / OECD CARF XML Schema

---

Overview

Crypto-to-fiat transactions are the most straightforward category of reportable transactions under DAC8/CARF. When a user sells a crypto-asset and receives fiat currency (EUR, USD, GBP, etc.), the value of the transaction is directly available from the trade settlement. However, there are still important details to get right: value determination, fee handling, timestamp rules, and currency conversion.

This article covers the specific requirements for reporting crypto-to-fiat exchange transactions in DAC8 XML.

What Qualifies as a Crypto-to-Fiat Transaction

A crypto-to-fiat transaction occurs when a user disposes of a crypto-asset and receives fiat currency in return. Common examples:

  • Selling BTC for EUR on an exchange order book
  • Converting ETH to USD through a market or limit order
  • Liquidating any crypto-asset position into fiat currency
  • Automatic conversions (e.g., auto-sell features)

Not included:

  • Fiat deposits or withdrawals that do not involve a crypto-asset exchange
  • Internal ledger movements that do not result in an actual exchange

Value Determination

For crypto-to-fiat exchanges, the gross proceeds is the total amount of fiat currency received by the user as a result of the exchange.

Before or After Fees?

This is a critical implementation question. The OECD CARF framework refers to "gross proceeds," which generally means the total consideration before deduction of fees:

ScenarioGross Proceeds
User sells 1 BTC, receives 28,000 EUR, platform charges 50 EUR fee28,050 EUR (before fee deduction)
User sells 1 BTC, receives 28,000 EUR net (fee already deducted from trade price)Depends on how fees are structured

> Caution: The treatment of fees may vary by jurisdiction. Some tax authorities may define gross proceeds as the amount actually credited to the user's account. If your jurisdiction has published specific guidance, follow it. If not, reporting the pre-fee amount is generally the more conservative approach. Document your methodology.

Example Trade Record

Trade ID:       TRD-2025-000456
User:           USR-00042
Action:         SELL
Asset:          BTC
Quantity:       0.25000000
Fiat received:  8,250.00 EUR
Platform fee:   20.00 EUR
Net credited:   8,230.00 EUR
Timestamp:      2025-06-15T14:32:17Z

If reporting gross proceeds before fees: 8,250.00 EUR If reporting net proceeds after fees: 8,230.00 EUR

Currency Conversion

If the user sells crypto for a fiat currency other than your reporting currency, you must convert:

User sells 0.5 BTC for 15,000 USD on 2025-09-10
ECB EUR/USD rate on 2025-09-10: 1.09

Gross proceeds in EUR = 15,000 / 1.09 = 13,761.47 EUR

Rules for conversion:

  • Use the exchange rate on the date of the transaction
  • Use a reputable, consistent source (e.g., ECB reference rates, or your platform's own rates if they are market-based)
  • Apply the same methodology for all users and all transactions
  • Document and retain the exchange rates used

Timestamp Rules

Each transaction has a timestamp indicating when it was executed. For reporting purposes:

  • Use the execution timestamp (when the trade was matched/settled), not the order placement time
  • Timestamps determine which reporting period a transaction falls into
  • A trade executed at 2026-12-31T23:59:59Z falls in the 2026 reporting period
  • A trade executed at 2027-01-01T00:00:01Z falls in the 2027 reporting period

Time zone considerations: Transaction timestamps should be in UTC for consistency. If your platform records timestamps in local time, convert to UTC for the purpose of determining the reporting period boundary.

Pending and Unsettled Trades

Only report transactions that have been fully settled. If a trade was initiated but not completed (e.g., pending settlement at year-end), it should be reported in the period when settlement occurs, not when the order was placed.

XML Encoding

Single Crypto-Asset Example

<TransactionSummary>
  <TransactionType>EXCHANGE_FIAT</TransactionType>
  <NumberOfTransactions>47</NumberOfTransactions>
  <AggregateGrossProceeds currCode="EUR">28500.00</AggregateGrossProceeds>
  <CryptoAssetDetails>
    <AssetCode>BTC</AssetCode>
    <TotalUnits>0.85000000</TotalUnits>
  </CryptoAssetDetails>
</TransactionSummary>

Multiple Fiat Currencies Received

If a user sold BTC for both EUR and USD during the year, and both are converted to EUR for reporting:

<!-- All BTC-to-fiat exchanges aggregated into one summary, converted to EUR -->
<TransactionSummary>
  <TransactionType>EXCHANGE_FIAT</TransactionType>
  <NumberOfTransactions>47</NumberOfTransactions>
  <AggregateGrossProceeds currCode="EUR">28500.00</AggregateGrossProceeds>
  <CryptoAssetDetails>
    <AssetCode>BTC</AssetCode>
    <TotalUnits>0.85000000</TotalUnits>
  </CryptoAssetDetails>
</TransactionSummary>

All crypto-to-fiat transactions for the same crypto-asset are aggregated into a single TransactionSummary, regardless of which fiat currency was originally received. The aggregate value is always in the reporting currency.

Aggregation Workflow

Step-by-step process for generating the crypto-to-fiat section:

  1. Query all completed sell/exchange transactions where fiat was received, for the reporting period
  2. Filter for the specific user and crypto-asset
  3. Convert each transaction's fiat amount to the reporting currency (if necessary)
  4. Sum the converted amounts to get AggregateGrossProceeds
  5. Sum the crypto-asset quantities to get TotalUnits
  6. Count the transactions to get NumberOfTransactions
  7. Round the aggregate proceeds to 2 decimal places

SQL Example

SELECT
    t.user_id,
    t.crypto_asset AS asset_code,
    COUNT(*) AS num_transactions,
    ROUND(SUM(
        CASE
            WHEN t.fiat_currency = 'EUR' THEN t.fiat_amount
            ELSE t.fiat_amount / fx.eur_rate
        END
    ), 2) AS aggregate_gross_proceeds_eur,
    SUM(t.crypto_amount) AS total_units
FROM trades t
LEFT JOIN fx_daily_rates fx
    ON fx.currency = t.fiat_currency
    AND fx.rate_date = DATE(t.executed_at)
WHERE t.trade_type = 'SELL'
  AND t.settlement_type = 'FIAT'
  AND t.status = 'COMPLETED'
  AND t.executed_at >= '2026-01-01T00:00:00Z'
  AND t.executed_at < '2027-01-01T00:00:00Z'
  AND t.user_id = 'USR-00042'
GROUP BY t.user_id, t.crypto_asset;

Common Pitfalls

  1. Forgetting to report acquisitions. Under CARF Section II.A.3, both disposals (selling crypto for fiat) and acquisitions (buying crypto with fiat) are reportable Exchange Transactions. They are reported in separate aggregate sub-categories: acquisitions under Section II.A.3(b) and disposals under Section II.A.3(c). Do not omit either direction.
  1. Double-counting. Ensure each trade record is counted exactly once. If your system records both a buy and sell side for each order, use only the sell side.
  1. Incorrect reporting period. Verify that year-boundary transactions are assigned to the correct period based on execution time, not order time.
  1. Missing currency conversions. If any trades settled in non-reporting-currency fiat, ensure conversion is applied before aggregation.
  1. Inconsistent fee treatment. Whatever approach you use for fees (gross vs. net), apply it uniformly across all transactions and all users.

Need help with DAC8 reporting?

Our team handles XML generation, TIN validation, and submission for CASPs across all 27 EU Member States.

Get Expert Help