TRC-721 协议接口

TRC-721 标准及其可选扩展中每个函数和事件的完整参考。

📘

前置阅读

本文是 TRC-721 的函数与事件参考。TRC-721 是 TRON 上的非同质化 Token(NFT)标准。TRC-20 不适合 NFT 场景;每个 TRC-721 Token 都独一无二,拥有独立的 tokenId、所有者与可选元数据。

TRC-721 对应以太坊 ERC-721,在接口层兼容。

必须实现的接口

每个 TRC-721 合约必须实现 TRC-721TRC-165 接口。

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 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);
}

函数参考

函数用途
balanceOf(address _owner)返回 _owner 持有的 NFT 数量。
ownerOf(uint256 _tokenId)返回 _tokenId 的当前所有者。
safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data)_tokenId_from 转移到 _to,若 _to 是合约则调用其 onTRC721Received
safeTransferFrom(address _from, address _to, uint256 _tokenId)同上,但 data 为空。
transferFrom(address _from, address _to, uint256 _tokenId)不带接收者钩子检查地转账 _tokenId。调用方负责验证 _to 能处理该 NFT;否则 Token 可能永久丢失。
approve(address _approved, uint256 _tokenId)授予 _approved 转账 _tokenId 的权限。
setApprovalForAll(address _operator, bool _approved)授予或撤销 _operator 转账调用方当前持有及将来持有的所有 NFT 的权限。
getApproved(uint256 _tokenId)返回当前被授权操作 _tokenId 的地址,若无则返回零地址。
isApprovedForAll(address _owner, address _operator)_operator 已被授权管理 _owner 的所有 NFT,则返回 true
supportsInterface(bytes4 interfaceID)来自 TRC-165。若合约实现了 interfaceID 标识的接口,则返回 true

事件参考

事件触发时机
Transfer(_from, _to, _tokenId)成功的 transferFromsafeTransferFrom 转移 Token 时触发。铸造(_from = 0x0)和燃烧(_to = 0x0)时也会触发。
Approval(_owner, _approved, _tokenId)approve 成功,为某个 Token 设置新的被授权地址。
ApprovalForAll(_owner, _operator, _approved)setApprovalForAll 成功,切换操作员授权状态。

TRC721TokenReceiver——接受安全转账的合约必须实现

通过 safeTransferFrom 接受 NFT 的钱包、中介或拍卖合约必须实现接收者钩子:

interface TRC721TokenReceiver {
    function onTRC721Received(
        address _operator,
        address _from,
        uint256 _tokenId,
        bytes _data
    ) external returns (bytes4);
}

onTRC721Received(address _operator, address _from, uint256 _tokenId, bytes _data)

safeTransferFrom 配合使用。当 _to 是合约时,safeTransferFrom 会调用该合约的 onTRC721Received 并检查返回值。合约必须返回哈希值 bytes4(keccak256("onTRC721Received(address,address,uint256,bytes)"))。任何其他返回值都会导致转账 revert。

📘

注意

TRC-721 的哈希值与以太坊 ERC-721 不同:bytes4(keccak256("onTRC721Received(address,address,uint256,bytes)")) 与 bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")) 不同。对于 onTRC721Received 的返回值,请使用 0x5175f878(TRON)而非 0x150b7a02(以太坊)。这是从以太坊移植合约时最常见的 bug。

元数据扩展(可选)

元数据扩展允许合约暴露人类可读的名称、符号以及每个 Token 的 URI。钱包和交易市场依赖此扩展来渲染 Token。

interface TRC721Metadata {
    function name() external view returns (string _name);
    function symbol() external view returns (string _symbol);
    function tokenURI(uint256 _tokenId) external view returns (string);
}
函数用途
name()返回人类可读的系列名称。
symbol()返回系列的简称。
tokenURI(uint256 _tokenId)返回指向描述该 Token 的 JSON 元数据文件的 URI。

元数据 JSON 文件应包含 namedescriptionimage 字段。建议托管在 IPFS、BTFS 或自有 CDN 上;如果 URI 下线,该 NFT 的元数据将无法访问。

枚举扩展(可选)

枚举扩展允许调用方列出系列中的所有 NFT 以及特定地址持有的所有 NFT。

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);
}
函数用途
totalSupply()返回合约当前追踪的 NFT 总数量。
tokenByIndex(uint256 _index)返回全局索引处的 tokenId。
tokenOfOwnerByIndex(address _owner, uint256 _index)返回 _owner 的按所有者索引处的 tokenId。

实现枚举扩展会在每次铸造、转账和燃烧时消耗额外的存储和能量,因为合约必须维护两个索引数组。除非确实需要链上枚举,否则可以跳过它;大多数应用可以通过链下的 Transfer 事件重建所有权信息。


相关资源