[ERC7572] コントラクトに関するメタデータを一元管理する仕組みを理解しよう！

# はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回は、コントラクトのメタデータを一元的に管理し、更新するための新しい仕組みを提案している**ERC7572**についてまとめていきます！

:::note info
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-7572

他にも様々なEIPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

# 概要

この仕様は、`contractURI()`を標準化し、コントラクトレベルのメタデータを返すようにします。
これは、DApps（分散アプリケーション）やオフチェーンのインデクサーが、手動でまたは各DAppごとに個別に指定することなく、コントラクトについての豊富な情報（その名前、説明、画像など）を表示するのに役立ちます。

ブロックチェーン上のスマートコントラクト（プログラム）に関する情報を一箇所で管理し、その情報を自動的にDAppsやサービスが取得できるようにするための標準です。
`contractURI()`関数は、そのスマートコントラクトのメタデータ（データのデータ）を提供します。
このメタデータには、コントラクトの名前、説明文、コントラクトを象徴する画像のURLなどが含まれていることが多いです。

このようにすることで、開発者やサービス提供者は、各DAppで1つ1つコントラクトの情報を手動で入力する必要がなく、統一された方法で情報を取得できるようになります。
これは、ブロックチェーン上での情報の一元管理と自動化を促進し、よりリッチなユーザー体験を実現するための仕組みと言えます。

# 動機

`contractURI()`関数に関する基準（標準）を定めることの重要性についての説明です。
`contractURI()`関数は、分散アプリケーション（DApps）がスマートコントラクトに関するメタデータ（例えば、コントラクトの名前、説明、画像など）を取得するために使用するものです。
しかしこの関数は、長い間正式なERC（Ethereum Request for Comments：イーサリアムの改善提案）によって参照される標準として確立されていませんでした。
ERCはイーサリアムブロックチェーンにおける標準規格を提案するためのドキュメントです。

この新しい標準は、DAppsがより統一された方法でコントラクトのメタデータにアクセスできるようにすることを目的としています。

加えて、この標準には`ContractURIUpdated()`イベントの導入も含まれています。
このイベントは、コントラクトのメタデータが更新されたときに外部のアプリケーションやサービスに通知するために使われます。
つまり、スマートコントラクトのメタデータが変更された場合、このイベントが発火（トリガーされる）し、DAppsやオフチェーンのインデクサーはその情報を更新するシグナルとして利用できます。

このような標準の導入は、ブロックチェーン上での情報の一貫性と透明性を高め、開発者がより信頼性の高い分散アプリケーションを構築するのを支援します。

# 仕様

`IERC7572`というインターフェースを実装することを義務付ける新しいERC（イーサリアムの改善提案）の標準についてです。
これは、スマートコントラクトに関するメタデータを管理する方法を標準化するためのものです。

### `contractURI()`関数

- **目的**
    - この関数は、スマートコントラクトのメタデータに関する情報を提供します。
    - このメタデータは、コントラクトの名前、説明、画像などを含むことができます。
- **返り値**
    - この関数から返される文字列は、オフチェーンリソースのURLまたはオンチェーンのJSONデータ文字列（`data:application/json;utf8,{}`形式）のいずれかです。
- **用途**
    - DAppsやオフチェーンのインデクサーが、スマートコントラクトについての豊富な情報を取得するために使用します。

### `ContractURIUpdated()`イベント

- **目的**
    - このイベントは、コントラクトのメタデータが更新されたときに発火します。
    - これにより、DAppsやオフチェーンのインデクサーは、メタデータの変更を検知して対応することができます。
- **用途**
    - オフチェーンのインデクサーが、コントラクトのメタデータの更新をクエリするために使用します。

### 追加の推奨事項

- **`name()`メソッド**
    - 基盤となるコントラクトが`name()`メソッドを提供する場合、`contractURI()`から返されるメタデータの`name`プロパティが優先されることが推奨されます。
    - これにより、コントラクト作成者は、更新の通知を伴うイベントを通じて、コントラクトの名前を更新できるようになります。

この標準は、スマートコントラクトのメタデータを管理し、アクセスする一貫した方法を提供することを目的としています。
これにより、DAppsやオフチェーンのサービスが、コントラクトに関する情報を効率的に取得し、更新することが可能になります。

## contractURIスキーマ

`contractURI()`から返されるJSONのスキーマは、以下に準拠する必要があります。

```json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "The name of the contract."
    },
    "description": {
      "type": "string",
      "description": "The description of the contract."
    },
    "image": {
      "type": "string",
      "format": "uri",
      "description": "A URI pointing to a resource with mime type image/* that represents the contract, typically displayed as a profile picture for the contract."
    },
    "banner_image": {
      "type": "string",
      "format": "uri",
      "description": "A URI pointing to a resource with mime type image/* that represents the contract, displayed as a banner image for the contract."
    },
    "featured_image": {
      "type": "string",
      "format": "uri",
      "description": "A URI pointing to a resource with mime type image/* that represents the featured image for the contract, typically used for a highlight section."
    },
    "external_link": {
      "type": "string",
      "format": "uri",
      "description": "The external link of the contract."
    },
    "collaborators": {
      "type": "array",
      "items": {
        "type": "string",
        "description": "An Ethereum address representing an authorized editor of the contract."
      },
      "description": "An array of Ethereum addresses representing collaborators (authorized editors) of the contract."
    }
  },
  "required": ["name"]
}
```

