Guide

USDT on TRC-20 vs ERC-20: which to accept

It is the same dollar of USDT, but the network it rides on changes the experience for both of you. TRC-20 USDT (on Tron) and ERC-20 USDT (on Ethereum) settle to the same fiat figure in your ledger, yet they differ in what the payer pays in network fees, how fast it confirms, and which wallets your customers already hold. The good news is you rarely have to pick one: a fiat-anchored halfin invoice can present both, and the customer settles in whichever they have. This guide explains the real differences, when to steer toward one network, and how to accept both from a single invoice without doubling your integration.

01

Same token, two networks — what actually differs

USDT is a single dollar-pegged stablecoin issued on several chains. "TRC-20" and "ERC-20" are not different coins; they are the token standard on Tron and on Ethereum respectively. One TRC-20 USDT and one ERC-20 USDT are both worth one dollar of USDT. What changes is the rail underneath: who validates the transaction, what the network charges to move it, and how long it takes to be safe to credit.

For a merchant the practical consequences are three. First, the network fee the payer covers to send the transfer — a chain characteristic, paid to the network, not to halfin. Tron transfers are typically cheaper than Ethereum L1 transfers, which is why a large share of stablecoin volume settles on TRC-20. Second, the addresses and wallets differ: a Tron address is not an Ethereum address, and a customer's funds live on whichever chain their exchange or wallet put them on. Third, confirmation behavior differs per chain, so the wait between "payment seen" and "safe to fulfil" is not identical across the two.

None of this changes what lands in your books. halfin anchors the invoice to a fiat amount, computes the payable USDT, and reconciles back to the dollar figure you billed regardless of which network carried it. The network choice is the customer's experience problem to optimize, not your accounting problem.

02

The comparison at a glance

Read the table as "what the payer experiences" rather than "what halfin charges" — halfin's commercial pricing is separate and not a function of the chain. The network-fee column is a qualitative property of each chain, not a number, because gas moves with network conditions.

The pattern that falls out of the table is simple: TRC-20 is the low-friction default most stablecoin payers reach for, while ERC-20 matters when the customer is already operating inside the Ethereum ecosystem and holds their USDT there. Accepting both lets each customer pay from where their money already sits.

PropertyUSDT on TRC-20 (Tron)USDT on ERC-20 (Ethereum)
Token standardTRC-20 on TronERC-20 on Ethereum
Network fee to the payerTypically low — a Tron network characteristicTypically higher — Ethereum L1 gas, varies with congestion
Address formatTron address (distinct from Ethereum)Ethereum address (0x…)
Confirmations before creditPer-Tron threshold, reorg-awarePer-Ethereum threshold, reorg-aware
Who typically holds itExchange-withdrawn stablecoin balances, Asia-heavy flowsDeFi / EVM-native payers, US books that settle on Ethereum
Best forLowest-friction, high-volume stablecoin billingCustomers already operating on Ethereum
03

Why network fees fall on the payer — and why that still matters to you

When a customer sends USDT, the chain charges a network fee for inclusion in a block. That fee is paid by the sender to the network, not to halfin and not to you. So strictly, an Ethereum gas spike does not raise your cost of accepting a payment. But it does raise the customer's, and a payer who is asked to spend a meaningful amount of gas on top of a small order will abandon or complain.

This is the real reason TRC-20 dominates stablecoin payments: on a low-value transfer, the cheaper rail is simply a better checkout. If you sell small-ticket items, present TRC-20 prominently so the network fee never dwarfs the purchase. If your customers are EVM-native and already pay Ethereum gas as a cost of doing business, ERC-20 is not friction for them — it is where their balance already is.

The mistake to avoid is forcing one network on everyone. A customer who only holds ERC-20 USDT, told they must pay on Tron, has to bridge or move funds first — friction you created. A customer who only holds TRC-20, told they must pay on Ethereum, eats avoidable gas. Letting the payer choose removes both problems at once.

  • Network (gas) fees are paid by the sender to the chain — not to halfin, not to you.
  • TRC-20 is usually the cheaper rail for the payer, which is why it carries most stablecoin volume.
  • ERC-20 is not extra friction for EVM-native customers — it is where their USDT already lives.
  • Forcing a single network pushes a bridge/transfer step onto whoever holds the other one.
04

Settlement and confirmations are per-chain, but credit is the same primitive

