# [ERC7506] オンチェーンで信頼情報を扱う仕組みを理解しよう！

> ERC Trusted Hint Registry は、「ヒント」と呼ばれるオンチェーンメタデータを標準的な形で管理するための仕組みを提案しています。

- URL: https://cardene.dev/articles/d491a2f54302c32eddc6
- 公開日: 2025-12-03
- 更新日: 2025-12-03
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、クレームの取り消し情報や信頼できる発行者情報などをチェーン上で管理し、信頼性を強化する仕組みを提案している**ERC7506**についてまとめていきます！

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

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

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

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

## 概要

**ERC Trusted Hint Registry** は、「**ヒント**」と呼ばれるオンチェーンメタデータを標準的な形で管理するための仕組みを提案しています。
ここでいうオンチェーンメタデータとは、「**チェーン上に記録された、他の情報（クレーム）を補足・説明するための付随情報**」のことです。

ERC Trusted Hint Registryでは、このヒントを「**ネームスペース**」と「**リスト**」という単位で整理して管理します。
ネームスペースは、あるまとまり（例えば1つのエコシステムや組織）ごとの領域のようなもので、その中に複数のヒントリストを持てるイメージです。
こうした構造にすることで、ヒントを体系立てて整理し、必要なものを取り出しやすくしています。

さらに、ヒントの書き込みには権限管理の仕組みがあります。
ネームスペースの所有者だけがヒントを書き込めるように制御できるだけでなく、その管理作業を他の信頼できるアドレスに委任することもできます。
これにより、運用を柔軟にしつつ、誰でも勝手に書き換えられないようにできます。

トランザクションの送信方法については、「**メタトランザクション**」を安全に扱う仕組みも組み込まれています。
メタトランザクションとは、「**実際にガスを払う送信者**」と「**内容に署名した当人**」が分かれているトランザクションの仕組みのことです。
ERC Trusted Hint Registryでは**EIP712**形式の署名を使って、署名内容が改ざんされていないことや、誰がその操作に同意したのかを検証できるようにしています。
**EIP712**は「**構造化されたデータに対して署名するための標準**」で、ユーザーにとって分かりやすく、安全に署名できるようにする仕様です。

:::message
**EIP712**については以下の記事を参考にしてください。
:::

[\[EIP712\] 型付き構造化データのハッシュ化と署名の仕組みを理解しよう！](/articles/f54bc85cb66de5a54257)

またオプションとして、ENS（Ethereum Name Service）との連携も考慮されています。
ENSはアドレスに人間が読める名前（例: `example.eth`）を紐づける名前解決サービスです。
ヒント管理にENSを組み合わせることで、「**このネームスペースやヒントは誰のものか**」を人間にも分かりやすい形で確認しやすくなり、信頼性の確認や発見性の向上に役立ちます。

インターフェースは、ヒントが変更されたときなどに特定のイベントを発行するようになっています。
これにより、「**いつ**」、「**誰が**」、「**どのヒントを**」変更したのかをオンチェーンのログから追跡しやすくなります。

:::message
ERC Trusted Hint Registryは、クレームやエコシステムに関するメタデータを扱うための、信頼性の高い標準的な枠組みを提供することを狙っています。
これによって、分散型環境におけるデータの解釈や検証の整合性を保ち、信頼性を維持する基盤となることを目指しています。
:::

## 動機

ERC Trusted Hint Registryの背景には、「**分散型の世界でどう信頼を築くか**」という課題があります。
ブロックチェーンや分散型技術は、「**相手を信頼しなくても成り立つ（トラストレス）**」仕組みを提供しますが、その上で動くエコシステム（ビジネス、コミュニティ、社会的なプロジェクトなど）は、逆に「**誰をどこまで信頼するか**」を決める必要があります。

こうしたエコシステムでは、参加者に対して「**クレーム**」が頻繁に発行されます。
ここでのクレームとは、「**ある主体が、別の主体について主張する情報**」のことで、例えば「**このアドレスはKYC済みである**」、「**この法人はこの団体のメンバーである**」といった主張が該当します。これらのクレームが、エコシステム内で信頼を形成する土台になり、取引や連携をスムーズにします。

一方で、これまでの実例から、「**単に検証可能なクレーム（Verifiable Credential など）が存在するだけでは、十分な信頼を作れない**」ことが分かってきました。
どのクレームをどのように解釈すべきか、いつ無効になったのか、誰を信頼できる発行者と見なすべきか、といった周辺情報が欠けていると、クレームを安全に利用できません。
そこで必要になるのが、クレームを補助するオンチェーンメタデータのレイヤーです。

