# [ERC7208] オンチェーンデータ管理の新しい仕組みを理解しよう！

> ERC7208は、オンチェーン上に保存されるデータを「抽象化（Abstraction）」するための一連のインターフェースを定義しています。これにより、データの保存とそれを制御するロジックを分離し、柔軟で拡張性のある設計を可能にします。

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

## はじめに

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

https://amzn.asia/d/gxvJ0Pw

今回は、オンチェーンのデータ保存（Data Object）と機能ロジック（Data Manager）を分離し、bytes32のData PointとData Indexによる共通アクセス構造で、データ管理を抽象化・標準化す提案している**ERC7208**についてまとめていきます！

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

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

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

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

## 概要

**ERC7208**は、オンチェーン上に保存されるデータを「**抽象化（Abstraction**）」するための一連のインターフェースを定義しています。
これにより、データの保存とそれを制御するロジックを分離し、柔軟で拡張性のある設計を可能にします。

この仕組みでは、オンチェーンのデータを「**データオブジェクト（Data Object：DO）**」というスマートコントラクトに格納します。
そして、これらのデータを参照するための外部インデックス機構を「**データポイント（Data Point：DP）**」と呼びます。
データの読み取りや変更は、「**データマネージャー（Data Manager：DM）**」と呼ばれる別のスマートコントラクト群によって行われます。

さらに、**ERC7208**ではアクセス制御のために2つの仕組みを導入します。

- 「**データインデックス（Data Index：DI）**」
    DMによるDOへのアクセスを制限するゲート機構として機能します。
-「**データポイントレジストリ（Data Point Registry：DPR）**」
    DPの発行（登録）を管理する仕組みです。

また、**ERC7208**の大きな特徴として「**データの可搬性（Data Portability）**」、すなわち「**水平的なデータ移動（Horizontal Data Mobility）**」の概念を導入しています。
これにより、異なる「**データインデックス（DI）**」間でデータを移動できるようになり、大規模なアップデートを行っても、基盤となるデータストレージに影響を与えることなくシステム全体を更新できます。

## 動機

Ethereumのエコシステムが拡大する中で、オンチェーン機能の需要も急速に増加しています。
市場の成長とともに、より複雑で柔軟なシステムが求められて効率化の必要性も高まっています。

これまで、新しいトークン標準（ERC）が次々と提案されてきましたが、その多くは市場の流行に左右されたものも多く見られました。
それぞれの標準には目的がありますが、異なる標準間での「**相互運用性（Interoperability）**」を高めるためには、より柔軟な仕組みが必要です。
つまり、異なるERC同士をつなぐ「**標準的なアダプタ機構（Standard Adapter Mechanism）**」が求められています。

#### 断片化された現状と課題

このようなアダプタが存在しない現状では、各プロジェクトが独自（Bespoke）に相互運用性を実現しようとしています。
しかし、こうした個別実装は非効率的であり、エコシステム全体の断片化（Fragmentation）を招いています。

加えて、すべての資産に適用できる「**万能な標準**」は存在しません。
資産には以下のような多様な種類があります。

| 資産の種類 | 説明  |
| ------- | -------------------- |
| Fungible（代替可能） | **ERC20**のような同一性を持つトークン |
| Non-Fungible（非代替）  | **ERC721**などのNFT        |
| Digital Twin（デジタルツイン） | 現実世界の資産をデジタルで表現したもの  |
| Real-world Assets（RWA） | 不動産や証券など実資産のトークン化    |
| DePin（Decentralized Physical Infrastructure） | 分散型物理インフラに紐づく資産      |

これらの資産は、それぞれ異なるトークン標準を使用して表現されています。
この多様性はイノベーションを促進する一方で、異なる標準間の互換性確保を難しくしています。

#### 相互運用性の欠如による問題

異なる標準間で資産をやり取りしたり、トレードや操作を行うためには、それぞれのプロトコルが関連するインターフェースに対応しなければなりません。
しかし、独自実装の増加と、スマートコントラクトの「**不変性（Immutability）**」がこれをさらに複雑にしています。

すでにデプロイ済みのプロトコルは、新しい標準に適応しにくく、将来のアップデートにも柔軟に対応できません。
これでは、エコシステム全体の発展を妨げることになります。

そのため、異なる標準でトークン化された資産が相互に連携できるようにするための「**共通アダプタ**」が必要です。
**ERC7208**は、そのための仕組みを提供します。

