Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-7572: 通过 `contractURI()` 实现合约级别元数据

指定和更新合约级别元数据

Authors Devin Finzer (@dfinzer), Alex Atallah (@alexanderatallah), Ryan Ghods (@ryanio)
Created 2023-12-06
Discussion Link https://ethereum-magicians.org/t/erc-contract-level-metadata-via-contracturi/17157

摘要

本规范标准化 contractURI() 以返回合约级别的元数据。这对于 dapps 和链下索引器来说非常有用,它们可以显示有关合约的丰富信息,例如其名称、描述和图像,而无需手动或单独为每个 dapp 指定。

动机

多年来,Dapps 已经包含了对 contractURI() 的支持,但没有 ERC 可以参考。此标准还引入了事件 ContractURIUpdated(),以指示何时更新元数据。

规范

本文档中的关键词“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“NOT RECOMMENDED”、“MAY”和“OPTIONAL”应按照 RFC 2119 和 RFC 8174 中的描述进行解释。

合约必须实现以下接口:

interface IERC7572 {
  function contractURI() external view returns (string memory);

  event ContractURIUpdated();
}

contractURI() 返回的字符串可以是链下资源或链上 JSON 数据字符串(data:application/json;utf8,{})。

ContractURIUpdated() 事件应该在合约元数据的更新时发出,以便链下索引器查询合约。

如果底层合约提供了任何与 contractURI 模式冲突的方法,例如 name()symbol(),建议 contractURI() 返回的元数据优先。这使合约创建者能够通过通知更新的事件来更新其合约详细信息。

contractURI 的模式

contractURI() 返回的 JSON 模式必须符合:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "合约的名称。"
    },
    "symbol": {
      "type": "string",
      "description": "合约的符号。"
    },
    "description": {
      "type": "string",
      "description": "合约的描述。"
    },
    "image": {
      "type": "string",
      "format": "uri",
      "description": "指向具有 mime type image/* 的资源的 URI,该资源表示合约,通常显示为合约的头像。"
    },
    "banner_image": {
      "type": "string",
      "format": "uri",
      "description": "指向具有 mime type image/* 的资源的 URI,该资源表示合约,显示为合约的横幅图像。"
    },
    "featured_image": {
      "type": "string",
      "format": "uri",
      "description": "指向具有 mime type image/* 的资源的 URI,该资源表示合约的特色图像,通常用于高亮部分。"
    },
    "external_link": {
      "type": "string",
      "format": "uri",
      "description": "合约的外部链接。"
    },
    "collaborators": {
      "type": "array",
      "items": {
        "type": "string",
        "description": "表示合约的授权编辑者的以太坊地址。"
      },
      "description": "表示合约的协作者(授权编辑者)的以太坊地址数组。"
    }
  },
  "required": ["name"]
}

例子:

{
  "name": "Example Contract",
  "symbol": "EC",
  "description": "Your description here",
  "image": "ipfs://QmTNgv3jx2HHfBjQX9RnKtxj2xv2xQCtbDXoRi5rJ3a46e",
  "banner_image": "ipfs://QmdChMVnMSq4U7oVKhud7wUSEZGnwuMuTY5rUQx57Ayp6H",
  "featured_image": "ipfs://QmS9m6e1E1NfioMM8dy1WMZNN2FRh2WDjeqJFWextqXCT8",
  "external_link": "https://project-website.com",
  "collaborators": ["0x388C818CA8B9251b393131C08a736A67ccB19297"]
}

未来的 ERC 可以继承这个 ERC,以便为模式添加更多属性以进行标准化。

理由

方法名 contractURI() 的选择是基于其在 dapps 中的现有实现。指定 ContractURIUpdated() 事件是为了帮助链下索引器知道何时重新获取元数据。

向后兼容性

作为一个新的 ERC,不存在向后兼容性问题。

参考实现

contract MyCollectible is ERC721, IERCXXXX {
    string _contractURI = "ipfs://QmTNgv3jx2HHfBjQX9RnKtxj2xv2xQDtbVXoRi5rJ3a46e"
    // or e.g. "https://external-link-url.com/my-contract-metadata.json";

    function contractURI() external view returns (string memory) {
        return _contractURI;
        // or e.g. for onchain:
        // 或者例如,对于链上:
        string memory json = '{"name": "Creatures","description":"..."}';
        return string.concat("data:application/json;utf8,", json);
    }

    /// @dev Suggested setter, not explicitly specified as part of this ERC
    //  @dev 建议的setter,未明确指定为此ERC的一部分
    function setContractURI(string memory newURI) external onlyOwner {
        _contractURI = newURI;
        emit ContractURIUpdated();
    }
}

安全考虑

应预期指定为 collaborators 的地址将收到管理员级别的功能,以便在实施此标准的 dapps 上更新合约信息。

版权

版权和相关权利通过 CC0 放弃。

Citation

Please cite this document as:

Devin Finzer (@dfinzer), Alex Atallah (@alexanderatallah), Ryan Ghods (@ryanio), "ERC-7572: 通过 `contractURI()` 实现合约级别元数据 [DRAFT]," Ethereum Improvement Proposals, no. 7572, December 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7572.