# [ERC6604] Abstract Tokenの仕組みを理解しよう！

> この提案では、ブロックチェーン技術の中で抽象トークン（Abstract Token）に関する概念を理解するためのものです。

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

## はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、**ERC20**、**ERC721**、**ERC1155**トークンをオフチェーンでのトークンの`mint`（メッセージとして）、スマートコントラクトを通じたオンチェーンへの具現化、そしてメッセージへの再抽象化を可能にする仕組みである、抽象トークンの標準インターフェースを提案している**EIP6604**についてまとめていきます！

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

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

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

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

## 概要

この提案では、ブロックチェーン技術の中で抽象トークン（**Abstract Token**）に関する概念を理解するためのものです。
抽象トークンは、オフチェーン（ブロックチェーン外）でのメッセージとしてのトークンの発行（`Mint`）、オンチェーン（ブロックチェーン上）でのスマートコントラクトを通じたトークンの具現化（**Reify**）、そしてメッセージへのトークンの再抽象化（**Dereify**）の標準インターフェースを提供します。
このプロセスは、**ERC20**、**ERC721**、**ERC1155**などの既存の標準に準拠していることができ、ウォレットや他のアプリケーションが、ブロックチェーン上での合意依存のイベントが発生する前に潜在的なトークンをより適切に扱うことを可能にします。

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

https://chaldene.net/erc20

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

https://chaldene.net/erc721

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

https://chaldene.net/erc1155

### 全体像とプロセス

#### トークンのオフチェーン発行（Minting）

トークンは最初、オフチェーンでメッセージとして発行されます。
これは、実際にブロックチェーン上でトランザクションを行う前に、トークンの存在を確認してそれを用いる準備をする段階です。

#### トークンのオンチェーン具現化（Reification）
次に、スマートコントラクトを通じて、これらのオフチェーンで発行されたトークンをオンチェーンで「**具現化**」します。
具体的には、これまでメッセージとして存在していたトークンが、スマートコントラクトの呼び出しによりブロックチェーン上に正式に作成されるプロセスです。

#### トークンの再抽象化（Dereification）
トークンは、必要に応じて、再びメッセージ形式に「**再抽象化**」することができます。
これは、トークンをブロックチェーン上の具体的なアセットから、再び抽象的なメッセージへと戻すことを意味します。

### 標準との準拠

#### ERC20、ERC721、ERC1155
これらの標準は、トークンの種類（通貨、ユニークなアセット、複数アセット）に基づいて異なりますが、抽象トークンはこれらの標準に準拠しているため、既存のウォレットやアプリケーションがこれらのトークンを扱う時の互換性が保証されます。

:::message
抽象トークンの概念は、ブロックチェーン上でのトークンの柔軟な扱いを可能にするためのものです。
オフチェーンでのトークンの発行、オンチェーンでの具現化、そして再抽象化のプロセスを通じて、トークンの流動性とアクセス性を高め、ブロックチェーン技術の利用可能性を広げることが目指されています。
**ERC20**、**ERC721**、**ERC1155**などの標準との準拠により、これらの抽象トークンは既存のブロックチェーンエコシステム内で容易に統合され、広く利用されることが期待されます。
:::

## 動機

抽象トークンの概念は、特にハイボリュームアプリケーションにおいて、トークンの発行と管理のコストと複雑さを削減することを目的としています。
具体的には、トークンのオンチェーン発行（reification）をトークンホルダーのニーズに応じて行うことで、ゼロコストでのトークン発行を可能にし、エアドロップ、イベント参加証（POAPs）、アクセス資格情報などの用途に役立てます。
また、マークルツリーを用いた大規模なトークン配布では、参加者がトークンを請求する時にマークル証明を提供する必要がありますが、この新しい標準はそのような配布における請求プロセスを改善することを目指しています。

### 主な特徴

#### 汎用性（Generic）
この標準は、マークルツリー、デジタル署名、その他の証明など、さまざまな証明メカニズムと互換性があります。
これにより、トークンの配布や請求プロセスがより柔軟になります。

#### 可読性（Legible）
ユーザーは抽象トークンコントラクトを照会することで、潜在的なトークン（例えば、トークンID、数量、URIなど）について理解できます。
これにより、ユーザーが自分に関連する情報を簡単に取得し、トークンの価値や目的をよりよく把握できるようになります。