#### 提案の目的と価値

**ERC7208**の目的は、「**データの管理（Handling）**」を「**ロジックの実装（Logic Implementation）**」から切り離し、ERCインターフェースに依存せずにデータを扱えるようにすることです。
これにより、開発者は標準に縛られず柔軟にデータを操作できるようになります。

**ERC7208**では、オンチェーンデータを「**データオブジェクト（DO）**」として格納し、そのデータを「**データポイント（DP）**」として抽象化します。
これらは複数の「**データマネージャー（DM）**」と連携可能であり、異なる標準の資産でも同時にアクセスや操作が行えます。

この仕組みは、既存および将来のトークン標準と共存し、柔軟・効率的・一貫性のある資産管理を可能にします。

#### データ抽象化

**ERC7208**の特徴のひとつは「**データ抽象化**」です。
これは、データの保存処理をトークンのロジックから切り離す考え方です。

従来、開発者はトークン標準（**ERC20**、**ERC721**など）に応じて、複雑な継承構造や重複する実装をしていました。
**ERC7208**では、これらを共通のインターフェースで統一することにより、開発負荷を軽減します。

結果として、データは「**どの標準を使うか**」に左右されず、独立して扱うことができます。

#### 標準の中立性

**ERC7208**は「**標準中立的（Standard Neutral）**」なアプローチを採用しています。
つまり、特定のトークン標準に依存せず、あらゆる標準間でデータをシームレスに移行できるよう設計されています。

これにより、異なる標準間の相互運用性が飛躍的に向上し、分断されたトークンエコシステムを統合的に扱えるようになります。

#### 一貫したインターフェース

**ERC7208**では、すべての資産データを「**基本的な関数群**」で操作できるようにします。
つまり、どの標準のトークンであっても、共通の関数でデータにアクセスできるため、開発者は統一的な方法で資産を管理できます。

また、データやメタデータ（属性情報）をオンチェーン上に保存し、同じ関数群を通じて取得・更新できるようにします。

#### データの可搬性

さらに、**ERC7208**では「**データの水平移動（Horizontal Mobility）**」を実現します。
これは、ある「**データインデックス（DI）**」の実装から別のDI実装へデータを移動できる仕組みです。

これにより、プロトコルやロジックを大規模に更新しても、基盤となるデータストレージに影響を与えず、柔軟なアップグレードが可能になります。

つまり、長期的な互換性を保ちつつ、システムの進化に対応できる構造が整います。

## 仕様

:::message
#### 概要

この提案（例：**ERC7208**）は、オンチェーンの「**データ保存（ストレージ）**」と「**機能ロジック**」を分離して扱う設計を標準化します。
データは**Data Object（DO）**に集約して保存し、そのデータを指し示す識別子として**Data Point（DP）**を使います。
データの読み書きやビジネスロジックは**Data Manager（DM）**が担い、DMとDOのあいだのアクセス制御は**Data Index（DI）**が仲介します。
DP自体の発行・所有・管理は**Data Point Registry（DPR）**が行います。

この分離により、異なるトークン標準（例：**ERC20**、**ERC721**など）同士でも同一の`read`/`write`の手順でデータにアクセスできるようになり、相互運用性が向上します。
さらに、アクセス制御の実装（DI）を差し替えても、保存済みデータ（DO）はそのまま維持できるため、将来のアップグレードにも強い構造になります（データの水平移動／ポータビリティ）。

```mermaid
flowchart TD
    A[User/アプリ] --> B[Data Manager: DM<br/>ビジネスロジック]

    %% 読み取りと書き込みの経路
    B -- 読み取り（read） --> D[Data Object: DO<br/>データ保存]
    B -- 書き込み（write）は必ず経由 --> C[Data Index: DI<br/>承認・アクセス制御]
    C -- 承認済みなら中継 --> D

    %% 参照子とレジストリ
    F[Data Point Registry: DPR<br/>DPの発行/所有/管理] -- 発行/管理 --> E[Data Point: DP<br/>bytes32の参照子]
    E -- インデックス/参照 --> D

```

#### 仕組み

##### 1. データ参照子（Data Point：DP）

DPは`bytes32`の固定長で、データの場所や整合性を判別するための情報（プレフィックス、チェーンID、発行レジストリのアドレスなど）をエンコードします。
DP自体に資産データを入れず、**インデックス（参照子）**として機能します。
これにより、将来の仕様追加や複数標準との併用でも、同じ形式で参照できます。