After a payer broadcasts, the transaction has to confirm before it is safe to treat as paid. halfin waits for the per-chain confirmation threshold and credits reorg-aware: a transaction that a chain reorganization unwinds is reflected rather than ignored. Tron and Ethereum have different thresholds, so the wait between a deposit being seen and the invoice flipping to paid is not identical on the two networks — but the meaning of "paid" is.

Whichever rail the customer used, a paid USDT invoice settles to the same fiat figure you billed, on the same balance, observable through the same dashboard, REST resource, and webhook event. You do not maintain a separate Tron ledger and Ethereum ledger; you maintain one balance, and the network is just metadata on how the money arrived.

Practically, this means your fulfilment logic does not branch on network. You wait for invoice.paid, verify the webhook signature, and fulfil — the same handler covers a TRC-20 payment and an ERC-20 payment. The only network-aware surface is what you show the payer before they pay: address, amount, network label, and countdown.

05

The recommended pattern: one fiat-anchored invoice, payer picks the network

You do not have to choose USDT-on-Tron versus USDT-on-Ethereum at integration time. Create the invoice anchored to a fiat amount — the dollars you actually bill — and let halfin compute the payable USDT and present the supported networks. The customer settles on whichever one they hold; the fiat anchor is identical either way, so your reconciliation does not care which rail won.

This is strictly better than hard-coding a single network. It removes the bridge-or-abandon decision from the customer, it keeps your accounting in one currency, and it future-proofs the integration: USDT also runs on Solana in halfin, so the same fiat-anchored invoice extends to another low-fee rail without a code change on your side.

The call below creates a fiat-anchored invoice. Note the request canon: the only request headers are X-API-Key and Content-Type, and idempotency_key is a snake_case field in the JSON body — not an Idempotency-Key header. Because the amount is anchored in fiat, you are not committing the customer to TRC-20 or ERC-20 here; you are stating the dollar figure and letting halfin price and present the USDT options.

# Fiat-anchored invoice: bill in USD, let the payer settle in USDT on the
# network they already hold (TRC-20, ERC-20, or Solana). The amount is a
# string, and idempotency_key is a BODY field — not a header.
curl -X POST https://api.thehalfin.com/api/v1/invoices \
  -H "X-API-Key: $HALFIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount_fiat": "49.00",
    "fiat_currency": "USD",
    "deferred": true,
    "description": "Pro plan — March",
    "idempotency_key": "00000000-0000-4000-8000-000000000010"
  }'

# halfin locks the rate at activation, pins the payable USDT amount, and the
# customer chooses TRC-20 or ERC-20 at the checkout. Track the result via the
# signed invoice.paid webhook. See docs.thehalfin.com for the response schema.
06

When you do want to pin a single network

Sometimes presenting every option is the wrong call and you want to fix the asset and network up front — a wallet that can only receive on one chain, a treasury policy that keeps stablecoin on one rail, or a flow where you already know the customer's network. In that case you create a fixed-asset invoice: state the crypto currency and amount directly instead of a fiat anchor.

USDT_TRC20 and USDT_ERC20 are distinct currency values. Choosing one pins both the asset and the rail, so the customer is shown a single network to pay on. Use the fiat-anchored pattern when you want maximum payer choice, and pin the currency only when a concrete constraint makes one network the right answer.

The same currency labels apply on the payout side. If you are sending USDT out rather than collecting it — a refund, an affiliate payout — the destination address dictates the network: a Tron address must receive USDT_TRC20, an Ethereum address must receive USDT_ERC20. Sending USDT on a network the destination cannot receive simply rejects that line, so match the currency to the address.

  • Fiat-anchored invoice → maximum payer choice; halfin presents the supported USDT networks.
  • Fixed-asset invoice with USDT_TRC20 or USDT_ERC20 → pins a single rail when a constraint requires it.
  • On payouts, the destination address dictates the network — match USDT_TRC20 / USDT_ERC20 to it.
  • USDT on Solana is a third supported rail; the same fiat-anchored invoice extends to it.
07

A practical decision rule

If you take nothing else from this guide: accept both, and only narrow the choice when you have a reason. A fiat-anchored invoice is the default because it pushes the network decision to the only party who knows where their USDT already sits — the payer — while keeping your books in one currency.

Steer toward TRC-20 in your messaging when you sell small-ticket items or serve customers who withdraw stablecoin from exchanges, because the cheaper rail makes the network fee a non-issue. Lean on ERC-20 when your customers are EVM-native and settle on Ethereum as a matter of course. And reach for a pinned, fixed-asset invoice only when a wallet limitation or a treasury rule removes the choice for you.