#### 包括性（Contained）
ユーザーは、特定のトークン実装コントラクトに使用されている証明メカニズムを理解する必要がありません。
これにより、ユーザーはトークンを請求するプロセスにおいて、技術的な詳細について深く理解することなく参加できます。

### 用途の例

- **エアドロップ**
    - 新しいトークンや既存トークンの無料配布を効率的に行うことができます。
- **イベント参加証（POAPs）**
    - イベントの参加証明として機能するトークンを、参加者にコストをかけずに発行できます。
- **アイデンティティ/アクセス資格情報**
    - 特定のサービスやアプリケーションへのアクセス権を示すためのトークンを、安全かつ効率的に管理できます。

### マークルツリーとの関連

マークルツリーは、トークンの大規模な配布において、発行や請求のコストを参加者に分散させるためによく使われます。
しかし、参加者がトークンを請求する時にマークル証明を提供する必要があるという点で、プロセスが複雑になる場合があります。
抽象トークンの標準は、このプロセスをユーザーフレンドリーなものにすることを目指しており、参加者がより簡単にトークンを請求できるようにすることで、大規模なトークン配布の効率性とアクセシビリティを向上させています。

## 仕様

### データタイプ

抽象トークンメッセージとその状態を管理するためのデータ構造に関する説明です。
これは、ブロックチェーン上でトークンをより柔軟に扱うためのシステムの一部として設計されています。
ここで説明されている概念は、トークンのオフチェーン発行とオンチェーンでの具現化（reification）、そしてその逆のプロセスを管理するために必要な情報を提供します。

#### 抽象トークンメッセージ構造（`AbstractTokenMessage`）

```ts
struct AbstractTokenMessage {
  uint256 chainId;
  address implementation;
  address owner;
  bytes meta;
  uint256 nonce;
  bytes proof;
}
```

- **`chainId`**
    - トークンメッセージが適用されるブロックチェーンのID。
    - これにより、メッセージが特定のチェーンと関連付けられます。
- **`implementation`**
    - トークンを具現化するためのスマートコントラクトのアドレス。
    - このコントラクトは、メッセージに基づいてトークンをオンチェーンに発行する責任を負います。
- **`owner`**
    - トークンのオーナー（所有者）のアドレス。
    - このアドレスは、トークンが具現化された際にトークンの所有権を有するアドレスです。
- **`meta`**
    - トークンを具現化するために必要な実装固有のコンテキスト。
    - これにはトークンID、数量、URIなど、トークンに関連する具体的な情報が含まれます。
- **`nonce`**
    - 複数のそうでなければ同一の抽象トークンメッセージが必要な場合にインクリメントされるカウンター。
    - これは、同じパラメータを持つメッセージを区別するために使用されます。
- **`proof`**
    - トークンを具現化するための実装固有の認証。
    - これは、メッセージの送信者がトークンを具現化する権限を持っていることを証明するために使用されます。

#### メッセージ状態列挙型（`AbstractTokenMessageStatus`）

```ts
enum AbstractTokenMessageStatus {
  invalid,
  valid,
  used
}
```

- **`invalid`**
    - スマートコントラクトがメッセージと交互に作用できない状態。
- **`valid`**
    - スマートコントラクトがメッセージと交互に作用できる状態。
- **`used`**
    - スマートコントラクトが既にメッセージと交互に作用した状態。

このシステムは、トークンのオンチェーン具現化プロセスを管理するために、トークンのオフチェーン発行からオンチェーン上での具現化、さらには使用後の状態変化までを追跡することを可能にします。
ここでのキーは柔軟性とセキュリティのバランスであり、トークンの発行と管理をより効率的かつ安全に行うための仕組みを提供しています。

### メソッド

抽象トークンの操作に関連する主要なメソッドに焦点を当てています。
このコンテキストでの「**抽象トークン**」とは、ブロックチェーン上でのトークンのオフチェーン発行、オンチェーン具現化（**reify**）、および再抽象化（**dereify**）を可能にするシステムを指します。
以下に、各メソッドの概要とその機能を説明します。

#### **reify**

- **目的**
    - メッセージ内のトークンをスマートコントラクトに移動させ、オンチェーンで具現化します。
- **動作**
    - 有効なトークンメッセージが与えられた場合、トークンコントラクトはそのメッセージに従ってトークンを具現化する必要があります。