この仕様では、そうした補助的なメタデータを「**ヒント**」と呼んでいます。
ヒントは、エコシステムがクレームを信頼できる形でやり取りし、検証するための手がかりとして使われます。ヒントの具体的な役割の例は、次のように整理できます。

| ヒントの役割 | 説明 |
| ------------- | ------------------------------------------- |
| 失効・取り消し情報     | 「**このクレームはいつ、どの理由で無効になったか**」といった情報を示します。        |
| 信頼できる発行者の識別   | 「**どの発行者（アドレスや組織）を信頼してよいか**」といった情報を示します。        |
| タイムスタンプ付きハッシュ | クレームの内容のハッシュとその時刻を記録し、後から改ざんされていないかを確認できます。 |

これらはあくまで一例であり、ヒントはエコシステムの要件に応じてさまざまな用途に使えますが、共通しているのは「**クレームの信頼性やデータの完全性を時間を通じて検証できるようにする**」という点です。

ERC Trusted Hint Registryは、こうしたヒントを管理するための、堅牢で柔軟かつ標準化されたインターフェースを提供することを目的としています。
任意のアドレスが、自分に紐づく複数のヒントリストを管理できるようになっており、ヒントの作成・更新をしやすくする機能に加えて、その操作権限を別の信頼できるアドレスに委譲できるようになっています。
これにより、エコシステムごとに求められる運用形態やユースケースに合わせて、ヒントリストを動的に活用できるようになります。

また、インターフェース設計にあたっては、相互運用性が強く意識されています。
具体的には、W3Cが策定する **Decentralized Identifiers**（分散型識別子）や **Verifiable Credentials**（検証可能な証明）といった仕様との整合性を考慮しています。
これらはID管理や証明情報の標準仕様であり、オンチェーン・オフチェーン双方で広く利用されることを想定したものです。
さらに、Ethereum Attestation Service（イーサリアム上でアテステーション、つまり「**ある主張に対する署名付き証明**」を扱うプロジェクト）との整合も視野に入れられており、既存のエコシステムとの連携をしやすくしています。

このように、ERC Trusted Hint Registryは、ヒント管理のスマートコントラクトインターフェースを標準化することで、分散型エコシステムにおける信頼の構築と拡張を支える役割を果たします。
オンチェーン・オフチェーンを問わずクレームを発行し、それを検証してどう解釈するかを共通の土台の上で扱えるようにするための基盤です。
そのためERC Trusted Hint Registryは、単に便利な追加機能というよりも、「**分散型の世界で信頼をどう構成するか**」という課題に対する、次のステップとなる仕組みとして位置づけられています。

## 仕様

### TrustedHintRegistryコントラクト

**ERC Trusted Hint Registry**は、オンチェーン上で「**ヒント（hint）**」と呼ばれるメタデータを扱うための標準インターフェースを定義したものです。
ヒントは、クレーム（claim）の信頼性や解釈、検証の補助として使われます。

**ERC7506**はm必須となる基本機能（ヒント取得・設定）、任意とされる管理系の機能（委任設定・メタデータ管理・署名付き操作など）を定義しています。

ガバナンスの仕組みは仕様に含まれていないため、各エコシステムが独自に実装できます。

### 定義

仕様で使用される用語を整理します。

| 用語         | 説明                                             |
| ---------- | ---------------------------------------------- |
| `claim` | 他の主体についてある主体が発行する主張のこと。  |
| `hint` | クレームを解釈したり信頼性を補強したりするための補助情報。  |
| `namespace`  | 登録されたアドレスが所有する領域で、その中にヒントリストが配置される。            |
| `hint list`  | `namespace` の中に存在するヒントの集合体で、複数のkey/valueを格納する。 |
| `hint key` | `hint value` を特定するための識別子。   |
| `hint value` | エコシステム内の主体に関する何らかの情報。  |
| `delegate`   | `hint list` への書き込み権限を委任されたアドレス。   |

### インターフェース

#### イベント

##### `HintValueChanged`

```javascript
event HintValueChanged(
  address indexed namespace,
  bytes32 indexed list,
  bytes32 indexed key,
  bytes32 value
);
```

ヒント値が変更された時に発行されるイベント。
このイベントは、指定された `namespace` 内の特定のヒントリストに含まれる `key` の値が変更された際に発行されます。
どの `namespace`・`list`・`key` に対して変更が発生したかを明確に記録することで、
オンチェーン上のヒント変更履歴を追跡しやすくなります。
ヒントは信頼性評価やデータの補強に利用されるため、変更ログが残ることはエコシステム全体の透明性を高めます。

**パラメータ**

* `namespace`
  * ヒントが属する `namespace` のアドレス。
* `list`
  * 値が変更されたヒントリストを表すキー。
