TRC-721 protocol interfaces
Full reference for every function and event in the TRC-721 standard and its optional extensions.
Prerequisites
This page is the reference for every function and event defined by TRC-721. TRC-721 is the TRON standard for non-fungible tokens (NFTs). The TRC-20 fungible-token standard is not sufficient for NFTs because each TRC-721 token is unique and needs its own tokenId, owner, and optional metadata.
TRC-721 is the TRON counterpart to Ethereum's ERC-721, and the two are interface-compatible.
Required interfaces
Every TRC-721 contract must implement the TRC-721 and TRC-165 interfaces.
pragma solidity 0.5.10;
interface TRC721 {
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);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) 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);
}
interface TRC165 {
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}Function reference
| Function | Purpose |
|---|---|
balanceOf(address _owner) | Returns the number of NFTs owned by _owner. |
ownerOf(uint256 _tokenId) | Returns the current owner of _tokenId. |
safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) | Transfers _tokenId from _from to _to, invoking onTRC721Received on _to if it is a contract. |
safeTransferFrom(address _from, address _to, uint256 _tokenId) | Same as above with empty data. |
transferFrom(address _from, address _to, uint256 _tokenId) | Transfers _tokenId without the receiver-hook check. The caller is responsible for verifying that _to can handle the NFT; otherwise the token may be permanently lost. |
approve(address _approved, uint256 _tokenId) | Grants _approved the authority to transfer _tokenId. |
setApprovalForAll(address _operator, bool _approved) | Grants or revokes _operator the authority to transfer every NFT the caller currently owns and will ever own. |
getApproved(uint256 _tokenId) | Returns the address currently approved for _tokenId, or the zero address if none. |
isApprovedForAll(address _owner, address _operator) | Returns true if _operator has been approved to manage every NFT owned by _owner. |
supportsInterface(bytes4 interfaceID) | From TRC-165. Returns true if the contract implements the interface identified by interfaceID. |
Event reference
| Event | Fires when |
|---|---|
Transfer(_from, _to, _tokenId) | A successful transferFrom or safeTransferFrom moves a token. Also fires on mint (_from = 0x0) and burn (_to = 0x0). |
Approval(_owner, _approved, _tokenId) | approve succeeds, setting a new approved address for one token. |
ApprovalForAll(_owner, _operator, _approved) | setApprovalForAll succeeds, toggling an operator. |
TRC721TokenReceiver — required for contracts that accept safe transfers
A wallet, broker, or auction contract that accepts NFTs via safeTransferFrom must implement the receiver hook:
interface TRC721TokenReceiver {
function onTRC721Received(
address _operator,
address _from,
uint256 _tokenId,
bytes calldata _data
) external returns (bytes4);
}onTRC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data)
onTRC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data)Works in tandem with safeTransferFrom. When _to is a contract, safeTransferFrom calls onTRC721Received on that contract and checks the return value. The contract must return the hash bytes4(keccak256("onTRC721Received(address,address,uint256,bytes)")). Any other return value causes the transfer to revert.
NoteThe TRC-721 hash is different from the Ethereum ERC-721 hash. Return
0x5175f878(TRON), not0x150b7a02(Ethereum). This is the most common porting bug when moving contracts from Ethereum.
Metadata extension (optional)
The metadata extension lets your contract expose human-readable names, symbols, and per-token URIs. Wallets and marketplaces rely on this extension to render tokens.
interface TRC721Metadata {
function name() external view returns (string memory _name);
function symbol() external view returns (string memory _symbol);
function tokenURI(uint256 _tokenId) external view returns (string memory);
}| Function | Purpose |
|---|---|
name() | Returns the human-readable collection name. |
symbol() | Returns a short symbol for the collection. |
tokenURI(uint256 _tokenId) | Returns a URI pointing to a JSON metadata file describing the individual token. |
The metadata JSON file should include a name, description, and image field. Host it on IPFS, BTFS, or your own CDN — if the URI eventually goes offline, the NFT's metadata becomes inaccessible.
Enumeration extension (optional)
The enumeration extension lets callers list every NFT in the collection and every NFT owned by a specific address.
interface TRC721Enumerable {
function totalSupply() external view returns (uint256);
function tokenByIndex(uint256 _index) external view returns (uint256);
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}| Function | Purpose |
|---|---|
totalSupply() | Returns the total number of NFTs currently tracked by the contract. |
tokenByIndex(uint256 _index) | Returns the tokenId at a global index. |
tokenOfOwnerByIndex(address _owner, uint256 _index) | Returns the tokenId at the per-owner index for _owner. |
Implementing enumeration costs extra storage and Energy on every mint, transfer, and burn because the contract must maintain two index arrays. Skip it unless you know you need on-chain enumeration — most applications can reconstruct ownership from Transfer events off-chain.
Related resources
- TRC-721 — standard overview
- TRC-721 contract example — full reference implementation
- Issuing a TRC-721 token — deployment walkthrough
- TRC-721 contract interaction — read and write from a deployed TRC-721
Updated 23 days ago