##### 2. データ保存（Data Object：DO）

DOはオンチェーンの実データを保持し、`read(dp, operation, data)`と`write(dp, operation, data)`という共通インターフェースでアクセスされます。
DOは特定の**Data Index**を信頼先として登録でき、アクセス制御の委譲や将来的な切り替え（ポータビリティ）に対応します。

##### 3. ロジックとUIの窓口（Data Manager：DM）

DMはアプリのビジネスロジックを実装し、ユーザー操作をDOの読み書きに変換します。
読み取りは`IDataIndex.read()`または`IDataObject.read()`を用いて行えますが、書き込みは常に`IDataIndex.write()`を経由します。
これにより、権限検証を確実に通過した更新だけがDOへ到達します。
DMは複数のDPを扱え、他のDMとDPを共有できます。

##### 4. アクセス制御のゲート（Data Index：DI）

DIは「**どのDMが、どのDPを、どのDOに対して操作できるか**」を承認（Approval）で管理します。
書き込み要求はまずDIが受け取り、承認済みであればDOの`write()`を呼び出します。
DIはID管理（例：アドレスベースのユーザーID）も担えますが、将来の移行を阻害しないID設計が重要です。

##### 5. 参照子の発行源（Data Point Registry：DPR）

DPRはDPの発行・所有権・管理者ロールを扱います。
DMは必要なときにDPRへDPの割り当てを要求します。
DOやDIはDP内に埋め込まれたレジストリ情報を参照することで、発行源や権限の正当性を素早く検証できます。

##### 6. 読み書きの流れ

1. DMが必要なDPをDPRから割り当ててもらいます。
2. 読み取りは`read()`でDOへ到達（DI経由または直接）。
3. 書き込みは必ずDI経由で`write()`を実行し、承認済みであればDOに反映されます。
4. 将来、アクセス制御を変えたい場合は、DO側の`setDIImplementation()`でDIの実装を差し替えても、保存済みデータはそのままです（水平移動）。
:::

### 用語

| 用語 | 説明 |
| ----- | ---------- |
| **Data Point（データポイント）**  | オンチェーンデータ構造を一意に識別する参照情報。1つまたは複数の**Data Object**内に保存され、1つまたは複数の**Data Manager**によって管理されます。発行は**Data Point Registry**によって行われます。 |
| **Data Object（データオブジェクト）**  | 低レベルのストレージ管理を実装したスマートコントラクト。データポイントを通じてデータ構造をインデックス化します。   |
| **Data Manager（データマネージャー）**           | 高レベルのロジックとエンドユーザー向けの操作インターフェースを提供するスマートコントラクト。**Data Object**のデータを管理します。  |
| **Data Point Registry（データポイントレジストリ）** | データポイントの発行を管理するコントラクト。互換性のあるデータポイントの空間を定義します。 |
| **Data Index（データインデックス）**             | **Data Manager**が**Data Object**へアクセスする際のアクセス制御を行うコントラクト。 |

### データポイント構造

**Data Point**は、オンチェーンのデータ構造を参照・インデックス化するための低レベル構造体です。
直接データを保存するのではなく、データを指し示す「**ポインタ**」として機能します。

#### 主な要件

| 項目    | 内容   |
| ----- | --------- |
| 型     | `bytes32`  |
| 目的  | データのインデックス化    |
| 非推奨用途 | 資産データの直接保存   |
| 構成    | 4バイトのプレフィックス、4バイトのチェーンID、20バイトのレジストリアドレスなどで構成されます。 |
| ユニーク性 | 各データポイントはレジストリによって一意の識別子を持ちます。 |

#### 推奨される内部構造

```javascript
/**
 * 推奨される DataPoint の内部構造（リファレンス実装例）
 * 0xPPPPVVRRIIIIIIIIHHHHHHHHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 * 
 * - Prefix (bytes4)
 *   -- PPPP - 種別プレフィックス（例: 0x4450 は "DP" の ASCII 表現）
 *   -- VV   - DataPoint仕様のバージョン（例: リファレンス実装では 0x00）
 *   -- RR   - 予約領域
 * 
 * - Registry-local identifier
 *   -- IIIIIIII - 32ビットの実装固有ID
 * 
 * - Chain ID (bytes4)
 *   -- HHHHHHHH - チェーンID
 * 
 * - REGISTRY Address (bytes20)
 *   -- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - データポイントを発行したレジストリのアドレス
 */
```

