はじめに

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

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

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

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

概要

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実装へデータを移動できる仕組みです。

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

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

仕様

概要

この提案(例: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)はそのまま維持できるため、将来のアップグレードにも強い構造になります(データの水平移動/ポータビリティ)。

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 - データポイントを発行したレジストリのアドレス
 */

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

例:具体的な 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()が呼ばれても、双方のインターフェースがイベントを発行します。

セキュリティ

アクセス制御は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層モデル

text
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などからお気軽に質問してください!

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