上記のJSONスキーマは、スマートコントラクトのメタデータを記述するためのフォーマットを定義しています。
このスキーマは、特定の情報を標準化された方法で提供するためのルールセットと見なすことができます。

- **`name`**
    - コントラクトの名前を表す文字列。
    - このフィールドは必須です。
- **`description`**
    - コントラクトの説明を表す文字列。
    - これにより、コントラクトが何をするのかについての詳細情報を提供できます。
- **`image`**
    - コントラクトを代表する画像へのURI。
    - この画像はコントラクトのプロファイル画像として一般に表示されます。
- **`banner_image`**
    - コントラクトを代表するバナー画像へのURI。
    - この画像は、コントラクトのバナー画像として表示されます。
- **`featured_image`**
    - コントラクトの特集画像へのURI。
    - この画像は、ハイライトセクション用に使用されることが一般的です。
- **`external_link`**
    - コントラクトの外部リンクへのURI。
    - これは、コントラクトに関連する外部ウェブサイトへのリンクを提供するために使用されます。
- **`collaborators`**
    - コントラクトの共同編集者（承認された編集者）を表すイーサリアムアドレスの配列。
    - これにより、コントラクトに対して編集権限を持つ人々が指定できます。

このスキーマは、スマートコントラクトに関連するメタデータを管理し、それをDAppsやオフチェーンのインデクサーが簡単に解釈できるようにすることを目的としています。
各プロパティは、コントラクトについての特定の情報をキャプチャし、これらの情報はDAppsによってコントラクトのリッチな表現を生成するために使用される可能性があります。

### 例

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

将来のERCは、標準化のためにスキーマに多くのプロパティを追加するためにこのスキーマを継承してもよいです。

# 補足

`contractURI()`メソッドと`ContractURIUpdated()`イベントがなぜスマートコントラクトの標準仕様に含まれているのかについての説明です。

### `contractURI()`メソッド

#### 選択の理由
`contractURI()`というメソッド名は、分散アプリケーション（DApps）内での既存の実装に基づいて選ばれました。
これは、このメソッドが既に一部のDAppsで使用されており、コントラクトのメタデータにアクセスするための非公式な標準として機能していたことを意味します。
そのため、この名称を正式な標準として採用することで、既存の実践との互換性を保ちつつ、一貫性と認識を促進しています。
#### 目的
このメソッドは、コントラクトに関するメタデータ（名前、説明、画像など）を含むJSON形式のデータを提供します。
DAppsやオフチェーンのインデクサーは、このメタデータを使用して、ユーザーに対してコントラクトに関する豊富な情報を表示できます。

### `ContractURIUpdated()`イベント

#### 目的
`ContractURIUpdated()`イベントは、コントラクトのメタデータが更新された時に発行されるイベントです。
このイベントが発行されると、オフチェーンのインデクサーやDAppsは、メタデータが変更されたことを知り、最新の情報を再取得することができます。

#### 利点
このイベントにより、メタデータの変更をリアルタイムで追跡し、情報を常に最新の状態に保つことが容易になります。
特に、メタデータが外部リソース（ウェブサイトや画像など）に依存している場合には、変更が頻繁に行われる可能性があるため、このイベントは特に有用です。

これらの仕様は、スマートコントラクトのメタデータを管理し、アクセスするプロセスを標準化することで、DAppsの開発者とユーザーの両方にメリットを提供します。
開発者は、一貫した方法でメタデータを公開でき、ユーザーはより豊かで最新のコントラクト情報にアクセスできるようになります。

# 互換性

新しいERCなので後方互換性の問題はありません。

# 実装

```ts
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
    function setContractURI(string memory newURI) external onlyOwner {
        _contractURI = newURI;
        emit ContractURIUpdated();
    }
}
```

# セキュリティ

スマートコントラクトのメタデータ標準（おそらく**IERC7572**などの提案された標準）に従って実装されたDApps（分散アプリケーション）において、「**コラボレーター**」として指定されたアドレスが、コントラクト情報の更新に関して管理者レベルの機能を受け取るべきであることを期待する必要があることを説明しています。
ここでいう「**コラボレーター**」とは、スマートコントラクトのメタデータに変更を加える権限を持つイーサリアムアドレスのことを指します。

:::note infoを開発する時、コントラクトのメタデータ（例えば、コントラクトの名前、説明、画像など）を更新するための「**管理者レベルのアクセス権**」を、特定のイーサリアムアドレスに付与することができます。
これらのアドレスは、コントラクトのデプロイヤー（作成者）によってコラボレーターとして指定されることがあり、指定されたアドレスはコントラクトの重要な情報を更新する能力を持ちます。
:::

この仕組みの主な目的は、スマートコントラクトのメタデータを適切に管理し、保守するために必要な柔軟性と制御を提供することです。
例えば、コントラクトの説明を更新する、新しい画像を設定する、またはその他の重要な情報を変更するなどのタスクを、コラボレーターが実行できます。
これにより、スマートコントラクトの情報が常に最新の状態に保たれ、DAppsのユーザーがより正確な情報に基づいて行動できるようになります。

# 引用

Devin Finzer (@dfinzer), Alex Atallah (@alexanderatallah), Ryan Ghods (@ryanio), "ERC-7572: Contract-level metadata via `contractURI()` [DRAFT]," Ethereum Improvement Proposals, no. 7572, December 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7572.

# 最後に

今回は「コントラクトのメタデータを一元的に管理し、更新するための新しい仕組みを提案している**ERC7572**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4