この構造により、どのチェーン上のどのレジストリがデータポイントを発行したかを明確に追跡できます。
また、プレフィックスを用いることで他のデータポイントとの互換性を保つことが可能になります。

:::message
#### 例：具体的な `DataPoint` の構築

| 項目 | 値 | 説明  |
| ---- | ------ | ----- |
| 種別プレフィックス (PPPP) | `0x4450` | `"DP"` の ASCII 表現（Data Pointの略） |
| バージョン (VV) | `0x01` | DataPoint仕様のバージョン  |
| 予約領域 (RR) | `0x00` | 予約フィールド。将来拡張用 |
| 実装固有ID (IIIIIIII) | `0x000000A1` | レジストリ内部で一意の識別子  |
| チェーンID (HHHHHHHH) | `0x000000AA` | 例えば「170」というチェーンID |
| レジストリアドレス (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) | `0xAbCDEF1234567890abcdef1234567890ABCdEf12` | データポイントを発行したレジストリのアドレス  |

1. **各セグメントを用意**

    ```text
    PPPP = 0x4450         // "DP"
    VV   = 0x01           // Version 1
    RR   = 0x00           // Reserved
    IIIIIIII = 0x000000A1 // 実装固有ID
    HHHHHHHH = 0x000000AA // Chain ID
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 0xAbCDEF1234567890abcdef1234567890ABCdEf12
    ```

2. **全てを連結**

    上記の要素を順番に結合します。
    
    ```text
    0x44500100000000A1000000AAAbCDEF1234567890abcdef1234567890ABCdEf12
    ```
    
    これが、最終的な `bytes32` の値となります。

完成した `DataPoint` は以下のようになります。

```javascript
bytes32 dataPoint = 0x44500100000000A1000000AAAbCDEF1234567890abcdef1234567890ABCdEf12;
```

| バイト範囲 | 名称 | 値　| 説明 |
| ----- | --------- | ------ | --------------- |
| 0〜3  | プレフィックス   | `0x4450`  | "DP" の ASCII 表現 |
| 4〜5  | バージョン  | `0x01`   | バージョン番号         |
| 6〜7   | 予約領域      | `0x00`    | 将来拡張用           |
| 8〜11  | 実装固有ID    | `0x000000A1`   | レジストリ固有のID      |
| 12〜15 | チェーンID    | `0x000000AA`    | チェーン識別子         |
| 16〜31 | レジストリアドレス | `0xAbCDEF1234567890abcdef1234567890ABCdEf12` | 発行元レジストリ  |

:::

### データオブジェクトインターフェース

**Data Object**は、実際のデータ保存と管理を担うスマートコントラクトです。
データ構造をインデックス化するために**Data Point**を使用し、低レベルのストレージ管理を実装します。

また、将来的に異なる**Data Index**実装へ移行できるよう、`setDIImplementation()`関数によってアクセス管理ロジックを切り替えることができます。

#### 実装すべきインターフェース

`Data Object`は、以下の**IDataObject**インターフェースを実装する必要があります。

```javascript
interface IDataObject {
    function read(bytes32 dp, bytes4 operation, bytes calldata data) external view returns(bytes memory);
    function write(bytes32 dp, bytes4 operation, bytes calldata data) external returns(bytes memory);
    function setDIImplementation(bytes32 dp, address newImpl) external;
}
```

##### `read`

```javascript
function read(bytes32 dp, bytes4 operation, bytes calldata data) external view returns(bytes memory);
```

データを読み取る関数。

指定された`DataPoint`に対応するデータ構造から情報を読み出します。
読み出し処理は`operation`によって指定された操作種別に基づいて実行されます。

**引数**

* `dp`
  　読み取る対象のデータポイント識別子。
* `operation`
  　実行する読み取り操作の種類を表す識別子。
* `data`
  　操作に必要な追加データ。

**戻り値**

* `bytes memory`
  　操作の結果として返されるデータ。

##### `write`

```javascript
function write(bytes32 dp, bytes4 operation, bytes calldata data) external returns(bytes memory);
```

データを保存（書き込み）する関数。

指定された`DataPoint`に紐づくストレージに対して、`operation`に応じた書き込み処理を行います。

**引数**

* `dp`
  　書き込む対象のデータポイント識別子。
