Token Standards
TRON supports a diverse range of token standards to power your decentralized applications, from native TRC-10 assets to EVM-compatible TRC-20 and TRC-721 tokens. Explore the technical specifications, implementation patterns, and key differences between fungible, non-fungible, and multi-token standards.
TRON has four token standards. Three are smart contracts on the TVM (TRC-20, TRC-721, TRC-1155); one is a protocol-native system (TRC-10) that predates the TVM and requires no contract code.
Comparison
Section titled “Comparison”| Standard | Type | EVM Equivalent | Smart Contract | Resources Required |
|---|---|---|---|---|
| TRC-10 | Native fungible | — | No | Bandwidth only |
| TRC-20 | Contract fungible | ERC-20 | Yes | Bandwidth + Energy |
| TRC-721 | Contract NFT | ERC-721 | Yes | Bandwidth + Energy |
| TRC-1155 | Contract multi-token | ERC-1155 | Yes | Bandwidth + Energy |
TRC-10 — Protocol-Native Tokens
Section titled “TRC-10 — Protocol-Native Tokens”TRC-10 tokens are issued directly by the TRON protocol without deploying a smart contract. Transfers use system transactions rather than TVM execution, so they cost only Bandwidth — no Energy is required.
Issuing a TRC-10 Token
Section titled “Issuing a TRC-10 Token”Issue via the AssetIssueContract API or through TRONSCAN’s token issuance UI.
Cost: 1,024 TRX issuance fee
Limit: One TRC-10 token per account
Key parameters:
name— token name (displayed in wallets)abbr— ticker symboltotal_supply— fixed total supplyprecision— decimal places (0–6)start_time/end_time— optional public sale windowtrx_num/num— exchange rate for public sale (TRX per token)
Transferring TRC-10 Tokens
Section titled “Transferring TRC-10 Tokens”// Task: Send native TRC-10 tokens using their numeric ID.await tronWeb.trx.sendToken( 'TRecipientAddress...', 1000, // amount '1000001', // token ID (numeric string));TRC-10 Limitations
Section titled “TRC-10 Limitations”- No custom contract logic — pure balance ledger
- No
approve/transferFrommechanism - Cannot be used directly in most DeFi protocols, which require TRC-20
- Cannot be composed with smart contracts
TRC-10 is not recommended for new projects. Use TRC-20 unless you have a specific reason to avoid smart contract execution costs (e.g., very high-frequency micro-transfers where Energy costs are prohibitive).
TRC-20 — Fungible Tokens
Section titled “TRC-20 — Fungible Tokens”TRC-20 is TRON’s smart contract fungible token standard, functionally identical to Ethereum’s ERC-20. Standard OpenZeppelin ERC-20 implementations compile and deploy on TRON with no interface changes — review only the TVM-specific differences (timestamps, updated SELFDESTRUCT behavior) before deploying.
(For Web2 developers: A token is not a physical coin moving around the network. A TRC-20 token is simply a smart contract containing a giant dictionary or “ledger” that tracks how many tokens each address owns. A “transfer” is just a function call that deducts from the sender’s balance and adds to the recipient’s balance within this contract’s internal database).
Interface
Section titled “Interface”// Task: Define the standard TRC-20 fungible token interface.// SPDX-License-Identifier: MITpragma solidity ^0.8.18;
interface ITRC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value);}Interacting with TRC-20 via tronweb
Section titled “Interacting with TRC-20 via tronweb”// Task: Perform common TRC-20 operations: balance, transfer, approve.const contract = await tronWeb.contract().at('TContractAddress...');
// Read balance (view call — no Energy cost)const raw = await contract.balanceOf('TUserAddress...').call();const amount = raw / 1e6; // adjust for token decimals
// Transfer (state-changing — costs Energy)await contract.transfer('TRecipient...', 10_000_000).send({ feeLimit: 150_000_000, // 150 TRX max shouldPollResponse: true,});
// Approve a spenderawait contract.approve('TSpender...', 1_000_000_000).send({ feeLimit: 50_000_000,});Key Mainnet TRC-20 Addresses
Section titled “Key Mainnet TRC-20 Addresses”USDT: TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6tUSDD: TPYmHEhy5n8TCEfYGqW2rPxsghSfzghPDnWTRX: TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFRSUN: TSSMHYeV2uE9qYH95DqyoCuNCzEL1NvU3SJST: TCFLL5dx5ZJdKnWuesXxi1VPwjLVmWZZy9Energy Cost
Section titled “Energy Cost”The base Energy cost for a USDT transfer is ~14,650 (existing holder) or ~29,650 (new account with zero balance). Under the Dynamic Energy Model (DEM), a congestion penalty of up to 340% applies, raising the theoretical peak to ~64,460 (existing holder) or ~130,460 Energy (new account). Set fee limits accordingly — a safe default is 20 TRX (feeLimit: 20_000_000).
TRC-721 — Non-Fungible Tokens
Section titled “TRC-721 — Non-Fungible Tokens”TRC-721 is TRON’s NFT standard, equivalent to Ethereum’s ERC-721. The function signatures are identical. There is one critical TRON-specific difference in the safe transfer receiver callback that causes hard-to-debug failures when porting from Ethereum.
Interface
Section titled “Interface”// Task: Define the standard TRC-721 NFT interface.// SPDX-License-Identifier: MITpragma solidity ^0.8.18;
interface ITRC721 { function balanceOf(address _owner) external view returns (uint256); function ownerOf(uint256 _tokenId) external view returns (address); function transferFrom(address _from, address _to, uint256 _tokenId) external payable; function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata _data) external payable; function approve(address _approved, uint256 _tokenId) external payable; function setApprovalForAll(address _operator, bool _approved) external; function getApproved(uint256 _tokenId) external view returns (address); function isApprovedForAll(address _owner, address _operator) external view returns (bool);
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);}Correct TRC-721 Receiver Contract
Section titled “Correct TRC-721 Receiver Contract”Any contract that receives TRC-721 tokens via safeTransferFrom must implement:
// Task: Implement the onTRC721Received callback with the correct TRON selector.// SPDX-License-Identifier: MITpragma solidity ^0.8.18;
contract TRC721Receiver { function onTRC721Received( address _operator, address _from, uint256 _tokenId, bytes calldata _data ) external returns (bytes4) { // Must return the TRC-721 selector: 0x5175f878 return bytes4(keccak256("onTRC721Received(address,address,uint256,bytes)")); }}Optional Extensions
Section titled “Optional Extensions”Metadata:
// Task: Define the NFT metadata extension for names and URIs.interface ITRC721Metadata { function name() external view returns (string memory); function symbol() external view returns (string memory); function tokenURI(uint256 _tokenId) external view returns (string memory);}Enumeration:
// Task: Define the NFT enumeration extension for on-chain indexing.interface ITRC721Enumerable { function totalSupply() external view returns (uint256); function tokenByIndex(uint256 _index) external view returns (uint256); function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);}Minimum Deployment Cost
Section titled “Minimum Deployment Cost”TRC-721 contract deployment requires a minimum of approximately 350 TRX in Energy burn at current network rates (plus Bandwidth for the transaction bytes). Use the Fee Model guide to estimate costs before deploying.
TRC-1155 — Multi-Token Standard
Section titled “TRC-1155 — Multi-Token Standard”TRC-1155 is TRON’s multi-token standard, equivalent to Ethereum’s ERC-1155. A single contract manages multiple token types — both fungible and non-fungible — and supports batch operations that reduce total Energy cost when transferring many tokens in one call.
Interface
Section titled “Interface”// Task: Define the TRC-1155 multi-token standard interface.// SPDX-License-Identifier: MITpragma solidity ^0.8.18;
interface ITRC1155 { function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external; function balanceOf(address owner, uint256 id) external view returns (uint256); function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory); function setApprovalForAll(address operator, bool approved) external; function isApprovedForAll(address owner, address operator) external view returns (bool);
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id);}Optional Metadata Extension
Section titled “Optional Metadata Extension”// Task: Define the multi-token metadata URI extension.interface ITRC1155MetadataURI { function uri(uint256 id) external view returns (string memory);}Batch Transfers
Section titled “Batch Transfers”The primary advantage of TRC-1155 over multiple TRC-721 calls is Energy efficiency. A safeBatchTransferFrom call transfers N token IDs in a single transaction, paying Bandwidth and Energy once rather than N times:
// Task: Perform an efficient batch transfer of multiple token IDs.contract.safeBatchTransferFrom( from, to, [tokenId1, tokenId2, tokenId3], // IDs [amount1, amount2, amount3], // amounts "0x");TRC-721 vs TRC-1155 Decision Guide
Section titled “TRC-721 vs TRC-1155 Decision Guide”| Use case | Standard |
|---|---|
| Classic NFT collection with unique ownership | TRC-721 |
| Game inventory: many item types, some fungible | TRC-1155 |
| Batch minting or batch transfers | TRC-1155 |
| Maximum compatibility with existing NFT tooling | TRC-721 |
| Single contract managing fungible + non-fungible tokens | TRC-1155 |
Token Standard by Transaction Cost
Section titled “Token Standard by Transaction Cost”| Operation | Approximate Energy cost |
|---|---|
| Deploy TRC-20 (standard OpenZeppelin) | 200,000–400,000 |
| TRC-20 transfer | 14,650–29,650 base (×4.4 peak DEM) |
| TRC-20 approve | 20,000–30,000 |
| Deploy TRC-721 | 500,000–900,000 |
| TRC-721 mint | 80,000–150,000 |
| TRC-721 safe transfer | 60,000–100,000 |
| TRC-1155 batch transfer (10 items) | 100,000–180,000 |
These are baseline estimates at energy_factor = 0. The Dynamic Energy Model can multiply costs up to 3.4× for high-demand contracts. Always simulate with triggerconstantcontract on mainnet before setting fee limits.