- **冪等性**
    - 一度具現化された特定のトークンメッセージは、最大でも一度しか使用できません。
    - 既に使用されたトークンメッセージで**reify**を呼び出すと、成功するかもしれないし失敗（**revert**）するかもしれません。

#### `status`

- **目的**
    - 特定のメッセージの状態を返します。
- **戻り値**
    - メッセージの状態（無効、有効、使用済み）。

#### **dereify**

- **目的**
    - コントラクトから別のコントラクトやチェーン向けのメッセージにトークンを移動させます。
- **オプション**
    - これにより、トークンを一つのコンテキストから別のコンテキストに移動させることができます。
    - **dereify**もまた冪等である必要があります。
- **動作**
    - 特定のトークンメッセージを使用してトークンを最大で一度だけ再抽象化できます。
    - トークンメッセージが既に使用されている場合、操作は成功するかもしれないし失敗するかもしれません。

:::message
#### 冪等
冪等（べきとう）という用語は、プログラミングや情報技術の分野で使われることが多く、特に操作が複数回実行された場合でも、最初の実行以降に状態に変更を加えない性質を指します。
つまり、ある操作を1回実行した結果と、同じ操作を複数回実行した結果が同じであることを意味します。

この概念は、特にネットワーク通信やデータベース操作、APIの設計などにおいて重要です。
例えば、ウェブサーバーに対するHTTP GETリクエストは冪等であると考えられています。
なぜなら、同じリソースに対するGETリクエストを何度実行しても、サーバー上のリソースの状態を変更せず、同じレスポンスが返されるからです。
一方で、HTTP POSTリクエストは非冪等であると考えられることが多いです。
POSTリクエストはサーバー上の状態を変更する操作（例えば、データの追加）に使われるため、同じPOSTリクエストを複数回実行すると、その都度新しいデータが追加され、最終的な状態が変化します。

抽象トークンの文脈において、**reify**や**dereify**の操作が冪等であるとは、同じトークンメッセージに基づいてこれらの操作を何度実行しても、トークンの状態やシステムの状態には最初の操作以降、新たな変更は加えられないことを意味します。
例えば、あるトークンメッセージに基づいて**reify**操作を行った場合、そのトークンメッセージを使って同じトークンを再度具現化しようとしても、既にトークンは具現化されているため、新たなトークンが生成されることはありません。
これにより、操作の安全性が保たれ、予期しない重複やエラーを防ぐことができます。
:::

#### `id`

- **目的**
    - トークンメッセージで定義されたトークンのIDを返します。
- **オプション**
    - トークンIDが明確に定義されていない抽象トークンコントラクト（例：**ERC20**）は、このメソッドを実装しないか、`0`を返すことができます。

#### `amount`

- **目的**
    - トークンメッセージで定義されたトークンの量を返します。
- **オプション**
    - トークン量が明確に定義されていない抽象トークンコントラクト（例：**ERC721**）は、このメソッドを実装しないか、`0`を返すことができます。

#### `uri`

- **目的**
    - トークンメッセージで定義されたトークンのURIを返します。
- **オプション**
    - URIが明確に定義されていない抽象トークンコントラクト（例：**ERC20**）は、このメソッドを実装しないか、空文字列を返すことができます。

#### `supportsInterface`

- **要件**
    - すべての抽象トークンコントラクトは**ERC165**をサポートし、サポートされるインターフェースに抽象トークンインターフェースIDを含める必要があります。

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

[\[ERC165\] コントラクトが特定のインターフェースをサポートしているか確認する仕組みを理解しよう！](/articles/541184977a5cba51b759)

これらのメソッドと機能は、抽象トークンの管理と操作を容易にするために設計されています。
トークンのオフチェーン発行からオンチェーン上での具現化、さらには別のコントラクトやチェーンへの移動まで、これらのプロセスを効率的かつ安全に行うことができます。

### イベント

抽象トークンシステムにおけるトークンの動きを追跡するために用いられるイベントについて説明しています。
ブロックチェーン上でイベントを発行する（`emit`）ことは、特定のアクションが発生したことを外部のリスナー（例えば、フロントエンドアプリケーション、監視サービスなど）に通知する一般的な方法です。
**Reify**と**Dereify**イベントは、それぞれトークンが具現化される（オンチェーンに移動される）ときと、トークンが再抽象化される（メッセージに戻される）ときに発生します。