* `operation`
  　実行する書き込み操作の種類を表す識別子。
* `data`
  　操作に必要なデータ。

**戻り値**

* `bytes memory`
  　操作結果。空のバイト列である場合もあります。

##### `setDIImplementation`

```javascript
function setDIImplementation(bytes32 dp, address newImpl) external;
```

`Data Index`の実装を設定または更新する関数。

データ管理の委譲先として使用する`Data Index`の実装を指定します。
これにより、異なるアクセス管理ロジックへ柔軟に切り替えることができます。

**引数**

* `dp`
  　対象のデータポイント識別子。
* `newImpl`
  　新しい`Data Index`実装のアドレス。

### データマネージャー

**Data Manager**は、ビジネスロジックや高レベルのデータ管理を担うスマートコントラクトです。
アプリケーション全体におけるユーザーインターフェース層として機能し、データの取得には`read()`を、更新や登録には`write()`を利用して、オンチェーン上のデータとやり取りを行います。

データの読み取りを行う場合、**Data Manager**は`IDataIndex.read()`もしくは`IDataObject.read()`を使用して、適切なデータアクセスを実現します。
一方で、データの書き込み操作を行う時には、必ず`IDataIndex.write()`を経由してデータを更新します。
これにより、アクセス制御が適切に適用され、セキュリティと一貫性を維持したデータ操作が可能になります。

さらに、**Data Manager**は他の**Data Manager**と**Data Point**を共有することができ、複数のデータポイントを同時に扱う柔軟性を持ちます。
これにより、異なるマネージャー間でのデータ連携や、複数資産にまたがる複合的な処理を行うことが可能です。

また、**Data Manager**は**Data Point Registry**から新しいデータポイントを要求・取得するためのロジックを実装する必要があります。
これにより、アプリケーションは必要なデータ参照を動的に確保し、システムの拡張や運用においても高い柔軟性を発揮します。

このように、**Data Manager**はビジネスロジックとデータ管理の中核として機能し、柔軟なデータ操作を実現しながら厳密なアクセス制御によってセキュリティと整合性を両立します。

### データポイントレジストリインターフェース

**Data Point Registry**は、データポイントの発行・移転・アクセス管理を行うスマートコントラクトです。
データマネージャーは、このレジストリに対してデータポイントの割り当てを要求します。

以下の**IDataPointRegistry**インターフェースを実装する必要があります。

```javascript
interface IDataPointRegistry {
    function isAdmin(bytes32 dp, address account) external view returns (bool);
    function allocate(address owner) external payable returns (DataPoint);
    function transferOwnership(bytes32 dp, address newOwner) external;
    function grantAdminRole(bytes32 dp, address account) external returns (bool);
    function revokeAdminRole(bytes32 dp, address account) external returns (bool);
}
```

##### `isAdmin`

```javascript
function isAdmin(bytes32 dp, address account) external view returns (bool);
```

指定アドレスが特定のデータポイントの管理者（Admin）であるかを確認する関数。

データポイントごとに設定された管理権限を確認します。

**引数**

* `dp`
  　確認対象のデータポイント識別子。
* `account`
  　確認するアカウントアドレス。

**戻り値**

* `bool`
  　`true`の場合、対象アカウントは管理者。

##### `allocate`

```javascript
function allocate(address owner) external payable returns (DataPoint);
```

新しいデータポイントを発行し、指定したアドレスに割り当てる関数。

発行時に所有者にAdminロールを付与します。

**引数**

* `owner`
  　新しいデータポイントの所有者アドレス。

**戻り値**

* `DataPoint`
  　割り当てられたデータポイント。

##### `transferOwnership`

```javascript
function transferOwnership(bytes32 dp, address newOwner) external;
```

データポイントの所有権を移転する関数。

既存のデータポイントを新しいオーナーに譲渡します。

**引数**

* `dp`
  　対象のデータポイント。
* `newOwner`
  　新しい所有者アドレス。

##### `grantAdminRole`

```javascript
function grantAdminRole(bytes32 dp, address account) external returns (bool);
```

指定アドレスにAdminロールを付与する関数。

他の管理者ロールを付与・剥奪できる権限を与えます。

**引数**

* `dp`
  　対象のデータポイント。
* `account`
  　新たに管理者ロールを付与するアドレス。

**戻り値**

* `bool`
  　ロールが付与された場合に`true`。

#### `revokeAdminRole`