* `key`
  * 値が変更されたヒントのキー。
* `value`
  * 新しく設定されたヒント値。

##### `HintListOwnerChanged`

```javascript
event HintListOwnerChanged(
  address indexed namespace,
  bytes32 indexed list,
  address indexed newOwner
);
```

ヒントリストの所有者が変更された時に発行されるイベント。
このイベントは、特定のヒントリストの所有者（管理者権限を持つアドレス）が別のアドレスへ変更された時に発行されます。
ただしリストが所属する `namespace`（アドレス自体）は変わらず、
あくまで「**そのリストを管理する権限の移転**」が行われます。
これにより、`namespace` の階層構造はそのまま保たれた状態で、
権限の移譲のみが行われたことを明確に追跡できます。

**パラメータ**

* `namespace`
  * 変更対象のヒントリストが属する `namespace` のアドレス。
* `list`
  * 所有者が変更されたヒントリスト。
* `newOwner`
  * ヒントリストの新しい所有者となるアドレス。

##### HintListDelegateAdded

```javascript
event HintListDelegateAdded(
  address indexed namespace,
  bytes32 indexed list,
  address indexed newDelegate
);
```

ヒントリストに `delegate` が追加された時に発行されるイベント。
`namespace` の所有者が、特定のヒントリストに対して `delegate`（書き込み権限を委任されたアドレス）を追加した時に発行されます。
`delegate` を追加することで、複数の主体が共同でヒントリストを管理しやすくなり、
権限の変化を追跡できるようにします。

**パラメータ**

* `namespace`
  * 対象の `namespace`。
* `list`
  * `delegate` が追加されたヒントリスト。
* `newDelegate`
  * 書き込み権限を付与されたアドレス。

##### `HintListDelegateRemoved`

```javascript
event HintListDelegateRemoved(
  address indexed namespace,
  bytes32 indexed list,
  address indexed oldDelegate
);
```

ヒントリストから `delegate` が削除された時に発行されるイベント。
ヒントリストに対する書き込み権限が委任されていた `delegate` が、権限を失った際に発行されます。
`delegate` の削除は権限管理上重要な操作のため、チェーン上に明確な履歴を残すことができます。

**パラメータ**

* `namespace`
  * 該当する `namespace` のアドレス。
* `list`
  * `delegate` が削除されたヒントリスト。
* `oldDelegate`
  * 削除された `delegate` のアドレス。

##### `HintListStatusChanged`

```javascript
event HintListStatusChanged(
  address indexed namespace,
  bytes32 indexed list,
  bool indexed revoked
);
```

ヒントリストの有効状態が変更された時に発行されるイベント。
ヒントリストが無効化された、あるいは再び有効化された際に発行されます。
`revoked` が `true` の場合は「リスト全体が無効化された」ことを意味し、
そのリストに含まれるすべてのヒント値が信頼できない状態とみなされます。
これにより、クレームの取り消しやデータの有効期限切れなどの情報を効率的に伝えられます。

**パラメータ**

* `namespace`
  * 対象 `namespace` のアドレス。
* `list`
  * 有効状態が変更されたヒントリスト。
* `revoked`
  * `true` の場合は無効化されたことを示す。

##### `getHint`

```javascript
function getHint(address _namespace, bytes32 _list, bytes32 _key) external view returns (bytes32);
```

指定された `namespace` とヒントリストから、特定キーに対応するヒント値を取得する関数。
この関数は読み取り専用で、`namespace` 内の `list` に含まれる `key` に対して保存されている `bytes32` の値を返します。
ヒント値はクレームの信頼性確認やデータ検証に利用されるため、この関数はシステム内で頻繁に呼び出される基礎的な機能です。
値を変更することはなく、ストレージへの書き込みも行いません。

**引数**

* `_namespace`
  * 参照対象となる `namespace` のアドレス。
* `_list`
  * 参照対象のヒントリストを識別する `bytes32` 値。
* `_key`
  * 取得対象のヒントキー。

**戻り値**

* `bytes32`
  * 指定された `key` に対応するヒント値。

##### `setHint`

```javascript
function setHint(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value) public;
```

特定のヒントキーに対応する値を更新する関数。
`namespace` の所有者または書き込み権限を持つ delegate が、
指定した key に対して新しい value を設定します。
ヒント値の変更はデータの解釈や信頼性の判断に影響するため、
権限管理が重要な関数です。
必要に応じてメタデータを追加できるオーバーロード版も用意されています。

**引数**

* `_namespace`
  * 更新対象となる `namespace` のアドレス。
* `_list`
  * ヒントリストを識別する `bytes32` のキー。
* `_key`
  * 値を更新する対象のヒントキー。