#### **Reify**イベント

- **目的**
    - トークンメッセージが実際のトークンに具現化される（オンチェーンに移動される）ときに発生します。
- **重要性**
    - このイベントの発行は、抽象トークンメッセージがオンチェーンのトークンに変換された正確なタイミングを捉え、外部の監視システムやユーザーインターフェイスがそのアクションを検知し、適切に反応できるようにします。

#### **Dereify**イベント

- **目的**
    - トークンが再抽象化され、特定のコントラクトやチェーン向けのメッセージに戻されるときに発生します。
- **重要性**
    - トークンが再抽象化されるプロセスを追跡することで、トークンの流動性やマルチチェーン間での移動が行われたことを外部のリスナーが把握できるようになります。
    - これは、特にディアプリケーションが異なるブロックチェーン間での資産の移動をサポートしている場合に有用です。

#### 実装上の考慮事項

- **冪等性**
    - **Reify**と**Dereify**の操作は冪等である必要があり、同じトークンメッセージに基づいて複数回操作を行っても、同じ結果が保証されます。
    - 特に**Reify**の場合、同じトークンメッセージを使ってトークンを再度具現化しようとする操作は、既に使用済みのメッセージに対しては無効とされるか、成功しない可能性があります。
- **透明性**
    - これらのイベントを通じて、トークンの動きはブロックチェーン上で完全に透明になり、トランザクションの監査やトークンの流れの追跡が容易になります。

**Reify**と**Dereify**イベントは、抽象トークンフレームワーク内での重要なアクションを示すため、開発者やユーザーにとって重要な情報源となります。
これらのイベントを適切に利用することで、アプリケーションはトークンのライフサイクルに関連する重要な変更点をリアルタイムで検知し、反応することが可能になります。

### 既存トークン規格への適用

抽象トークンが既存のトークン標準と互換性を持つためには、抽象トークンメッセージからの`transfer`を可能にするために、既存のトークン転送関数をオーバーロード（上書きまたは拡張）する必要があります。
これは、抽象トークンシステムを既存の**ERC20**、**ERC721**、**ERC1155**などの標準に適合させ、これらのトークンがオフチェーンのメッセージを介しても転送できるようにするための要件です。

#### 背景

ブロックチェーンのトークン標準（例えば、**ERC20**、**ERC721**、**ERC1155**）は、トークンの`transfer`や管理に関する一連のルールと関数を定義します。
これらの標準に従ったスマートコントラクトは、トークンの発行、`transfer`、およびその他の操作を規定した方法で実行できます。

#### 抽象トークンとの統合

抽象トークンシステムは、トークンのオフチェーン発行とオンチェーン上での具現化（**reify**）、およびその逆のプロセス（**dereify**）を可能にする新しい概念です。
このシステムを既存のトークン標準と統合するためには、これらの基本操作を拡張または上書きする必要があります。

#### 具体的な実装方法

1. **関数のオーバーロード**
    - 例えば、**ERC20**では`transfer`関数がトークンの転送を担います。
    - 抽象トークンシステムでは、`transfer`関数をオーバーロードして、抽象トークンメッセージを引数として受け取り、それに基づいてトークンを転送するロジックを追加する必要があります。

2. **抽象トークンメッセージの処理**
    - オーバーロードされた関数は、抽象トークンメッセージを解析し、適切なトークン操作（例えば、`transfer`）を実行するロジックを含む必要があります。
    - これには、メッセージの検証、トークンの所有者の特定、トークン量の確認などが含まれます。

3. **互換性の維持**
    - このプロセスでは、既存の標準に準拠したアプリケーションやウォレットが抽象トークンもサポートできるように、互換性を損なわないように注意する必要があります。
    - つまり、既存の標準に基づいた操作は引き続き機能し、抽象トークンメッセージを介した新しい形式の操作もサポートされるべきです。

:::message
抽象トークンが既存のトークン標準と互換性を持つためには、抽象トークンメッセージからトークンを`transfer`する機能を含むように、既存の`transfer`関数を拡張する必要があります。
これにより、トークンの柔軟な管理と転送が可能になり、ブロックチェーンアプリケーションの新たなユースケースをサポートできるようになります。
:::

### Abstract ERC-20

