← All articles

Token Standards on TRON

“A token transfer” on TRON is not one thing. The chain carries three distinct kinds of value, and they are built on entirely different plumbing. A TRX transfer is a native protocol operation. A TRC-10 transfer is also native — the protocol understands the token directly, without running any code. A TRC-20 transfer is neither: it is a smart contract executing, the same machinery that runs a DeFi swap.

For an investigator, the standard a transfer uses is not a detail. It decides whether the transfer can bring a new account into existence, which resource it consumes, and whether the recipient is a readable field or something buried in call data. This article walks the three standards and what separates them on-chain.

TRX: the native coin

TRX is the base layer everything else sits on. It is “the most important cryptocurrency on the TRON network” — used to pay for resources when an account’s Bandwidth or Energy runs short, staked to obtain those resources and voting rights, and used as collateral in DeFi lending.

Its smallest unit is the SUN, where 1 TRX = 1,000,000 SUN. Amounts in raw transaction data are denominated in SUN, which is why a one-TRX transfer shows an amount of 1000000.

Moving TRX is its own protocol transaction type — TransferContract (type 1), which “transfers TRX from one account to another.” It carries the sender, the recipient, and the amount as top-level fields. There is no code involved: the protocol moves the balance directly.

TRC-10: a token the protocol understands natively

TRC-10 is where TRON differs most sharply from Ethereum. It is “a native token standard supported by the TRON network. Unlike TRC-20 tokens, it does not rely on the TRON Virtual Machine (TVM) but is implemented directly at the blockchain protocol level.” The chain itself knows what a TRC-10 token is — issuing and transferring one runs no contract code at all.

Issuance is a transaction type, not a deployment. Any account can issue a TRC-10 token through the AssetIssueContract transaction type (type 6), “limited to one issuance per account — with a creation fee of 1024 TRX” (a network parameter rather than a fixed constant). There is no Solidity, no bytecode — the token’s name, supply, and precision are fields in a transaction the protocol records directly.

Transfers use their own type. Sending a TRC-10 token is a TransferAssetContract (type 2), introduced “to transfer tokens from one account address to another.” Like a TRX transfer, it exposes the token, sender, recipient, and amount as readable top-level fields.

Because TRC-10 is a protocol-native asset class, the TVM was even extended to handle it: dedicated opcodes like CALLTOKEN and TOKENBALANCE (whose own description names the “trc10 token”) let a contract attach and read TRC-10 value. Those opcodes exist precisely because TRC-10 is something the protocol treats as first-class — covered alongside the rest of the TVM in /learn/smart-contracts-and-the-tvm/. TRC-20 gets no such native support, because a TRC-20 token is not a protocol object at all.

TRC-20: a token that is really a smart contract

TRC-20 is “a set of contract standards for the issuance of token assets.” A TRC-20 token is not a protocol primitive — it is a smart contract that implements a standard interface, running on the TVM. As TRON’s own glossary puts it, TRC-20 is “a technical standard used for smart contracts on the TRON blockchain for implementing tokens with the TRON Virtual Machine.”

The standard is defined by TIP-20 (status: Final), adapted from Ethereum’s ERC-20 — which is possible because the TVM is EVM-compatible. It specifies a fixed interface every compliant token exposes:

FunctionWhat it does
totalSupply()Total tokens in existence
balanceOf(address)An address’s balance
transfer(to, value)Move tokens from the caller
transferFrom(from, to, value)Move tokens the caller was approved to spend
approve(spender, value)Authorize another address to spend the caller’s tokens
allowance(owner, spender)Remaining approved amount

Plus two events — Transfer and Approval — that contracts emit so off-chain readers can follow token movement through logs.

[!NOTE] The approve/allowance pair is where a lot of TRON risk lives. approve() authorizes “a third party (like a DApp smart contract) to transfer the token from the token owner’s account.” A wallet that has approved a malicious contract for an unlimited allowance can be drained later without signing anything further — the approval already granted the permission. Reading a wallet’s outstanding approvals is its own investigative step.

Because a TRC-20 transfer is a contract call — a TriggerSmartContract invoking transfer(address,uint256) — it behaves nothing like a native transfer, and that is the crux of the whole distinction.

The three standards, side by side

TRXTRC-10TRC-20
What it isNative coinProtocol-native tokenSmart contract
Runs on the TVM?NoNoYes
Transfer transaction typeTransferContract (1)TransferAssetContract (2)TriggerSmartContract (31)
Resource consumedBandwidthBandwidthBandwidth and Energy
Can activate a new account?YesYesNo
Recipient on-chainTop-level fieldTop-level fieldEncoded in call data

The resource column follows directly from the architecture. Every transaction consumes Bandwidth, measured by its byte size, and each account gets 600 free Bandwidth per day — the resource model is covered in /learn/stake-2/. But Energy “measures the amount of computation required by the TRON Virtual Machine,” and is consumed only by contract execution. A TRX or TRC-10 transfer runs no code, so it burns Bandwidth alone. A TRC-20 transfer is code, so it consumes Energy on top of the Bandwidth for its bytes.

What the distinction signals on-chain

Only native transfers can activate an account. A TRX or TRC-10 transfer to an uninitialized address creates and activates it; a TRC-20 transfer cannot — a point developed in /learn/account-activation/. The consequence for attribution is direct: a wallet holding nothing but USDT may have been activated by someone else entirely, because the USDT that funds it could never have brought it into existence. TRONORIGIN treats a token-only funding history as a weak attribution signal for exactly this reason — a TRC-20 inflow tells you less about who stood up an address than a native one does.

The recipient is readable for native transfers and hidden for TRC-20. A TransferContract or TransferAssetContract records the recipient as a real to_address field. A TriggerSmartContract does not: its top-level contract_address is the token contract, and the actual recipient and amount are ABI-encoded inside the call data. Reading TRC-20 flow means decoding that data, not reading a field — the mechanics of which belong to /learn/smart-contracts-and-the-tvm/. The dominant TRC-20 on the network, and the one most of this matters for, is USDT — its story is /learn/usdt-on-tron/.

The through-line is that “token transfer” hides three different machines. Knowing which one you are looking at tells you, before you read anything else, whether the transfer could have created the account, what it cost to send, and whether the counterparty is sitting in plain sight or waiting to be decoded.

Sources