```javascript
function revokeAdminRole(bytes32 dp, address account) external returns (bool);
```

指定アドレスのAdminロールを剥奪する関数。

アカウントが自らのロールを剥奪した場合でも、再付与は可能です。

**引数**

* `dp`
  　対象のデータポイント。
* `account`
  　ロールを剥奪するアドレス。

**戻り値**

* `bool`
  　ロールが剥奪された場合に`true`。

### データインデックスインターフェース

**Data Index**は、**Data Manager**のアクセス制御を担うゲートウェイです。
どのマネージャーがどのデータポイント・データオブジェクトにアクセスできるかを定義します。

また、ID管理機構により、異なる実装間の互換性空間を定義します。

以下の**IDataIndex**インターフェースを実装します。

```javascript
interface IDataIndex {
    function isApprovedDataManager(bytes32 dp, address dm) external view returns(bool);
    function allowDataManager(bytes32 dp, address dm, bool approved) external;
    function read(address dobj, bytes32 dp, bytes4 operation, bytes calldata data) external view returns(bytes memory);
    function write(address dobj, bytes32 dp, bytes4 operation, bytes calldata data) external returns(bytes memory);
}
```

##### `isApprovedDataManager`

```javascript
function isApprovedDataManager(bytes32 dp, address dm) external view returns(bool);
```

指定された**Data Manager**が特定の**Data Point**に対して書き込み可能かを確認する関数。

アクセス制御の一環として、事前に承認されているかを確認します。

**引数**

* `dp`
  　対象のデータポイント。
* `dm`
  　確認対象のデータマネージャーアドレス。

**戻り値**

* `bool`
  　承認済みであれば`true`。

##### `allowDataManager`

```javascript
function allowDataManager(bytes32 dp, address dm, bool approved) external;
```

データマネージャーのアクセス権限を設定する関数。

特定のデータポイントに対して、指定マネージャーのアクセスを許可または拒否します。
この関数はデータポイントの管理者のみ実行可能であるべきです。

**引数**

* `dp`
  　対象のデータポイント。
* `dm`
  　アクセス対象のデータマネージャー。
* `approved`
  　`true`の場合アクセス許可、`false`の場合拒否。

##### `read`

```javascript
function read(address dobj, bytes32 dp, bytes4 operation, bytes calldata data) external view returns(bytes memory);
```

指定データオブジェクトからデータを読み取る関数。

アクセス制御を通過した上で、対象のデータ構造に対して読み取りを行います。

**引数**

* `dobj`
  　対象のデータオブジェクトアドレス。
* `dp`
  　対象のデータポイント。
* `operation`
  　読み取り操作の種類。
* `data`
  　追加データ。

**戻り値**

* `bytes memory`
  　操作結果のデータ。

##### `write`

```javascript
function write(address dobj, bytes32 dp, bytes4 operation, bytes calldata data) external returns(bytes memory);
```

指定データオブジェクトにデータを書き込む関数。

承認済みのデータマネージャーのみが実行可能です。
対象データ構造に対して、指定された操作に基づく書き込みを行います。

**引数**

* `dobj`
  　対象のデータオブジェクトアドレス。
* `dp`
  　対象のデータポイント。
* `operation`
  　実行する操作の種類。
* `data`
  　書き込みに使用するデータ。

**戻り値**

* `bytes memory`
  　書き込み結果のデータ。

## 補足

#### `bytes32`による柔軟なデータポインタ

**Data Point（データポイント）**を`bytes32`としてエンコードする決定は、柔軟性と将来の互換性を重視した設計思想に基づいています。

`bytes32`は32バイトの固定長データ型であり、Ethereum上で最も広く使用される基本的な型の1つです。
この形式を採用することで、さまざまなデータ構造やエンコード形式に対応でき、異なるユースケースに合わせた拡張が容易になります。
例えば、将来的に新しいデータ標準や構造が登場しても、`bytes32`で定義されたデータポイントは互換性を維持しつつ、それらを参照することが可能です。
これにより、現在のERCに基づく標準アダプタ（Standard Adapter）を将来の新しい構造にも適用できるようになります。

