Skip to content

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.


StandardTypeEVM EquivalentSmart ContractResources Required
TRC-10Native fungibleNoBandwidth only
TRC-20Contract fungibleERC-20YesBandwidth + Energy
TRC-721Contract NFTERC-721YesBandwidth + Energy
TRC-1155Contract multi-tokenERC-1155YesBandwidth + Energy

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.

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 symbol
  • total_supply — fixed total supply
  • precision — decimal places (0–6)
  • start_time / end_time — optional public sale window
  • trx_num / num — exchange rate for public sale (TRX per token)
send_trc10.js
// Task: Send native TRC-10 tokens using their numeric ID.
await tronWeb.trx.sendToken(
'TRecipientAddress...',
1000, // amount
'1000001', // token ID (numeric string)
);
  • No custom contract logic — pure balance ledger
  • No approve/transferFrom mechanism
  • 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 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).

ITRC20.sol
// Task: Define the standard TRC-20 fungible token interface.
// SPDX-License-Identifier: MIT
pragma 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);
}
trc20_sdk.js
// 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 spender
await contract.approve('TSpender...', 1_000_000_000).send({
feeLimit: 50_000_000,
});
USDT: TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t
USDD: TPYmHEhy5n8TCEfYGqW2rPxsghSfzghPDn
WTRX: TNUC9Qb1rRpS5CbWLmNMxXBjyFoydXjWFR
SUN: TSSMHYeV2uE9qYH95DqyoCuNCzEL1NvU3S
JST: TCFLL5dx5ZJdKnWuesXxi1VPwjLVmWZZy9

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 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.

ITRC721.sol
// Task: Define the standard TRC-721 NFT interface.
// SPDX-License-Identifier: MIT
pragma 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);
}

Any contract that receives TRC-721 tokens via safeTransferFrom must implement:

TRC721Receiver.sol
// Task: Implement the onTRC721Received callback with the correct TRON selector.
// SPDX-License-Identifier: MIT
pragma 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)"));
}
}

Metadata:

ITRC721Metadata.sol
// 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:

ITRC721Enumerable.sol
// 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);
}

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 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.

ITRC1155.sol
// Task: Define the TRC-1155 multi-token standard interface.
// SPDX-License-Identifier: MIT
pragma 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);
}
ITRC1155Metadata.sol
// Task: Define the multi-token metadata URI extension.
interface ITRC1155MetadataURI {
function uri(uint256 id) external view returns (string memory);
}

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:

batch_transfer.sol
// Task: Perform an efficient batch transfer of multiple token IDs.
contract.safeBatchTransferFrom(
from,
to,
[tokenId1, tokenId2, tokenId3], // IDs
[amount1, amount2, amount3], // amounts
"0x"
);
Use caseStandard
Classic NFT collection with unique ownershipTRC-721
Game inventory: many item types, some fungibleTRC-1155
Batch minting or batch transfersTRC-1155
Maximum compatibility with existing NFT toolingTRC-721
Single contract managing fungible + non-fungible tokensTRC-1155

OperationApproximate Energy cost
Deploy TRC-20 (standard OpenZeppelin)200,000–400,000
TRC-20 transfer14,650–29,650 base (×4.4 peak DEM)
TRC-20 approve20,000–30,000
Deploy TRC-721500,000–900,000
TRC-721 mint80,000–150,000
TRC-721 safe transfer60,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.