* `_value`
  * 新しく設定するヒント値。

##### `setHintSigned`

```javascript
function setHintSigned(
  address _namespace,
  bytes32 _list,
  bytes32 _key,
  bytes32 _value,
  address _signer,
  bytes calldata _signature
) public;
```

署名によってヒント値を更新する関数。
メタトランザクションの仕組みを利用し、署名者が**EIP712**準拠のデータに署名することで意図を示し、
別の `sender` がその署名データを使ってトランザクションを実行します。
署名内容には nonce が含まれ、再利用（リプレイ攻撃）を防ぎます。
この関数はユーザーが自分でガスを支払わなくても操作できるという利点があります。

**引数**

* `_namespace`
  * 更新対象の `namespace`。
* `_list`
  * 対象のヒントリスト。
* `_key`
  * 更新対象のヒントキー。
* `_value`
  * 新しいヒント値。
* `_signer`
  * **EIP712**署名を生成したアドレス。
* `_signature`
  * 署名データ（**EIP712**準拠）。

##### `setHints`

```javascript
function setHints(
  address _namespace,
  bytes32 _list,
  bytes32[] calldata _keys,
  bytes32[] calldata _values
) public;
```

複数のヒントキーに対してまとめて値を更新する関数。
複数のkey/valueを一度に変更できるため、大量のヒント更新が必要な場合に効率的です。
`_key` と `_values` の長さが一致している必要があります。
`namespace` の所有者または `delegate` のみが利用できます。

**引数**

* `_namespace`
  * 対象 `namespace` のアドレス。
* `_list`
  * 対象ヒントリスト。
* `_keys`
  * 更新対象となる複数のヒントキー。
* `_values`
  * 各キーに対応する新しいヒント値。

##### `setHintsSigned`

```javascript
function setHintsSigned(
  address _namespace,
  bytes32 _list,
  bytes32[] calldata _keys,
  bytes32[] calldata _values,
  address _signer,
  bytes calldata _signature
) public;
```

署名付きメタトランザクションで複数のヒント値をまとめて更新する関数。
`setHintSigned` の複数キー対応版です。
ユーザーは**EIP712**署名を生成するだけでよく、実際のトランザクションは `sender` が送信します。
これによりユーザー負担を減らしつつ、複数の更新を安全に実行できます。

**引数**

* `_namespace`
  * 対象 `namespace`。
* `_list`
  * 対象ヒントリスト。
* `_keys`
  * 更新対象キーの配列。
* `_values`
  * 新しく設定する値の配列。
* `_signer`
  * **EIP712**署名を生成したアドレス。
* `_signature`
  * meta transaction用の署名データ。

##### `setHintDelegated`

```javascript
function setHintDelegated(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value) public;
```

事前に承認された `delegate` がヒント値を更新するための関数。
`namespace` の所有者によって `delegate` として登録されたアドレスのみが実行できます。
`delegate` は、所有者の代わりに特定のヒントリストのkey/valueを変更できます。
権限の範囲は `namespace` 全体ではなく、特定の `list` ごとに管理されるため、精密な権限コントロールが可能です。

**引数**

* `_namespace`
  * 対象となる `namespace` のアドレス。
* `_list`
  * `delegate` が書き込み権限を持つヒントリスト。
* `_key`
  * 更新対象のヒントキー。
* `_value`
  * 新しいヒント値。

##### `setHintDelegatedSigned`

```javascript
function setHintDelegatedSigned(
  address _namespace,
  bytes32 _list,
  bytes32 _key,
  bytes32 _value,
  address _signer,
  bytes calldata _signature
) public;
```

署名付きメタトランザクションで `delegate` がヒント値を更新する関数。
`delegate` に書き込み権限はあるものの、ガス代を支払う必要はありません。
`delegate` は**EIP712**形式の署名を提供し、第三者の `sender` がその署名を使ってトランザクションを送信します。
そのため、ユーザー負担を最小限にしつつ、安全に更新処理を行えます。
署名には `nonce` が含まれ、リプレイ攻撃を防ぎます。

**引数**

* `_namespace`
  * ヒントリストが属する `namespace` のアドレス。
* `_list`
  * `delegate` の対象となるヒントリスト。
* `_key`
  * 更新対象のヒントキー。
* `_value`
  * 新しいヒント値。
* `_signer`
  * **EIP712** 署名を生成した `delegate` のアドレス。
* `_signature`
  * 署名データ。

##### `setHintsDelegated`

```javascript
function setHintsDelegated(
  address _namespace,
  bytes32 _list,
  bytes32[] calldata _keys,
  bytes32[] calldata _values
) public;
```

