[ERC2400] 標準化されたトランザクションハッシュのURI形式の仕組みを理解しよう！

# はじめに

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

https://amzn.asia/d/gxvJ0Pw

今回は、Ethereumトランザクションのハッシュに関する標準化されたURI形式を定義する提案している**ERC2400**についてまとめていきます！

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

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

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

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

# 概要

通常、トランザクションハッシュ（transaction hash）は、それ自体だけでは意味を持ちません。
なぜなら、単なるハッシュ値であり、どのチェーン上のどの処理を指しているのかといった情報が欠落しているためです。

**ERC2400**で提案された標準では、トランザクションを表示するために必要な以下のすべての情報を含みます。

* チェーンID（`chainId`）
* 呼び出されたメソッドのシグネチャ
* 発行されたイベントのシグネチャ

これにより、単なるハッシュだけではわからないトランザクションの内容を、他のアプリケーションでも解釈可能にします。

# 動機

**ERC2400**の主な目的は、Ethereumクライアント間の相互運用性を向上させることです。
異なるシステムが、送信されたトランザクションハッシュを共通の形式で扱い、その詳細を理解・表示できるようにします。

また、この標準に従うことで、トランザクションの内容を復号するために必要な情報を含むURIを定義できます。

## ユースケース

この標準の活用例として、以下のような状況が挙げられます。

* **QRコード**
    * 暗号通貨の売買などで、送信されたトランザクションを示すQRコードを表示することができます。
* **ウェブリンクやハイパーリンク**
    * Webページ、Eメール、チャットメッセージなどに埋め込まれたリンクにより、ユーザーが自分の好みのExplorerで即座に内容を確認できます。
* **Web3アプリケーション**
    * DApps、マイニングプール、取引所などが、ユーザーの環境に応じて自動的にトランザクション情報を表示できます。
* **ウォレット**
    * ユーザー間でトランザクションレシートを共有しやすくなります。
* **チャットアプリケーション**
    * **ERC681**（支払いリクエスト仕様）への返信として、トランザクションの内容を直接提示できます。

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

https://qiita.com/cardene/items/87cb8429d7a2f0db7c28

# 仕様

**ERC2400**では、EthereumのトランザクションレシートをURI形式で表現するための構文とセマンティクスが定義されています。
これにより、トランザクションの情報を一意かつ標準化された形式で共有・表示できるようになります。

## 構文

トランザクションレシートのURIは、スキーマとして `"ethereum"` を使用し、以下のような形式で構成されます。

```
ethereum:tx-<transaction_hash>@<chain_id>?<parameters>
```

各要素の意味は以下の通りです。

* `transaction_hash`
  必須項目です。64桁の16進数（`0x`で始まる）で、対象トランザクションのハッシュ値を指定します。

* `chain_id`
  オプション項目です。トランザクションが属するEthereumチェーンのID（**EIP155**に準拠）を10進数で指定します。省略された場合、Mainnet（`chainId = 1`）と見なされます。

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

https://qiita.com/cardene/items/2526432899353e4a0225

* `parameters`
  任意項目で、トランザクションのメソッド呼び出しやイベントに関する情報を `key=value` 形式で列挙します。複数指定する場合は `&` で連結します。

利用可能な `key` は以下の2つです。

* `method`
  呼び出された関数のシグネチャ。例：`transfer(address,uint256)`

* `events`
  発行されたイベントのシグネチャをセミコロン `;` 区切りで列挙。例：`Transfer(!address,!address,uint256)`

※ `!` が付いた型（例：`!address`）は、indexedなイベント引数を示します。
※ 型名や関数名、イベント名は、EthereumのABI（Application Binary Interface）仕様に準拠した表記です。文字列はURLエンコードされます。

## セマンティクス

* `transaction_hash`
  必須項目です。指定された `chain_id` のブロックチェーンから該当トランザクションを検索します。見つからない場合は「トランザクションが存在しない」というエラーを返す必要があります。

* トランザクションが「未確定（pending）」である場合
  該当トランザクションがブロックに取り込まれるまで継続的に確認を行い、最終的に確定（通常12ブロック後）した時点で表示する必要があります。

