Solidity

如何為鏈上 NFT 正確實施 ContractURI

  • October 3, 2021

我正在嘗試在 OpenSea 上為 NFT 集合實現契約級元數據,但是,如果我使用以下程式碼執行此操作,則契約的元數據不會在 OpenSea 集合頁面上更新,也不會更新契約的描述在代幣的頁面上。

TokenURI 也儲存在鏈上,並在給出適當數據時進行更新。就我而言,它將是一個 SVG 圖像以及一些資訊字元串。(更多以下片段)

該程式碼缺少所有不相關的內容。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

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

import "./base64.sol";

contract Test is ERC721Enumerable, ERC721URIStorage, Ownable {
   using Counters for Counters.Counter;
   using Strings for uint256;

   string private _contractURI;

   constructor() ERC721("Test", "T") {}

   function svgToImageURI(string memory _source) public pure returns (string memory) {
       string memory baseURL = "data:image/svg+xml;base64,";
       string memory svgBase64Encoded = Base64.encode(bytes(string(abi.encodePacked(_source))));
       return string(abi.encodePacked(baseURL, svgBase64Encoded));
   }

   function formatTokenURI(string memory _imageURI, string memory _name, string memory _description, string memory _properties) public pure returns (string memory) {
       return string(
           abi.encodePacked(
               "data:application/json;base64,",
               Base64.encode(
                   bytes(
                       abi.encodePacked(
                           '{"name":"', _name,
                           '", "description": "', _description, '"',
                           ', "attributes": ', _properties,
                           ', "image":"', _imageURI, '"}'
                       )
                   )
               )
           )
       );
   }

   function setTokenURI(uint256 _tokenId, string memory _tokenURI) public onlyOwner() {
       _setTokenURI(_tokenId, _tokenURI);
       emit tokenChanged(_tokenId);
   }

   function setContractURI(string memory contractURI_) public onlyOwner() {
       _contractURI = string(abi.encodePacked(
           "data:application/json;base64,",
           Base64.encode(
               bytes(
                   abi.encodePacked(
                       contractURI_
                   )
               )
           )
       ));
   }

   function contractURI() public view returns (string memory) {
       return _contractURI;
   }
}

我給 setContractURI 函式的輸入是來自 OpenSea 網站的簡單 JSON 片段,因此我確信我遵守它的規則。

{
 "name": "OpenSea Creatures",
 "description": "OpenSea Creatures are adorable aquatic beings primarily for demonstrating what can be done using the OpenSea platform. Adopt one today to try out all the OpenSea buying, selling, and bidding feature set.",
 "image": "https://openseacreatures.io/image.png",
 "external_link": "https://openseacreatures.io",
 "seller_fee_basis_points": 100, 
 "fee_recipient": "0xA97F337c39cccE66adfeCB2BF99C1DdC54C2D721"
}

我究竟做錯了什麼?我在 Polygon Mumbai 測試網上。

看來我的setContractURI功能encodepacket太多了。看起來它現在正在 OpenSea 上執行。

   function setContractURI(string memory contractURI_) public onlyOwner() {
       _contractURI = string(abi.encodePacked(
               "data:application/json;base64,",
               Base64.encode(
                   bytes(
                       contractURI_
                   )
               )
           ));
   }

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