複数のヒント値を `delegate` がまとめて更新する関数。
`delegate` が複数のkey/valueを一度に変更するための関数です。
大量のデータ更新を同時に行う場合に効率的で、各キーと値のペアがまとめて更新されます。
権限は `list` 単位で付与されているため、`delegate` が更新可能な範囲を明確に制御できます。

**引数**

* `_namespace`
  * 対象 `namespace` のアドレス。
* `_list`
  * `delegate` が担当するヒントリスト。
* `_keys`
  * 更新対象の複数のヒントキー。
* `_values`
  * `_keys` に対応する複数の新しいヒント値。

##### `setHintsDelegatedSigned`

```javascript
function setHintsDelegatedSigned(
  address _namespace,
  bytes32 _list,
  bytes32[] calldata _keys,
  bytes32[] calldata _values,
  address _signer,
  bytes calldata _signature
) public;
```

署名付きメタトランザクションで、複数のヒント値を `delegate` がまとめて更新する関数。
複数のkey/valueの更新を、`delegate` が**EIP712**署名によって承認し、`sender` が実際のトランザクションを送信する形式です。
大量データを扱う場面でも効率性と安全性を両立できます。
`nonce` を用いることで署名が再利用されることを防ぎます。

**引数**

* `_namespace`
  * 対象 `namespace`。
* `_list`
  * 対象ヒントリスト。
* `_keys`
  * 更新対象のキー一覧。
* `_values`
  * 新しい値の一覧。
* `_signer`
  * 署名を生成した `delegate` のアドレス。
* `_signature`
  * 署名データ。

##### `setListStatus`

```javascript
function setListStatus(address _namespace, bytes32 _list, bool _revoked) public;
```

ヒントリストの有効／無効状態を変更する関数。
この関数は、特定のヒントリストが「**有効か**」、「**無効か**」を示す状態を更新します。
`_revoked` が `true` の場合、そのリストは無効化されたとみなされます。
仕様上、「**リストの無効化**」は、そのリスト内のすべてのヒント値を一括で無効であると扱うために利用できます。
これにより、個別の `key` を逐一更新しなくても、リスト単位で一括無効化の扱いが可能になります。

**引数**

* `_namespace`
  * 対象となる `namespace` のアドレス。
* `_list`
  * 状態を変更する対象のヒントリストを表す `bytes32` 値。
* `_revoked`
  * `true` の場合はリストを無効化し、`false` の場合は有効として扱う状態にします。

##### `setListStatusSigned`

```javascript
function setListStatusSigned(
  address _namespace,
  bytes32 _list,
  bool _revoked,
  address _signer,
  bytes calldata _signature
) public;
```

署名付きメタトランザクションでヒントリストの有効／無効状態を変更する関数。
この関数は `setListStatus` のメタトランザクション版です。
リストの状態変更を行う権限を持つ `_signer` が、**EIP712**形式のデータに署名し、
別の `sender` が `_signature` を含めたトランザクションを送ることで処理を実行します。
署名データには `nonce` が含まれ、同じ署名が再利用されることを防ぎます。

**引数**

* `_namespace`
  * 対象 `namespace` のアドレス。
* `_list`
  * 状態変更対象のヒントリスト。
* `_revoked`
  * リストを無効とするかどうかを示すフラグ。
* `_signer`
  * 状態変更を承認する署名者のアドレス。
* `_signature`
  * **EIP712**準拠で生成された署名データ。

##### `setListOwner`

```javascript
function setListOwner(address _namespace, bytes32 _list, address _newOwner) public;
```

ヒントリストの所有者を別のアドレスに移転する関数。
この関数は、指定されたヒントリストのオーナーを `_newOwner` に変更します。
重要なのは、リストが所属する `_namespace` 自体は変更されない点です。
つまり、リストの「**場所**」は同じ `namespace` に残りつつ、そのリストを管理するアドレスだけが切り替わります。
これにより、既存の参照パス（`namespace` → `list` → `key` → `value`）が壊れずに、
運用上の管理者だけを入れ替えることができます。

**引数**

* `_namespace`
  * 対象リストが属する `namespace` のアドレス。
* `_list`
  * 所有者を変更したいヒントリストの識別子。
* `_newOwner`
  * 新たにそのリストの所有者となるアドレス。

##### `setListOwnerSigned`

```javascript
function setListOwnerSigned(
  address _namespace,
  bytes32 _list,
  address _newOwner,
  address _signer,
  bytes calldata _signature
) public;
```

署名付きメタトランザクションにより、ヒントリストの所有者を移転する関数。
この関数は `setListOwner` のメタトランザクション版です。
現在のリスト所有者など、権限を持つ `_signer` が**EIP712**署名を生成し、別の `sender` が `_signature` をコントラクトに渡して所有者変更を実行します。
これにより、オーナー自身がガスを払わなくても管理変更を行える一方、署名と `nonce` によって安全性が確保されます。