```ts
interface IAbstractERC20 is IAbstractToken, IERC20, IERC165 {
  // reify the message and then transfer tokens
  function transfer(
    address to,
    uint256 amount,
    AbstractTokenMessage calldata message
  ) external returns (bool);

  // reify the message and then transferFrom tokens
  function transferFrom(
    address from,
    address to,
    uint256 amount,
    AbstractTokenMessage calldata message
  ) external returns (bool);
}
```

#### `transfer`

```javascript
function transfer(
  address to,
  uint256 amount,
  AbstractTokenMessage calldata message
) external returns (bool);
```

**概要**

メッセージを具現化してからトークンを転送する関数。

**詳細**

この関数は、抽象トークンメッセージを受け取り、それを具現化（オンチェーン化）してから指定されたアドレスにトークンを転送します。
*ERC20*の`transfer`関数の機能を拡張し、抽象トークンメッセージを介した転送を可能にします。

**引数**

- `to`
    - トークンの受取人のアドレスです。
- `amount`
    - `transfer`するトークンの量です。
- `message`
    - 抽象トークンメッセージです。
    - このメッセージは、トークンの`transfer`に先立って具現化されます。

**戻り値**

- `bool`
    - 操作の成功または失敗を示します。

#### `transferFrom`

```javascript
function transferFrom(
  address from,
  address to,
  uint256 amount,
  AbstractTokenMessage calldata message
) external returns (bool);
```

**概要**

メッセージを具現化してから、一方のアドレスから別のアドレスへトークンを転送する関数。

**詳細**

この関数は、抽象トークンメッセージを受け取り、それを具現化（オンチェーン化）してから、一方のアドレスから別のアドレスへトークンを転送するために使用します。
**ERC20**の`transferFrom`関数の機能を拡張し、抽象トークンメッセージを介しての転送をサポートします。
この操作は通常、トークンの所有者が自分の代わりに他者がトークンを転送することを許可した場合に使用されます。

**引数**

- `from`
    - トークンの送信者のアドレスです。
- `to`
    - トークンの受取人のアドレスです。
- `amount`
    - 転送するトークンの量です。
- `message`
    - 抽象トークンメッセージです。このメッセージは、トークンの転送に先立って具現化されます。

**戻り値**

- `bool`
    - 操作の成功または失敗を示します。

### Abstract ERC-721

```ts
interface IAbstractERC721 is IAbstractToken, IERC721 {
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes calldata _data,
    AbstractTokenMessage calldata message
  ) external;

  function transferFrom(
    address from,
    address to,
    uint256 tokenId,
    AbstractTokenMessage calldata message
  ) external;
}
```

#### `safeTransferFrom`

```javascript
function safeTransferFrom(
  address from,
  address to,
  uint256 tokenId,
  bytes calldata _data,
  AbstractTokenMessage calldata message
) external;
```

**概要**

メッセージを具現化してから、トークンを安全に転送する関数。

**詳細**

この関数は、抽象トークンメッセージを使用して、特定のトークンIDを持つ**ERC721**トークンを一方のアドレスから別のアドレスへ安全に転送します。
`safeTransferFrom`は、受取人がトークンを受け入れることができるかどうかを確認する追加のチェックを提供します。
これにより、トークンがコントラクトに転送される場合、そのコントラクトが適切にトークンを処理できることを保証します。

**引数**

- `from`
    - トークンの送信者のアドレスです。
- `to`
    - トークンの受取人のアドレスです。
- `tokenId`
    - 転送されるトークンのIDです。
- `_data`
    - トークン転送とともに送信される追加データです。
    - このデータは、受取人がコントラクトの場合に、トークン受け入れロジックをトリガーするのに使用される場合があります。
- `message`
    - 抽象トークンメッセージです。
    - このメッセージは、トークンの転送に先立って具現化されます。

#### `transferFrom`

```javascript
function transferFrom(
  address from,
  address to,
  uint256 tokenId,
  AbstractTokenMessage calldata message
) external;
```

**概要**

メッセージを具現化してから、トークンを転送する関数。

**詳細**

この関数は、抽象トークンメッセージを使用して、特定のトークンIDを持つ**ERC721**トークンを一方のアドレスから別のアドレスへ転送します。
`transferFrom`は、所有者または承認されたユーザーがトークンを転送するために使用されます。
この関数は、`safeTransferFrom`と異なり、受取人がトークンを受け入れる能力をチェックしません。

**引数**