また、**Data Point**にはプレフィックス（先頭の識別子）を付与することが推奨されています。
これにより、**Data Object**はデータアクセス時に互換性を即座に判断でき、異なる規格間での衝突やエラーを防げます。
同時に、このプレフィックスは、対応する**Data Point Registry**（発行元レジストリ）を特定し、管理者アクセス権限を検証する際にも使用されます。
一方で、末尾（サフィックス）には「**どのレジストリから発行されたデータポイントか**」を特定する情報を格納することが必須とされています。
これにより、**Data Object**は異なるレジストリ由来の無効なトランザクションを素早く検出し、誤ったデータ利用を防止できます。

このような構造により、システムは柔軟性を保ちながら、安全で一貫性のあるデータ参照を実現します。

#### Data Pointの管理とアクセス制御

**Data Manager（データマネージャー）**は、自身が利用するデータポイントを自由に選択できます。
しかし、その割り当てと管理は必ず**Data Point Registry（データポイントレジストリ）**を通じて行われます。
つまり、データポイントの発行・所有・管理といった操作は、統一的なレジストリを介して処理されるため、アクセス制御や権限管理が明確に維持されます。

データの書き込みアクセス（`write()`）は、**Data Index（データインデックス）**を経由して実行されます。
これにより、書き込み操作が行われるたびに適切なアクセス検証が行われ、許可されたマネージャーのみがデータを変更できるようになります。
このアクセス経路の明確な分離が、セキュリティと統一性を保証する重要な仕組みとなっています。

#### Data Objectの独立性とスケーラビリティ

**Data Object（データオブジェクト）**は、他のコンポーネントから独立したスマートコントラクトとして設計されています。
これは、システムのスケーラビリティを確保するための重要な設計判断です。

それぞれの**Data Object**は、共通の`read()`および`write()`インターフェースを実装しており、**Data Manager**との通信を標準化します。
この共通化により、複数のアプリケーションが異なる**Data Object**をそれぞれのアドレス空間で保持しながらも、統一的な方法でデータにアクセスできます。

また、この階層構造を採用することで、資産を表すトークンのインターフェース（**ERC20**・**ERC721**など）とは独立してデータストレージを管理できます。
つまり、資産のロジック（トークンの操作など）とデータの保管（ステートの記録）を分離し、それぞれが独自に拡張・更新できる柔軟な構造を実現します。

アクセス権限の管理は各実装に委ねられており、それぞれの**Data Object**が独自のデータポイント領域を制御できます。
この仕組みにより、複雑で動的なユースケースを扱うことが可能になり、異なるERC標準やスマートコントラクト同士の連携、さらにはクロスチェーンやロールアップ環境を組み合わせた高度な資産管理も実現できます。

#### 変更可能なオンチェーンデータの管理

従来の多くの標準化インターフェースでは、オンチェーンデータは静的（immutable）であることが多く、変更やアップデートには制約がありました。
しかし、**ERC7208**の**Data Object**は、**mutable（可変）なオンチェーンデータ**の保存を可能にします。

これにより、**Data Manager**は委譲されたストレージにおいて動的な状態を保持し、必要に応じて随時変更を反映できます。
例えば、ユーザーの行動に応じた状態変化や、外部シグナルに基づいた資産更新など、時間とともに変化するデータを柔軟に扱うことができます。
これが、従来の固定的なストレージ設計にはない大きな利点です。

このような仕組みによって、アプリケーションはよりリアルタイムでインタラクティブな機能を備えることができ、オンチェーン上での動的ロジックを実現できます。

#### データの水平移動

もう1つの重要な設計要素が、**水平的なデータ移動（Horizontal Data Mobility）**、または**データポータビリティ**と呼ばれる仕組みです。

**Data Manager**は、ある**Data Object**のストレージ管理を、別の**Data Index**実装へ移行することが可能です。
つまり、アクセス管理ロジックを変更したり、より高度なアクセス制御機構を導入したりする時に、基盤となるストレージ構造を変更する必要がありません。
これは、データそのもの（価値を保持する情報）は常に**Data Object**側に保持されているためです。

結果として、アクセス制御やユーザー管理を行う**Data Index**をアップグレードしても、既存のデータ構造や値を維持したままシステムを進化させることができます。
これにより、システム全体の保守性と将来適応性が向上し、長期的な拡張性を確保することができます。

## 互換性

**ERC7208**は、既存のトークン標準の機能を拡張することを目的としており、破壊的変更を導入しません。
すでにデプロイ済みのトークンは、他のERCで発行されたものであっても、そのままラップ（wrap：既存資産を外側のインターフェースで包むこと）し、インデックス化（index：検索・参照しやすいように識別子を付けること）して**Data Point**として扱えます。
保存は**Data Object**で担い、その後は任意の**Data Manager**の実装を通して公開・操作できます。