**引数**

* `_namespace`
  * 対象 `namespace` のアドレス。
* `_list`
  * 所有者を変更するヒントリスト。
* `_newOwner`
  * 新しい所有者アドレス。
* `_signer`
  * 所有者変更を承認する署名者のアドレス。
* `_signature`
  * **EIP712**準拠の署名データ。

##### `addListDelegate`

```javascript
function addListDelegate(
  address _namespace,
  bytes32 _list,
  address _delegate,
  uint256 _untilTimestamp
) public;
```

ヒントリストに対して `delegate` を追加する関数。
この関数は、特定のヒントリストに対して書き込み権限を委任するアドレスを追加します。
`delegate` は `_untilTimestamp` までの期間、そのリストに対する書き込み操作を行うことができます。
これにより、エコシステム内の他の主体に対して限定的な編集権限を付与し、共同編集や運用分担をしやすくします。

**引数**

* `_namespace`
  * 対象 `namespace` のアドレス。
* `_list`
  * `delegate` を追加するヒントリスト。
* `_delegate`
  * 書き込み権限を付与するアドレス。
* `_untilTimestamp`
  * `delegate` 権限の有効期限（UNIX 時刻）。

##### `addListDelegateSigned`

```javascript
function addListDelegateSigned(
  address _namespace,
  bytes32 _list,
  address _delegate,
  uint256 _untilTimestamp,
  address _signer,
  bytes calldata _signature
) public;
```

署名付きメタトランザクションでヒントリストに `delegate` を追加する関数。
この関数は `addListDelegate` のメタトランザクション版です。
リストの所有者など、権限を持つ `_signer` が**EIP712**データに署名し、第三者の `sender` がトランザクションを送信することで `delegate` を追加します。
署名には `nonce` を含めることで、署名の再利用による不正な追加を防ぎます。

**引数**

* `_namespace`
  * 対象 `namespace`。
* `_list`
  * `delegate` を追加するヒントリスト。
* `_delegate`
  * 書き込み権限を付与するアドレス。
* `_untilTimestamp`
  * `delegate` 権限の有効期限。
* `_signer`
  * `delegate` 追加を承認する署名者。
* `_signature`
  * **EIP712**準拠の署名データ。

##### `removeListDelegate`

```javascript
function removeListDelegate(address _namespace, bytes32 _list, address _delegate) public;
```

ヒントリストから `delegate` を削除する関数。
この関数は、特定のヒントリストに対して設定されていた `delegate` を解除します。
これにより、その `delegate` は対象リストに対する書き込み権限を失います。
権限が不要になった場合や、信頼性に問題が生じた場合などに利用されます。

**引数**

* `_namespace`
  * 対象 `namespace` のアドレス。
* `_list`
  * `delegate` を削除するヒントリスト。
* `_delegate`
  * 削除対象の `delegate` アドレス。

##### `removeListDelegateSigned`

```javascript
function removeListDelegateSigned(
  address _namespace,
  bytes32 _list,
  address _delegate,
  address _signer,
  bytes calldata _signature
) public;
```

署名付きメタトランザクションにより、ヒントリストから `delegate` を削除する関数。
この関数は `removeListDelegate` のメタトランザクション版です。
権限を持つ `_signer` が、`delegate` 削除を承認する**EIP712**署名を行い、`sender` が `_signature` を使ってコントラクト呼び出しを行います。
これにより、オーナー自身が直接トランザクションを送信しなくても `delegate` 権限の管理を安全に行えます。

**引数**

* `_namespace`
  * 対象 `namespace`。
* `_list`
  * `delegate` を削除するリスト。
* `_delegate`
  * 削除対象の `delegate`。
* `_signer`
  * `delegate` 削除を承認した署名者。
* `_signature`
  * **EIP712**準拠の署名データ。

##### `getMetadata`

```javascript
function getMetadata(
  address _namespace,
  bytes32 _list,
  bytes32 _key,
  bytes32 _value
) external view returns (bytes memory);
```

特定のヒント値に紐づいたメタデータを取得する関数。
この関数は、特定の `namespace`、`list`、`key`、`value` に対応するメタデータを返します。
メタデータには付加的な情報（証跡・ハッシュ・関連する構造化情報など）が含まれる場合があり、
ヒント値の解釈や検証を補強する目的で使われます。

**引数**

* `_namespace`
  * 対象 `namespace` のアドレス。
* `_list`
  * 対象ヒントリスト。
* `_key`
  * 対象ヒントキー。
* `_value`
  * 対象ヒント値（メタデータが紐づく値）。