* `method`
  `method` パラメータが指定されている場合、トランザクションの `calldata` の先頭4バイト（関数セレクタ）と、指定された関数シグネチャの `keccak256` ハッシュから得られる値が一致する必要があります。一致しない場合は「メソッド検証エラー」として扱います。

* `events`
  `events` パラメータが指定されていて、トランザクションが成功している場合は、ログに含まれるイベントと一致するかを検証します。指定されたイベントのいずれかが見つからなければ、「イベント検証エラー」として扱います。

※ `method` や `events` が指定されていない場合、それはトランザクションの詳細情報が不要、もしくは存在しないことを意味します。

## 使用例

* **ETH送金のシンプルなURI**

  ```
  ethereum:tx-0x1143b5e38fe3cf585fb026fb9b5ce35c85a691786397dc8a23a07a62796d8172@1
  ```

* **ERC20トークン送金**

  ```
  ethereum:tx-0x5375e805b0c6afa20daab8d37352bf09a533efb03129ba56dee869e2ce4f2f92@1?method="transfer(address,uint256)"&events="Transfer(!address,!address,uint256)"
  ```

* **複雑なコントラクト呼び出し**

  ```
  ethereum:tx-0x4465e7cce3c784f264301bfe26fc17609855305213ec74c716c7561154b76fec@1?method="issueAndActivateBounty(address,uint256,string,uint256,address,bool,address,uint256)"&events="Transfer(!address,!address,uint256);BountyIssued(uint256);ContributionAdded(uint256,!address,uint256);BountyActivated(uint256,address)"
  ```

この形式を使うことで、トランザクションの詳細を他のアプリケーションやユーザーと一貫して共有できるようになります。
特に、ウォレット、ブロックエクスプローラー、QRコード、チャットアプリなどでの連携において非常に有効です。

# 補足

**ERC2400**は、トランザクションの情報を「送信された状態で」外部に伝える手段（URI）を提供することを目的にしています。
したがって、実際のトランザクションのデータは、ブロックチェーン本体または未確定トランザクションキューから取得される必要があります。
これにより、トランザクションの存在確認（検証）も同時に行えます。

トランザクションハッシュが取得できないことは、作成されたばかりのトランザクションではよくあることであり、すぐに見つからないこともあります。
ただし、以下のようなケースも考えられます。

* トランザクションが実際には送信されていなかった
* 同じ `nonce` の別トランザクションに置き換えられた（gasPrice を上げて上書きされたなど）
* トランザクションが含まれたブロックがフォークやuncle（孤立ブロック）により無効化された

また、トランザクションの `calldata` や発行された `event` を正しく読み取るには、対応するABI（Application Binary Interface）情報が必要です。
トランザクションの署名者は、その関数やイベントを理解した上でトランザクションを生成しているため、URIにデコードに必要な情報（関数名やイベント定義）をオプションとして含めることが可能です。

これにより、受け取った側がブロックチェーンからトランザクション情報を取得する際に、対応するABIを持っていなくてもURIからデコードに必要な情報を得ることができます。

# 互換性

**ERC2400**で提案された形式（例：`ethereum:tx-...`）は、将来的に仕様が変更・拡張された場合にも対応できるように設計されています。

今後、互換性のないアップグレード（部分的または完全な非互換）が導入される場合には、`tx-` の部分を別の接頭辞に置き換えることでバージョンの識別を行います。
この接頭辞は、後続の値とハイフン（`-`）で区切る必要があります。

例えば、新しいバージョンでは `tx2-` や `receipt-` のような形式を使うことで、旧バージョンのURIとの衝突を防ぎつつ、新機能を安全に導入できます。

# 引用

Ricardo Guilherme Schmidt (@3esmit), Eric Dvorsak (@yenda), "ERC-2400: Transaction Receipt URI [DRAFT]," Ethereum Improvement Proposals, no. 2400, November 2019. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2400.

# 最後に

今回は「Ethereumトランザクションのハッシュに関する標準化されたURI形式を定義する提案している**ERC2400**」についてまとめてきました！
いかがだったでしょうか？

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