- `from`
    - トークンの送信者のアドレスです。
- `to`
    - トークンの受取人のアドレスです。
- `tokenId`
    - 転送されるトークンのIDです。
- `message`
    - 抽象トークンメッセージです。
    - このメッセージは、トークンの転送に先立って具現化されます。

### Abstract ERC-1155

```ts
interface IAbstractERC1155 is IAbstractToken, IERC1155 {
  function safeTransferFrom(
    address from,
    address to,
    uint256 id,
    uint256 amount,
    bytes calldata data,
    AbstractTokenMessage calldata message
  ) external;

  function safeBatchTransferFrom(
    address from,
    address to,
    uint256[] calldata ids,
    uint256[] calldata amounts,
    bytes calldata data,
    AbstractTokenMessage[] calldata messages
  ) external;
}
```

#### `safeTransferFrom`

```javascript
function safeTransferFrom(
  address from,
  address to,
  uint256 id,
  uint256 amount,
  bytes calldata data,
  AbstractTokenMessage calldata message
) external;
```

**概要**

メッセージを具現化してから、単一のトークンタイプを安全に転送する関数。

**詳細**

この関数は、抽象トークンメッセージを用いて、**ERC1155**に準拠したトークンの安全な転送を実現します。
転送は、指定されたトークンIDと量に基づいて行われ、転送データとメッセージを含むことができます。
この関数は、受取人がコントラクトの場合に、トークンを受け入れる能力を持つかどうかを検証します。

**引数**

- `from`
    - トークンの送信者のアドレスです。
- `to`
    - トークンの受取人のアドレスです。
- `id`
    - 転送されるトークンのIDです。
- `amount`
    - 転送されるトークンの量です。
- `data`
    - トークン転送と共に送信される追加データです。
- `message`
    - 抽象トークンメッセージです。
    - このメッセージは、トークンの転送に先立って具現化されます。

#### `safeBatchTransferFrom`

```javascript
function safeBatchTransferFrom(
  address from,
  address to,
  uint256[] calldata ids,
  uint256[] calldata amounts,
  bytes calldata data,
  AbstractTokenMessage[] calldata messages
) external;
```

**概要**

メッセージを具現化してから、複数のトークンタイプを安全に一括転送する関数。

**詳細**

この関数は、複数の抽象トークンメッセージを用いて、**ERC1155**に準拠した複数のトークンタイプを一括で安全に転送する機能を提供します。
転送は、トークンIDと量の配列に基づいて行われ、追加の転送データとメッセージの配列を含むことができます。
このバッチ処理により、複数のトークン転送を一つのトランザクションで効率的に行うことが可能になります。

**引数**

- `from`
    - トークンの送信者のアドレスです。
- `to`
    - トークンの受取人のアドレスです。
- `ids`
    - 転送されるトークンのIDの配列です。
- `amounts`
    - 各トークンIDに対応する転送されるトークンの量の配列です。
- `data`
    - トークン転送と共に送信される追加データです。
- `messages`
    - 抽象トークンメッセージの配列です。
    - これらのメッセージは、トークンの転送に先立って具現化されます。

## 補足

抽象トークンメッセージにおける「**メタデータ（meta）フィールド**」と「**証明（proof）フィールド**」の設計理念について説明します。
これらのフィールドは、抽象トークンシステムの柔軟性と将来の拡張性を確保するために、特定の方法で設計されています。

#### メタフォーマット

##### 概要

`meta`フィールドは、最も広いアクセシビリティを保持するために、単純なバイト配列として定義されています。

##### 詳細

- **アクセシビリティの確保**
    - バイト配列を使用することで、さまざまな種類のメタデータを柔軟に扱うことができます。
    - これにより、将来的に発展するトークン標準や予測できないメタデータ形式にも対応可能となります。
- **実装コントラクトとの相互作用**
    - 抽象トークンを扱うアプリケーションは、このフィールドを解析する代わりに、実装コントラクトと相互作用してトークンメタデータを取得できます。
    - このアプローチにより、`meta`フィールドの可読性は二次的な問題となります。
- **エラーチェックとデコード**
    - バイト配列は実装コントラクト内で構造体としてデコードされ、エラーのチェックが可能です。
    - これにより、様々なメタデータ形式に対応しつつ、エラー処理も適切に行えます。

#### 証明フォーマット

##### 概要