**戻り値**

* `bytes`
  * 指定されたヒントに紐づくメタデータ。

##### `setMetadata`

```javascript
function setMetadata(
  address _namespace,
  bytes32 _list,
  bytes32 _key,
  bytes32 _value,
  bytes calldata _metadata
) public;
```

ヒント値に紐づくメタデータを設定する関数。
この関数は、指定のヒントに対して `metadata` を保存します。
メタデータは `bytes` 形式であり、外部サービスとの連携情報や証明データなど、
柔軟な用途に利用できます。
ヒント本体（`value`）とは独立して管理されるため、値を変更せずに付加情報だけを更新できます。

**引数**

* `_namespace`
  * 対象 `namespace`。
* `_list`
  * 対象ヒントリスト。
* `_key`
  * 対象ヒントキー。
* `_value`
  * メタデータが紐づくヒント値。
* `_metadata`
  * 保存するメタデータ（bytes）。

##### `setMetadataSigned`

```javascript
function setMetadataSigned(
  address _namespace,
  bytes32 _list,
  bytes32 _key,
  bytes32 _value,
  bytes calldata _metadata,
  address _signer,
  bytes calldata _signature
) public;
```

署名付きメタトランザクションでヒントのメタデータを設定する関数。
この関数は `setMetadata` をメタトランザクションに対応させたものです。
権限を持つ `_signer` がメタデータ設定を承認する**EIP712**署名を行い、`sender` がトランザクションを送信します。
ユーザー自身がガスを支払う必要がなく、安全性と利便性の両方を満たします。
署名内容には `nonce` が含まれ、リプレイ攻撃を防止します。

**引数**

* `_namespace`
  * メタデータ対象の `namespace`。
* `_list`
  * 対象ヒントリスト。
* `_key`
  * 対象ヒントキー。
* `_value`
  * メタデータが紐づくヒント値。
* `_metadata`
  * 新しいメタデータ（bytes）。
* `_signer`
  * この更新を承認する署名者。
* `_signature`
  * **EIP712**準拠の署名。

##### `setMetadataDelegated`

```javascript
function setMetadataDelegated(
  address _namespace,
  bytes32 _list,
  bytes32 _key,
  bytes32 _value,
  bytes calldata _metadata
) public;
```

事前に承認された `delegate` がメタデータを設定する関数。
この関数は、`namespace` の所有者によって `delegate` として登録されたアドレスのみが実行できます。
`delegate` はヒント値の更新と同様に、メタデータの設定も行えるため、運用負荷を分散したり、複数主体でリストを管理する時に便利です。
ヒント本体の更新同様、書き込み権限は `list` 単位で制御されます。

**引数**

* `_namespace`
  * 対象 `namespace`。
* `_list`
  * メタデータを追加するヒントリスト。
* `_key`
  * 対象ヒントキー。
* `_value`
  * 対象ヒント値。
* `_metadata`
  * 保存するメタデータ。

##### `setMetadataDelegatedSigned`

```javascript
function setMetadataDelegatedSigned(
  address _namespace,
  bytes32 _list,
  bytes32 _key,
  bytes32 _value,
  bytes calldata _metadata,
  address _signer,
  bytes calldata _signature
) public;
```

署名付きメタトランザクションで `delegate` がメタデータを設定する関数。
この関数は `setMetadataDelegated` のメタトランザクション対応版です。
`delegate` は自身の書き込み操作を**EIP712**署名で承認し、別の `sender` が実行します。
これにより `delegate` がガス代を負担する必要がなくなるため、ユーザー体験が向上します。
`nonce` によって署名の再利用が防がれており、安全性も確保されています。

**引数**

* `_namespace`
  * 対象 `namespace`。
* `_list`
  * 対象ヒントリスト。
* `_key`
  * 対象ヒントキー。
* `_value`
  * メタデータが紐づくヒント値。
* `_metadata`
  * 保存したいメタデータ。
* `_signer`
  * メタデータ設定を承認する署名者。
* `_signature`
  * **EIP712**署名データ。

## 補足

#### データ構造の意図

ヒント情報は以下のような多層的な構造で管理されます。

```javascript
//     namespace          hint list          hint key    hint value
mapping(address => mapping(bytes32 => mapping(bytes32 => bytes32))) hints;
```

この構造は、以下のような階層的な関係を持っています。

| レベル                 | 役割                      |
| ------------------- | ----------------------- |
| `namespace（address）`  | 所有者のアドレスをそのまま名前空間として扱う。 |
| `hint list（bytes32）`  | 用途ごとに分けられたヒントの集合。       |
| `hint key（bytes32）`   | 個々のヒントを識別する値。           |
| `hint value（bytes32）` | ヒントの中身。                 |

