はじめに

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

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください!

今回は「Web3 URL to EVM Call Message Translation」についてまとめていきます。

Web3://プロトコルを使用して、ブラウザから直接EVMのスマートコントラクトにアクセスし、HTML/CSS/画像などのオンチェーンコンテンツを取得できるようにする仕組みを提案しているERC6860についてまとめていきます!

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

概要

ERC6860とは、HTTPスタイルのWeb3 URL(例: web3://uniswap.eth/)をEVMのCall Messageに変換するプロトコルのことです。 RFC 3986に準拠したURIをEVMメッセージに変換し、宛先アドレスとcalldataパラメータを指定します。

この規格はERC4804の更新版であり、いくつかの修正と明確化が加えられています。

ERC4804については以下の記事を参考にしてください。

Web3 URLを使用することで、dAppウェブサイトやノードサービスプロバイダーなどのWeb2プロキシに依存せず、ユーザーが直接オンチェーンコンテンツにアクセスできるようになります。

対応するコンテンツタイプはHTML、CSS、JavaScript、SVG、PNG、JPGなど、Webで一般的に使用されるあらゆる形式をサポートしています。 これにより、EVMを分散型バックエンドとして使用し、完全にオンチェーンでホストされたWebサイトを実現できます。

動機

この提案が生まれた背景には以下のような課題がありました。

Web2プロキシへの依存

現在、Web3からデータを読み取る際は、通常Web2プロキシによる変換に依存しています。 この変換は主にdAppウェブサイト、ノードサービスプロバイダー、Etherscanなどのプロキシによって行われており、ユーザーのコントロール外にあります。

この中央集権的な依存関係は、Web3の分散化という理念に反しています。 プロキシがダウンしたり、検閲されたり、不正な情報を提供したりするリスクがあります。

オンチェーンコンテンツへの直接アクセス

ERC6860は、Web2ユーザーがWeb3コンテンツに直接アクセスするためのシンプルな方法を提供することを目的としています。 特にSVGやHTMLなどのオンチェーンWebコンテンツに対して、人間が読みやすいURL形式でアクセスできるようになります。

既存のURI標準(RFC 3986)との互換性を維持しながら、ENS(Ethereum Name Service)などのドメイン名解決と統合することで、web3://uniswap.eth/のような直感的なURLでスマートコントラクトにアクセスできます。

仕様

URL構造

Web3 URLの基本構文は以下の通りです。

text
web3URL = schema "://" [ userinfo "@" ] contractName [ ":" chainid ] pathQuery [ "#" fragment ]

各コンポーネントの詳細は以下です。

コンポーネント 必須 説明
schema 必須 "w3"または"web3"
userinfo 任意 送信者アドレス。省略時は0x0
contractName 必須 Ethereumアドレス(0x...)またはENSドメイン名
chainid 任意 ネットワーク識別子。省略時はメインネット(1)
pathQuery 必須 パスとオプションのクエリパラメータ
fragment 任意 参照文字列。スマートコントラクトには送信されない

Web3 URLの例は以下です。

text
web3://uniswap.eth/
web3://cyberbrokers-meta.eth/renderBroker/9999
web3://vitalikblog.eth:5/
web3://0x1234...abcd:11155111/tokenURI/1?returns=(string)

最初の例はENSドメインを使用したシンプルなアクセスです。 2番目の例はメソッド呼び出しと引数を含んでいます。 3番目の例はチェーンIDを明示的に指定しています。 4番目の例は直接アドレスを使用し、戻り値の型を指定しています。

resolveモードの決定

コントラクトはresolveMode()関数を実装することで、URLの解釈方法を指定できます。 この関数はbytes32値を返します。

resolveMode()関数の定義は以下です。

javascript
function resolveMode() external returns (bytes32);

この関数は、コントラクトがWeb3 URLをどのように処理するかを決定します。

戻り値とモードの対応は以下です。

戻り値 モード 説明
"manual"(0x6d616e75616c...) マニュアルモード pathQueryがそのままcalldataになる
"auto"(0x6175746f...)、ゼロ、未実装 オートモード Solidity ABIとして解釈される
その他 エラー リクエストが失敗する

マニュアルモード

マニュアルモードでは、pathQueryのバイトがそのままcalldataとして使用されます。 パーセントエンコーディングのデコードは行われません。 pathQueryが空の場合、calldataはデフォルトで"/"(0x2f)になります。

マニュアルモードの構文は以下です。

text
mPath = [ *( "/" segment ) "/" segment [ "." fileExtension ] ]
mQuery = *( pchar / "/" / "?" )

戻り値の処理

マニュアルモードでは、戻り値はABIエンコードされたbytesとして扱われ、フロントエンドに配信される前にデコードされます。 MIMEタイプはファイル拡張子によって決定され、拡張子がない場合はtext/htmlがデフォルトとなります。

例えば、web3://example.eth/image.pngの場合、MIMEタイプはimage/pngとして解釈されます。

オートモード

オートモードでは、pathQueryが標準的なSolidity ABIとして解釈されます。 これにより、人間が読みやすいメソッド呼び出しが可能になります。

パス構造

オートモードのパス構造は以下です。

text
aPath = [ "/" [ method *( "/" argument ) ] ]

methodはSolidityの関数名で、argumentはその引数です。 引数は"/"で区切られます。

サポートされる引数の型

オートモードでサポートされる引数の型は以下です。

型 形式 例
bool "true"または"false" true
uint/uint<X> 10進数(X: 8-256) 123
int/int<X> 符号付き10進数 -456
address 0xプレフィックス付き20バイト16進数またはドメイン名 0x1234...またはvitalik.eth
bytes/bytes<X> 0xプレフィックス付き16進数(X: 1-32) 0xabcd...
string テキスト(オプションでファイル拡張子付き) hello.txt

型の自動検出

型が明示的に指定されていない場合、以下の順序で自動検出されます。

優先順位 入力パターン 解釈される型
1 10進数のみ uint256
2 32バイトの16進数(0x...) bytes32
3 20バイトの16進数(0x...) address
4 その他の16進数 bytes
5 "true"または"false" bool
6 それ以外 address(ドメイン名として解析)

検出は優先順位の高い順に行われ、最初にマッチしたパターンの型が適用されます。

使用例

オートモードの使用例は以下です。

text
web3://cyberbrokers-meta.eth/renderBroker/9999

この例では、cyberbrokers-meta.ethコントラクトのrenderBroker関数を引数9999で呼び出します。 9999は自動的にuint256として解釈されます。

戻り値の処理

オートモードでは、クエリパラメータで戻り値の処理方法を指定できます。

クエリパラメータ 動作
returns属性なし ABIデコードされたbytesが返される。MIMEタイプは最終引数がファイル拡張子付きstringの場合のみ決定される
returns=() JSON配列形式の生の16進文字列が返される
returns=(types) 指定された型に従ってABIデコードされ、JSON-RPC形式で返される

戻り値の処理例は以下です。

text
web3://0x1234.../balanceOf/vitalik.eth?returns=(uint256)

この例では、balanceOf関数の戻り値がuint256として解釈され、JSON-RPC形式(0xプレフィックス付き16進数)で返されます。

JSON-RPC形式では、整数は16進文字列として、ブール値とstringはネイティブのJSON形式として返されます。

実践的な使用例

Web3 URLの具体的な使用例を詳しく見ていきます。

基本的なコントラクトアクセス

最もシンプルな例として、web3://w3url.eth/があります。

text
web3://w3url.eth/

このURLにアクセスすると、まずw3url.ethがENSで解決されてコントラクトアドレスが取得されます。 次にresolveMode()が呼び出され、コントラクトがマニュアルモードかオートモードかが判定されます。 パスが空("/"のみ)のため、デフォルトのコンテンツが返されます。

NFTメタデータの取得

NFTプロジェクトのメタデータを取得する例は以下です。

text
web3://cyberbrokers-meta.eth/renderBroker/9999

この例では、cyberbrokers-meta.ethコントラクトのrenderBroker関数をトークンID 9999 で呼び出しています。 引数9999は数字のみで構成されているため、自動的にuint256として解釈されます。 戻り値はABIエンコードされたbytesとして返され、通常はSVGやJSONなどのメタデータが含まれています。

別チェーンへのアクセス

メインネット以外のチェーンにアクセスする場合は、チェーンIDを明示的に指定します。

text
web3://vitalikblog.eth:5/

この例では、:5でGoerliテストネット(チェーンID 5)を指定しています。 ENSドメインの解決もGoerliネットワーク上で行われます。

戻り値の型指定

ERC20トークンの残高を取得する例は以下です。

text
web3://0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/balanceOf/vitalik.eth?returns=(uint256)

このURLは、USDCコントラクト(0xA0b86991...)のbalanceOf関数をvitalik.ethを引数として呼び出しています。 vitalik.ethはaddress型の引数としてENSで解決され、コントラクトアドレスに変換されます。 ?returns=(uint256)により、戻り値がuint256として解釈され、JSON-RPC形式("0x..." の16進文字列)で返されます。

複数の戻り値

複数の戻り値を持つ関数の場合は、括弧内に複数の型をカンマ区切りで指定します。

text
web3://example.eth/getInfo/1?returns=(string,uint256,bool)

この例では、3つの戻り値(string、uint256、bool)が期待されています。 結果はJSON配列として返され、各要素がそれぞれの型に応じたJSON形式で表現されます。

補足

ABNF文法

ERC6860では、Web3 URLの完全な構文をABNF(Augmented Backus-Naur Form)で定義しています。 ABNFはインターネット標準で広く使用される文法記法で、RFC 5234で定義されています。

主要な文法定義は以下です。

text
web3URL = schema "://" [ userinfo "@" ] contractName [ ":" chainid ] pathQuery [ "#" fragment ]
schema = "w3" / "web3"
userinfo = address
contractName = address / domainName
chainid = 1*DIGIT

このベース構文は、すべてのWeb3 URLに適用されます。 schemaは"w3"または"web3"のいずれかで、contractNameはEthereumアドレスまたはENSなどのドメイン名を指定します。

マニュアルモードのパス構文は以下のように定義されています。

text
mPathQuery = mPath [ "?" mQuery ]
mPath = [ *( "/" segment ) "/" segment [ "." fileExtension ] ]
mQuery = *( pchar / "/" / "?" )
fileExtension = 1*( ALPHA / DIGIT )

マニュアルモードでは、パスがそのままcalldataとして使用されるため、任意のセグメント構造が許可されます。 ファイル拡張子(.html、.pngなど)はMIMEタイプの決定に使用されます。

オートモードのパス構文は以下のように定義されています。

text
aPath = [ "/" [ method *( "/" argument ) ] ]
method = ALPHA *( ALPHA / DIGIT )
argument = boolArg / uintArg / intArg / addressArg / bytesArg / stringArg

オートモードでは、メソッド名と引数がスラッシュで区切られた構造を持ちます。 各引数は型に応じたフォーマットで記述されます。

戻り値の型指定構文は以下です。

text
aQuery = "?" "returns" "=" "(" [ retTypes ] ")"
retTypes = retType *( "," retType )
retType = "(" retTypes ")" / "bool" / "uint" [ "8" / "16" / ... / "256" ] / "int" [ "8" / ... ] / "address" / "bytes" [ "1" / ... / "32" ] / "string"

returnsパラメータにより、クライアントは期待する戻り値の型を明示的に指定できます。 これにより、コントラクトからの生のバイトデータが適切にデコードされ、JSON形式で返されます。

設計原則

ERC6860は4つのコア原則に基づいて設計されています。

人間可読性として、生のアドレスの代わりにENS名を使用し、16進数のcalldataの代わりにメソッド構文を使用します。 これにより、HTTP URLに慣れているユーザーの期待に応えます。

HTTP互換性として、相対パス、クエリ文字列、フラグメント、パーセントエンコーディングなどのURL規約を踏襲し、ブラウザとの統合を容易にしています。

シンプルさとして、自動型検出によりURL長を最小化しつつ、必要に応じて明示的な型指定もサポートしています。

柔軟性として、コントラクトがエンコーディングの解釈を制御できるため、リソースの場所をきめ細かくカスタマイズできます。

ドメイン名解決

contractNameがドメイン名の場合、以下の手順で解決されます。

  1. ENS(Ethereum Name Service)を使用してドメイン名を解決
  2. チェーンIDが指定されていない場合はメインネット(chainid=1)を使用
  3. 解決されたアドレスに対してEVMメッセージを送信

例えば、web3://uniswap.eth/は、まずENSでuniswap.ethを解決し、そのアドレスに対してCall Messageを送信します。

スコープ

この仕様は読み取り専用(Solidityのview関数)のセマンティクスのみを定義しています。 状態を変更する関数は、将来の拡張として定義される可能性があります。

後方互換性

ERC6860はERC4804を明示的に置き換えます。 主な変更点は以下です。

項目 ERC4804 ERC6860
プロトコル名 "ethereum-web3://"、"eth-web3://"を含む 削除。"web3://"と"w3://"のみ
オートモードの戻り値型 bytes32として扱う bytesとして扱う
サポートする型 uint256、bytes32、address、bytes、string int8-int256、uint8-uint256、bytes1-bytes32を追加
整数のエンコーディング 文字列表現 JSON-RPC形式(0xプレフィックス付き16進数)
マニュアルモードのパス解釈 解釈なし ファイル拡張子に基づくMIMEタイプ決定

これらの変更により、より広範な型のサポートと、JSON-RPC標準との一貫性が実現されています。

セキュリティ

ERC6860の仕様ドキュメントでは、セキュリティに関する特別な考慮事項は記載されていません。

ただし、一般的なWeb3アプリケーションと同様に、以下の点に注意することが推奨されます。

コントラクトの信頼性として、アクセスするコントラクトが信頼できるものであることを確認する必要があります。 悪意のあるコントラクトは、不正なコンテンツを返す可能性があります。

ENS解決の信頼性として、ENSドメインの所有者が変わった場合、異なるコントラクトにリダイレクトされる可能性があります。

引用

最後に

今回は「Web3 URL to EVM Call Message Translation」についてまとめてきました。