相互運用（異なる標準どうしが連携すること）を前提に統合する場合は、ユースケースごとに互換性を検証する必要があります。

ただし、**ERC7208**で定義するインターフェースは、ストレージをロジックから切り離すことで、標準が異なっても同じ`read`/`write`手順でデータにアクセスできるようにします。
その結果、既存のトークンはラップして**Data Object**に紐づけるだけで、**Data Manager**から操作できます。
元のコントラクト本体を変更せずに機能を拡張でき互換性も維持できます。

## 参考実装

参考実装は、**Standard Adapter（標準アダプタ：異なる標準の橋渡しをする実装）**の例として、**代替可能（Fungible）**と**半代替可能（Semi-Fungible）**の2種類のトークンがストレージを共有する構成を示します。
エンドユーザーは2つのインターフェースいずれかで操作します。
半代替可能トークン側は単一の**Data Manager**が代表し、代替可能トークン側は複数の**Data Manager**によって表現されます。
ストレージ（保存）とロジック（機能）を分離する仕組みは、**Fungible Fractions Data Object**という単一の**Data Object**です。
さらに、**ファクトリ（factory：同型のコントラクトを反復的にデプロイするための補助）**を用いて、各半代替可能トークンとストレージを共有する代替可能トークンのインターフェースをデプロイします。

どちらのインターフェースから`transfer()`が呼ばれても、双方のインターフェースがイベントを発行します。

https://eips.ethereum.org/assets/eip-7208/contracts/

## セキュリティ

アクセス制御は3層に分離されます。分離の目的は、責務の明確化と誤設定の局所化です。
どの層が失敗しても、他層の検証が追加の安全網として機能します。

#### 層別の責務

| 層 | コンポーネント | 役割の要点 |
| ----- | -------- | ------- |
| Layer 1 | **Data Point Registry** | **Data Manager**へのデータポイント割り当てを担い、**所有権（Admin/Write権限）**を管理します。レジストリは「誰が`allow/deny`できるか」を決める起点です。   |
| Layer 2 | **Data Index**          | **Data Manager**が**Data Point**にアクセスできるかを**承認（Approval）**で管理します。誰が承認を付与・剥奪できるかは**Data Point Registry**に照会して検証します。 |
| Layer 3 | **Data Object**         | **Data Point**と**Data Index**の**信頼関係**を管理します。信頼済みの**Data Index**からの`write()`だけを受け付けます。                            |

#### アクセス制御の3層モデル

```
Layer 1: Data Point Registry
  └─ Data Pointの「所有者」と「権限（Admin/Write）」を管理する基点
        ↓（誰が許可を付与・剥奪できるかを判定）

Layer 2: Data Index
  └─ Data Managerごとの承認（Approval）を管理
        ↓（承認済みであれば書き込み要求を中継）

Layer 3: Data Object
  └─ 信頼先として登録したData Indexからのwriteだけを受け入れる

```

#### ユーザーID管理に関する注意

**Data Object**はユーザー関連データを保持するケースが多く、**Data Manager**もその管理ロジックを持ちます。
ここで**Data Index**側で**ユーザー管理（例：アドレスに基づくID）**を提供できる設計は便利ですが、IDの選定を誤ると、Data Managerが別のData Indexへ移行（マイグレーション）する時の障壁になります。**水平移動（Horizontal Mobility）**を阻害しないよう、IDスキームは移行耐性を意識して選ぶ必要があります。

## 引用

Rachid Ajaja (@abrajaja), Matthijs de Vries (@sudomati), Alexandros Athanasopulos (@Xaleee), Pavel Rubin (@pash7ka), Sebastian Galimberti Romano (@galimba), Daniel Berbesi (@berbex), Apostolos Mavropoulos (@ApostolosMavro), Barbara Marcano (@Barbara-Marcano), Daniel Ortega (@xdaniortega), "ERC-7208: On-Chain Data Containers," Ethereum Improvement Proposals, no. 7208, June 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7208.

## 最後に

今回は「オンチェーンのデータ保存（Data Object）と機能ロジック（Data Manager）を分離し、bytes32のData PointとData Indexによる共通アクセス構造で、データ管理を抽象化・標準化す提案している**ERC7208**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下の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