`proof`フィールドもまた、プレーンなバイト配列として定義されています。
この設計は、フィールドの内容が変動する可能性があることを考慮しています。

##### 詳細

- **内容の多様性**
    - `proof`フィールドの内容は、例えばマークルツリーのノードの配列や`65`バイトの署名など、用途に応じて変わる可能性があります。
- **全てのユースケースをカバー**
    - バイト配列を使用することで、将来的に考えられる全ての使用例をカバーできますが、これはメッセージサイズの増加という代償を伴います。

:::message
`meta`フィールドと`proof`フィールドの設計は、抽象トークンシステムの汎用性と拡張性を確保するために、バイト配列を使用しています。
これにより、さまざまなメタデータ形式や証明方法に柔軟に対応し、将来のトークン標準や新しいユースケースの出現に備えることができます。
:::

## 互換性

特に互換性に関する問題は見つかっていません。

## 実装

以下に実装コードが格納されています。

https://eips.ethereum.org/assets/eip-6604/

## セキュリティ

抽象トークンに関するセキュリティ上の懸念点を説明しています。

#### メッセージの紛失

- **問題**
    - 抽象トークンメッセージはオンチェーン上に保持されないため、メッセージの紛失はトークンの紛失につながる可能性があります。
- **対応策**
    - 抽象トークンを発行するアプリケーションは、自身でメッセージを保存することができますが、理想的にはユーザーが自分の暗号ウォレット内で抽象トークンメッセージを保存し、それと対話できるようになるべきです。

#### 具現化の認証

- **問題**
    - トークンメッセージは、有効性の証明が含まれている場合にのみ具現化（オンチェーン化）できます。
    - 証明メカニズム自体はこの標準の範囲外ですが、証明メカニズムを設計する時にはいくつかの点を考慮する必要があります。
- **考慮事項**
    - 総供給量はオンチェーンおよび/またはオフチェーンで監査する必要がありますか？
    - メカニズムは秘密（例：デジタル署名）への継続的なアクセスを必要としますか、それとも不変（例：マークル証明）ですか？
    - 攻撃者が有効なトークンメッセージの具現化を防ぐ方法はありますか？

#### 非所有者による（非）具現化

- **問題**
    - 非所有者が所有者に代わってトークンメッセージを（非）具現化できるかどうか。
- **メリット**
    - 有効なメッセージが存在する場合、所有者はいつでも（非）具現化できるため、サポートするアプリケーションはこれを処理できるべきです。
- **デメリット**
    - トークンコントラクトが使用済みメッセージの（非）具現化に対して`revert`する場合、攻撃者はトランザクションをフロントランニングすることによって所有者を悩ませる可能性があります。

#### 抽象トークンブリッジの二重支払い

- **問題**
    - 抽象トークンはトークン固有のブリッジに使用される可能性がありますが、抽象トークン標準はクロスチェーンメッセージパッシングを指定していません。
    - その結果、チェーンAとB上の抽象トークンコントラクトは、メッセージMの（非）具現化が他のチェーン上で発生したかどうかを知ることができません。
- **二重支払いの危険性**
    - 攻撃者がチェーンAで持っているトークンをチェーンBにブリッジすることを要求し、ブリッジメカニズムが抽象トークンメッセージMを作成します。
    - 攻撃者がチェーンBでメッセージMを具現化しても、チェーンAでメッセージMを非具現化しない場合、攻撃者はトークンを継続して使用できます。
- **対応策**
    - チェーンA上の対応するトークンが非具現化されるまで、チェーンBでメッセージMの具現化を防ぐために、何らかのオラクルメカニズムが必要です。

これらのセキュリティ上の考慮事項は、抽象トークンの設計と実装において重要な役割を果たします。
これらの問題を適切に管理することで、抽象トークンシステムの安全性と効率性を確保できます。

## 引用

Chris Walker (@cr-walker) <chris@ckwalker.com>, "ERC-6604: Abstract Token [DRAFT]," Ethereum Improvement Proposals, no. 6604, March 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6604.

## 最後に

今回は「**ERC20**、**ERC721**、**ERC1155**トークンをオフチェーンでのトークンの`mint`（メッセージとして）、スマートコントラクトを通じたオンチェーンへの具現化、そしてメッセージへの再抽象化を可能にする仕組みである、抽象トークンの標準インターフェースを提案している**EIP6604**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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