この構造の特徴は、`namespace` の所有者が自動的にその `namespace` 内のすべてのリストの初期所有者になる点です。
このため、別途「**リストの所有権を主張する手続き**」を用意する必要がありません。

この方式にはいくつかの利点があります。

まず、仕様実装がシンプルになり、権限管理が明確になります。
`namespace` の所有者が誰なのかが一目で分かり、書き込み権限をどこに付与すべきか判断しやすくなります。
また、意図しない所有権変更や権限混乱のリスクも抑えることができ、攻撃対象が増えにくい構造になっています。

一方で、`delegate` の管理やリスト所有者の変更といった機能には、別の補助的なデータ構造が必要になります。
ただし、これらの追加データは `hint` のメイン構造に影響を与えず、あくまで権限チェックのための補助的なレイヤーとして機能します。

#### 管理機能を備える理由

**ERC Trusted Hint Registry**が大切にしているポイントの1つが、豊富な管理機能を備えていることです。
これによって、複数の主体がヒントリストを共同で扱いやすくなり、エコシステム全体の信頼性を高めることにつながります。

関数の構成を見ても、権限管理や委任、所有者変更、メタデータ管理、メタトランザクションなど、管理・運用面を重視した仕様になっています。

この考え方には、以下のような背景があります。

ユーザーの多くはトランザクションの詳細操作に慣れていないため、ユーザーフレンドリーな仕組みが重要です。
とくにメタトランザクションは、ユーザーが自分の秘密鍵の管理権限を保持したまま、プラットフォーム側が手続きを代行できる仕組みであり、使い勝手を大きく向上させます。
ユーザーは**EIP712**のメッセージに署名するだけでよく、アプリケーションがその署名を使って実際の処理を送信する形になります。

こうした設計により、エコシステムの複雑さをユーザーから隠しつつ、安全で拡張性の高い運用構造を実現しています。

## セキュリティ

#### Meta Transactions

メタトランザクションは便利な仕組みですが、署名済みデータが別の場面で再利用されてしまう「**リプレイ攻撃**」のリスクがあります。

特に以下のようなケースが懸念されます。

* 他のチェーンで同じコントラクトが展開された場合
* コントラクトが再デプロイされた場合

**ERC Trusted Hint Registry**は**EIP712**を採用することで、この問題を防いでいます。
**EIP712**では、署名の中に「**ドメイン情報**」が含まれます。
ドメイン情報にはチェーンIDやコントラクトアドレスが含まれるため、異なるコントラクト・異なるチェーンでは同じ署名を使い回すことができません。

メタトランザクションを安全に扱うための基本が、この仕様に組み込まれています。

#### 権限管理（Rights Management）

**ERC7506**では、権限の管理が非常に重要な要素となっています。

ヒントリストの `owner` は、そのリストに対して完全な管理権限を持つため、誰を `delegate` として追加するか、どのキーに対する編集を許可するかなど、書き込みに関する最終的な判断を行います。

権限管理の仕組みは、以下のような目的で設計されています。

* 不正なアドレスがヒント値を変更できないようにする
* `delegate` の操作を必要に応じて細かく制御できるようにする
* `owner` が常に全権限を保持し続ける

結果として、ヒント情報の信頼性を保ち、外部からの不正な書き換えを防ぎます。

#### ガバナンス（Governance）

**ERC Trusted Hint Registry**はガバナンスの仕組みを標準仕様に含めていません。
その理由は、ガバナンスはエコシステムによって大きく異なるため、共通仕様として定義するのが適さないからです。

ただし、エコシステムによっては、ヒントリストの変更や削除に承認プロセスを必要とする場合があります。
そのため、**ERC7506**はガバナンスを外側で自由に設定できるようにしています。

ガバナンス方法の例としては以下があります。

| 方法         | 説明                      |
| ---------- | ----------------------- |
| コントラクトの拡張  | 特定のメソッドにガバナンスチェックを追加する。 |
| マルチシグウォレット | 複数人の承認を必要とする仕組みを使う。     |
| オフチェーン手続き  | 外部システムによる承認プロセスを設ける。    |

これにより、エコシステムの特性に合わせた柔軟な運用が可能になります。

## 引用

Philipp Bolte (@strumswell), Dennis von der Bey (@DennisVonDerBey), Lauritz Leifermann (@lleifermann), "ERC-7506: Trusted Hint Registry [DRAFT]," Ethereum Improvement Proposals, no. 7506, August 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7506.

## 最後に

今回は「クレームの取り消し情報や信頼できる発行者情報などをチェーン上で管理し、信頼性を強化する仕組みを提案している**ERC7506**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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