Erc-721

OpenZeppelin ERC721 URIStorage 實現缺少可列舉函式

  • December 22, 2021

我正在嘗試使用預設的 OpenZeppelin 4.x ERC721URIStorage 實現來建構 ERC721 合約。在此 URL ( https://docs.openzeppelin.com/contracts/4.x/erc721 ) 的文件中,您可以找到以下文本:

ERC721URIStorage 合約是 ERC721 的實現,包括所有標準擴展(IERC721Metadata 和 IERC721Enumerable)。

現在,如果您在此處查看 IERC721Enumerable 介面文件(https://docs.openzeppelin.com/contracts/4.x/api/token/erc721#IERC721Enumerable),您可以看到有一個tokenOfOwnerByIndex函式,但不幸的是它不可用在 OpenZeppelin ERC712URIStorage 實現中,因為它應該根據文件。

我錯過了什麼還是 OpenZeppelin 文件有誤?

這是程式碼:

// contracts/GameItem.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract GameItem is ERC721URIStorage {
   using Counters for Counters.Counter;
   Counters.Counter private _tokenIds;

   constructor() ERC721("GameItem", "ITM") {}

   function awardItem(address player, string memory tokenURI)
       public
       returns (uint256)
   {
       _tokenIds.increment();

       uint256 newItemId = _tokenIds.current();
       _mint(player, newItemId);
       _setTokenURI(newItemId, tokenURI);

       return newItemId;
   }
}

ERC721URIStorage 合約是 ERC721 的實現,包括所有標準擴展(IERC721Metadata 和 IERC721Enumerable)。

不, ERC721 oz 實現只包括IERC721Metadata擴展而不包括IERC721Enumerable

tokenOfOwner可作為ERC721Enumerable擴展的一部分

而且你只是繼承自ERC721URIStorage,實習生只繼承自ERC721實現,它只包括Metadata extension

請參閱下面的 ERC721 實現描述,ERC721URIStorage您的範例合約使用該實現:

ERC721 不可替代令牌標準的實施,包括元數據擴展,但不包括可作為 ERC721Enumerable 單獨提供的 Enumerable 擴展。


您的範例的完整實現如下:

// contracts/GameItem.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract GameItem is ERC721URIStorage, ERC721Enumerable, Ownable {
   using Counters for Counters.Counter;
   Counters.Counter private _tokenIds;

   constructor() ERC721("GameItem", "ITM") {}

   function awardItem(address player, string memory tokenURI)
       public
       returns (uint256)
   {
       _tokenIds.increment();

       uint256 newItemId = _tokenIds.current();
       _mint(player, newItemId);
       _setTokenURI(newItemId, tokenURI);

       return newItemId;
   }
   
   function _beforeTokenTransfer(address from, address to, uint256 tokenId)
       internal
       override(ERC721, ERC721Enumerable)
   {
       super._beforeTokenTransfer(from, to, tokenId);
   }

   function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
       super._burn(tokenId);
   }

   function tokenURI(uint256 tokenId)
       public
       view
       override(ERC721, ERC721URIStorage)
       returns (string memory)
   {
       return super.tokenURI(tokenId);
   }

   function supportsInterface(bytes4 interfaceId)
       public
       view
       override(ERC721, ERC721Enumerable)
       returns (bool)
   {
       return super.supportsInterface(interfaceId);
   }

   function safeMint(address to, uint256 tokenId) public onlyOwner {
       _safeMint(to, tokenId);
   }

}

IDK 我對我的答案的感覺如何,但我所做的是我進入我的 node_modules 文件夾,並將 ERC721Enumerable 中的所有程式碼複製到 ERC721URIStorage 中,這就是我能夠組合兩個模組的方式。不確定這是否是正確的解決方法,但到目前為止它已在我的程式碼中執行

引用自:https://ethereum.stackexchange.com/questions/103674