# ERC721 的列舉擴充(enumeration extension)

除了元資料擴充功能以外,為了能方便查詢發行量、能依序列出所有未被銷毀的 NFT、以及能列舉特定帳戶持有的 NFT,因此設計出這個介面。

# 列舉擴充介面

interface ERC721Enumerable /* is ERC721 */ {
    /// 回傳目前發行的 ERC721 總量
    function totalSupply() external view returns (uint256);

    /// 回傳第 `_index` 個未被銷毀的 NFT tokenId
    function tokenByIndex(uint256 _index) external view returns (uint256);

    /// 回傳第 `_index` 個由 `_owner` 帳戶持有的 NFT tokenId
    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}

# 代價

當然,凡事都有代價,尤其是要方便查詢的話,自然需要在區塊鏈上多儲存資訊。以 OpenZeppelin 的 ERC721 Enumerable 合約為例 (opens new window),我們可以發現它新增了以下幾個狀態變數:

    // 映射擁有者到他所持有的 NFT 列表
    // 擁有者位址 => Index => TokenId
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // 映射 token ID 到擁有者的 NFT 列表中的 Index 
    // TokenId => Index of `_ownedTokens`
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // 用來儲存所有 token ID,因此可以快速查詢總發行量,也能方便列舉
    uint256[] private _allTokens;

    // 映射 token ID 到所有 token ID 陣列的 Index
    // token ID => Index of `_allTokens`
    mapping(uint256 => uint256) private _allTokensIndex;

由於提供此功能所付出的代價不低,因此也有其他的 ERC721 的變種,就讓我們後面再來聊聊吧。

Last Updated: 2023/1/12 上午6:20:49