はじめに

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

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

今回は、HTTPスタイルのWeb3URLをEVM呼び出しメッセージに変換する仕組みを提案しているERC6860についてまとめていきます!

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

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

概要

この規格では、RFC3986をweb3://uniswap.eth/のようなEVMメッセージに変換する仕組みを提案しています。

js
EVMMessage {
   To: 0xaabbccddee.... // where uniswap.eth's address registered at ENS
   Calldata: 0x
   ...
}

RFC3986は、Uniform Resource Identifier (URI)の構文に関する標準を定めたものです。 URIはインターネット上のリソースを識別するために使用されます。

主な内容

URIは5つの部分で構成されます。

  • スキーム (scheme)
    • リソースへのアクセス方法を指定。
    • 例
      • http, https, ftp
  • 認証情報 (authority)
    • ホスト名やユーザー情報を含む。
    • 例
      • //user:pass@host:port
  • パス (path)
    • リソースの位置を示す。
    • 例
      • /path/to/resource
  • クエリ (query)
    • リソースへの追加情報を提供。
    • 例
      • ?key1=value1&key2=value2
  • フラグメント (fragment)
    • リソース内の特定の部分を指す。
    • 例
      • #section1

スキームはアルファベットで始まり、アルファベット、数字、プラス(+)、ドット(.)、ハイフン(-)を含むことができます。 また、特殊文字はエンコードする(例: スペースは%20にエンコード。)必要があります。 相対URI(ベースURIからの相対パスで指定されるURI)やURIの正規化(URIを比較するために標準形式に変換するプロセス)などの特徴もあります。

具体例

https://example.com:8080/path/to/resource?query=123#section2

  • スキーム
    • https
  • 認証情報
    • example.com:8080
  • パス
    • /path/to/resource
  • クエリ
    • query=123
  • フラグメント
    • section2

この規格は、ERC4804にに若干の変更を加えた提案になります。

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

動機

Web3のデータを読み取るとき、通常RPCノードやEtherscan、DappsなどのWeb2プロキシを介してブロックチェーンにアクセスする必要があります。 Web2ユーザーがWeb3コンテンツに直接アクセスすることは難しく、プロキシを介してアクセスすることがほとんどです。 この規格では、Web2ユーザーがプロキシを介さずに直接Web3コンテンツにアクセスできる方法を提供します。 特にオンチェーンにSVGやHTML、メタデータなどのコンテンツが保存されているときこの規格が役に立ちます。 SVGやHTMLなどのURIに互換性のある標準との相互運用性を可能にし、Web3コンテンツを既存のWeb2インフラストラクチャとシームレスに統合することができます。

仕様

この規格では、RFC2234というプロトコルやデータ形式の構文を正確に定義するAugmented Backus-Naur Form (ABNF)を使用しています。

RFC2234は、Augmented BNF for Syntax Specifications(ABNF)というデータ形式やプロトコルの構文を正確に記述するために使用される形式について定義しています。

基本情報

ABNFはネットワークプロトコルやデータ形式の構文を記述するための標準的な形式を提案しています。

基本構造
  • 規則(Rule)
    • ABNFは、名前付きの規則(ルール)を使って構文を記述します。
    • 例
      • rule = definition
  • リテラル(Literal)
    • 文字列や文字を直接表現します。
    • 例
      • "text"
  • オルタネーション(Alternation)
    • 複数の選択肢を示します。
    • 例
      • rule1 / rule2
  • 連接(Concatenation)
    • シーケンスを示します。
    • 例
      • rule1 rule2
記号の使用
  • コロン(=)
    • 規則の定義を示す。
  • 斜線(/)
    • 選択肢の区切りを示す。
  • 括弧(())
    • グループ化を示す。
  • 角括弧([])
    • オプションを示す。
  • アスタリスク(*)
    • 繰り返しを示す。
データ型
  • 数字
    • 数字を使って範囲や回数を指定します。
    • 例
      • DIGIT = %x30-39(0から9の数字)
  • 文字
    • 文字の範囲を指定します。
    • 例
      • ALPHA = %x41-5A / %x61-7A(AからZおよびaからz)

具体例

text
URI           = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
scheme        = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
hier-part     = "//" authority path-abempty

この例では、URIの構文を記述しています。

  • URI
    • scheme、hier-part、query、fragmentの組み合わせ。
  • scheme
    • アルファベットで始まり、アルファベット、数字、+、-、.の組み合わせ。
  • hier-part
    • authorityとpath-abemptyの組み合わせ。

Web3 URLは以下の形式を持つASCII文字列です。

plaintext
web3URL = schema "://" [ userinfo "@" ] contractName [ ":" chainid ] pathQuery
  • schema
    • スキーム部分は"w3"または"web3"です。
    • この部分はURLがWeb3 URLであることを示します。
plaintext
schema = "w3" / "web3"
  • userinfo
    • userinfoはアドレスを表し、EVMコールメッセージの「from」フィールドに相当します。
    • 指定されていない場合、プロトコルは送信者アドレスとして0x0を使用します。
plaintext
userinfo = address
  • contractName
    • コントラクト名を指定し、EVMコールメッセージの「to」フィールドに相当します。
    • これはアドレスまたはドメイン名です。
    • ドメイン名の場合、それは名前解決サービス(例:Ethereum Name Service)を通じてアドレスに解決されます。
plaintext
contractName = address / domainName
address = "0x" 20( HEXDIG HEXDIG )
domainName = *( unreserved / pct-encoded / sub-delims )
  • chainid
    • チェーンIDを指定し、どのブロックチェーン上でcontractNameを解決してメッセージを送信するかを決定します。
    • 指定されていない場合、プロトコルは名前サービスプロバイダーの主要チェーン(例:Ethereumの場合は1)を使用します。
plaintext
chainid = %x31-39 *DIGIT
  • pathQuery
    • パスとオプションのクエリからなり、手動モード(manual mode)または自動モード(auto mode)によって構造が異なります。
plaintext
pathQuery = mPathQuery / aPathQuery

相対URL

Web3 URLは相対URLをサポートしており、Resolveモードによってサポートの方法が異なります。

plaintext
web3UrlRef = web3URL / relativeWeb3URL
relativeWeb3URL = relPathQuery
relPathQuery = relMPathQuery / relAPathQuery

具体例

例えば、以下のWeb3 URLを考えます。

plaintext
web3://0x1234567890abcdef1234567890abcdef12345678@0xabcdef1234567890abcdef1234567890abcdef12:1/path/to/resource?query=param
  • schema
    • web3
  • userinfo
    • 0x1234567890abcdef1234567890abcdef12345678(EVMコールメッセージの送信者)
  • contractName
    • 0xabcdef1234567890abcdef1234567890abcdef12(スマートコントラクトのアドレス)
  • chainid
    • 1(Ethereumメインネット)
  • pathQuery
    • /path/to/resource?query=param(リソースのパスとクエリ)

Resolveモード

Resolveモードには、手動モード(manual mode)と自動モード(auto mode)の2つがあります。

Resolveモードの確認方法

プロトコルは、「too」アドレスのresolveModeメソッドを呼び出すことでResolveモードを確認します。 このメソッドのSolidity署名は以下の通りです。

js
function resolveMode() external returns (bytes32);

サポートされているResolveモード

手動モード(manual mode)

resolveModeの戻り値が以下の値と一致する場合に手動モードが使用されます。

bash
0x6d616e75616c0000000000000000000000000000000000000000000000000000

これは、"manual"をbytes32形式にエンコードしたものです。

自動モード(auto mode)

resolveModeの戻り値が以下のいずれかと一致する場合に自動モードが使用されます。

plaintext
0x6175746f00000000000000000000000000000000000000000000000000000000

これは、"auto"をbytes32形式にエンコードしたものです。 または、戻り値が以下の場合も自動モードが使用されます。

plaintext
0x0000000000000000000000000000000000000000000000000000000000000000

さらに、resolveModeメソッドの呼び出しがエラーを投げる(メソッドが実装されていないか、メソッド内でエラーが発生する)場合も自動モードが使用されます。

その他のモード

上記に該当しない戻り値を返した場合、プロトコルはリクエストを失敗させ、「unsupported resolve mode」というエラーを返します。

手動モード

手動モードでは、mPathQueryとして指定された生のデータがメッセージのコールデータとして直接使用されます。

手動モードの構造

mPathQuery

手動モードのmPathQueryは以下のように定義されます。

plaintext
mPathQuery = mPath [ "?" mQuery ]
mPath

mPathはmPathAbemptyで、スラッシュ/で始まるか空である必要があります。

plaintext
mPath = mPathAbempty ; begins with "/" or is empty

mPathAbemptyは、セグメントの繰り返しとオプションのファイル拡張子からなります。

plaintext
mPathAbempty = [ *( "/" segment ) "/" segment [ "." fileExtension ] ]
segment = *pchar ; as in RFC 3986
fileExtension = 1*( ALPHA / DIGIT )

segmentは任意の文字列で、fileExtensionはアルファベットまたは数字の繰り返しです。

mQuery

mQueryは、RFC3986に準拠した任意の文字列です。

plaintext
mQuery = *( pchar / "/" / "?" ) ; as in RFC 3986

手動モードの動作

mPathQueryが空の場合、送信されるコールデータは/(0x2f)になります。 返されたメッセージデータはABIエンコードされたバイト列として扱われ、デコードされたバイト列がフロントエンドに返されます。 フロントエンドに返されるMIMEタイプはデフォルトでtext/htmlですが、ファイル拡張子が存在する場合、そのファイル拡張子からMIMEタイプが推定されます。

相対URLのサポート

手動モードでは、HTTP URLに似た相対URLもサポートされています。

relMPathQuery

相対URLの構造は以下の通りです。

plaintext
relMPathQuery = relMPath [ "?" mQuery ]
relMPath

relMPathは、絶対パスmPathAbsolute、非スキームパスmPathNoscheme、空のパスmPathEmptyから構成されます。

plaintext
relMPath = mPathAbsolute ; begins with "/" but not "//"
          / mPathNoscheme ; begins with a non-colon segment
          / mPathEmpty    ; zero characters

mPathAbsoluteはスラッシュで始まり、オプションのファイル拡張子を持つことができます。

plaintext
mPathAbsolute = "/" [ segmentNz *( "/" segment ) ] [ "." fileExtension ]

mPathNoschemeはコロン(:)を含まないセグメントで始まり、オプションのファイル拡張子を持つことができます。

plaintext
mPathNoscheme = segmentNzNc *( "/" segment ) [ "." fileExtension ]
segmentNzNc = 1*( unreserved / pct-encoded / sub-delims / "@" )

mPathEmptyは空の文字列です。

plaintext
mPathEmpty = 0<pchar>

自動モード

このセクションは、Web3 URLの自動モード(Auto Mode)について説明しています。自動モードでは、関数の呼び出し方法と引数の指定方法が定義されています。これにより、ユーザーは特定のスマートコントラクトの関数を呼び出し、結果を取得することができます。

自動モードの構造

aPathQuery

自動モードのaPathQueryは、以下のように定義されます。

plaintext
aPathQuery = aPath [ "?" aQuery ]
aPath

aPathは、関数メソッドと引数を含むオプションのパスです。 空またはスラッシュ/だけの場合、ターゲットコントラクトは空のコールデータで呼び出されます。 それ以外の場合、標準のSolidityコントラクトABIが使用されます。

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

methodは、呼び出す関数の名前を示す文字列です。

plaintext
method = ( ALPHA / "$" / "_" ) *( ALPHA / DIGIT / "$" / "_" )
argument

argumentは、関数メソッドの引数を示します。

plaintext
argument = boolArg / uintArg / intArg / addressArg / bytesArg / stringArg
  • boolArg
    • 真偽値を示す引数。
plaintext
boolArg = [ "bool!" ] ( "true" / "false" )
  • uintArg
    • 符号なし整数を示す引数。
plaintext
uintArg = [ "uint" [ intSizes ] "!" ] 1*DIGIT
  • intArg
    • 符号付き整数を示す引数。
plaintext
intArg = "int" [ intSizes ] "!" 1*DIGIT
  • addressArg
    • アドレスを示す引数。
plaintext
addressArg = [ "address!" ] ( address / domainName )
  • bytesArg
    • バイト列を示す引数。
plaintext
bytesArg = [ "bytes!" ] bytes / "bytes1!0x" 1( HEXDIG HEXDIG ) / ... / "bytes32!0x" 32( HEXDIG HEXDIG )
  • stringArg
    • 文字列を示す引数。
plaintext
stringArg = "string!" *pchar [ "." fileExtension ]
自動型検出

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

  • 数字の場合
    • uint256
  • 32バイトのデータの場合
    • bytes32
  • 20バイトのデータの場合
    • address
  • それ以外のバイトデータの場合
    • bytes
  • trueまたはfalseの場合
    • bool
  • 上記以外の場合
    • addressとしてドメイン名を解釈し、解決できなければエラーを返します。
aQuery

クエリ部分は、返されるデータの形式を指定します。

plaintext
aQuery = attribute *( "&" attribute )
  • attribute
    • returns属性は、返されるデータの形式を指定します。
plaintext
attribute = attrName "=" attrValue
attrName = "returns" / "returnTypes"
attrValue = [ "(" [ retTypes ] ")" ]
retTypes = retType *( "," retType )
retType = retRawType *( "[" [ %x31-39 *DIGIT ] "]" )
retRawType = "(" retTypes ")" / retBaseType
retBaseType = "bool" / "uint" [ intSizes ] / "int" [ intSize ] / "address" / "bytes" [ bytesSizes ] / "string"
返されるデータ

returns属性が未定義または空の場合、返されるメッセージデータはABIエンコードされたバイト列として扱われます。 returns属性が()の場合、返されるデータは生のバイト列としてJSON配列にエンコードされます。 その他の場合、returns属性のデータ型に従ってABIデコードされ、JSON形式でエンコードされます。

相対URLのサポート

自動モードでは、相対URLは現在のコントラクトに対して相対的に解決され、自己参照、/パス、または完全なメソッドと引数を参照できます。

例

Example 1a

bash
# 手動モード
web3://w3url.eth/
  1. ENSを使ってw3url.ethのアドレスを取得します(チェーンIDは1、つまりMainnet)。
  2. resolveMode()メソッドを呼び出して、0xDD473FAEをcalldataとして送信し、戻り値がmanualであることを確認します。
  3. コントラクトにToアドレスを指定し、calldataとして0x2F(スラッシュ/)を送信します。
  4. 返されたデータはABIエンコードされたバイトとして処理され、フロントエンドに返されます。
    • MIMEタイプはデフォルトでtext/htmlです。

Example 1b

bash
# 自動モード
web3://w3url.eth/
  1. ENSを使ってw3url.ethのアドレスを取得します(チェーンIDは1、つまりMainnet)。
  2. resolveMode()メソッドを呼び出して、0xDD473FAEをcalldataとして送信し、戻り値が空であることを確認します(自動モード)。
  3. コントラクトにToアドレスを指定し、空のcalldataで呼び出します。
  4. 返されたデータはABIエンコードされたバイトとして処理され、フロントエンドに返されます。
    • MIMEタイプは未定義です。

Example 2

text
# 自動モード
web3://cyberbrokers-meta.eth/renderBroker/9999
  1. ENSを使ってcyberbrokers-meta.ethのアドレスを取得します(チェーンIDは1、つまりMainnet)。
  2. resolveMode()メソッドを呼び出して、0xDD473FAEをcalldataとして送信し、戻り値が空であることを確認します(自動モード)。
  3. コントラクトにToアドレスを指定し、calldataとして0x + keccak("renderBroker(uint256)")[0:4] + abi.encode(uint256(9999))を送信します。
  4. 返されたデータはABIエンコードされたバイトとして処理され、フロントエンドに返されます。
    • MIMEタイプは未定義です。

Example 3

bash
# 手動モード
web3://vitalikblog.eth:5/
  1. ENSを使ってvitalikblog.ethのアドレスを取得します(チェーンIDは5、つまりGoerli)。
  2. resolveMode()メソッドを呼び出して、手動モードであることを確認します。
  3. コントラクトにToアドレスを指定し、calldataとして0x2F(スラッシュ/)を送信します。
  4. 返されたデータはABIエンコードされたバイトとして処理され、フロントエンドに返されます。
    • MIMEタイプはtext/htmlです。

Example 4

bash
# 手動モード
web3://0xe4ba0e245436b737468c206ab5c8f4950597ab7f:42170/
  1. resolveMode()メソッドを呼び出して、手動モードであることを確認します。
  2. コントラクトにToアドレス(0xe4ba0e245436b737468c206ab5c8f4950597ab7f)を指定し、calldataとして0x2F(スラッシュ/)を送信します(チェーンIDは42170、つまりArbitrum Nova)。
  3. 返されたデータはABIエンコードされたバイトとして処理され、フロントエンドに返されます。
    • MIMEタイプはtext/htmlです。

Example 5

bash
# 自動モード
web3://0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/balanceOf/vitalik.eth?returns=(uint256)
  1. ENSを使ってvitalik.ethのアドレスを取得します(チェーンIDは1、つまりMainnet)。
  2. コントラクトのbalanceOf(address)メソッドをvitalik.ethのアドレスで呼び出します。
  3. 返されたデータはABIエンコードされたuint256型として処理され、JSON形式でフロントエンドに返されます。MIMEタイプはapplication/jsonです。

Example 6

bash
# 自動モード
web3://0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/balanceOf/vitalik.eth?returns=()
  1. ENSを使ってvitalik.ethのアドレスを取得します(チェーンIDは1、つまりMainnet)。
  2. コントラクトのbalanceOf(address)メソッドをvitalik.ethのアドレスで呼び出します。
  3. 返されたデータは生のバイト列として処理され、JSON形式でフロントエンドに返されます。
    • MIMEタイプはapplication/jsonです。

Web3URLの完全なABNF

Web3URLの完全なABNFを開く
bash
web3URL         = schema "://" [ userinfo "@" ] contractName [ ":" chainid ] pathQuery
schema          = "w3" / "web3"
userinfo        = address
contractName    = address 
                / domainName
chainid         = %x31-39 *DIGIT

pathQuery       = mPathQuery ; path+query for manual mode
                / aPathQuery ; path+query for auto mode

web3UrlRef      = web3URL 
                / relativeWeb3URL
relativeWeb3URL = relPathQuery
relPathQuery    = relMPathQuery ; Relative URL path+query for manual mode
                / relAPathQuery ; Relative URL path+query for auto mode

mPathQuery      = mPath [ "?" mQuery ]
mPath           = mPathAbempty ; begins with "/" or is empty

relMPathQuery   = relMPath [ "?" mQuery ]
relMPath        = mPathAbsolute ; begins with "/" but not "//"
                / mPathNoscheme ; begins with a non-colon segment
                / mPathEmpty    ; zero characters

mPathAbempty    = [ *( "/" segment ) "/" segment [ "." fileExtension ] ]
mPathAbsolute   = "/" [ segmentNz *( "/" segment ) ] [ "." fileExtension ]
mPathNoscheme   = segmentNzNc *( "/" segment ) [ "." fileExtension ]
mPathEmpty      = 0<pchar>

segment         = *pchar ; as in RFC 3986
segmentNz       = 1*pchar ; as in RFC 3986
segmentNzNc     = 1*( unreserved / pct-encoded / sub-delims / "@" )
                ; as in RFC 3986: non-zero-length segment without any colon ":"

mQuery          = *( pchar / "/" / "?" ) ; as in RFC 3986

aPathQuery      = aPath [ "?" aQuery ]
aPath           = [ "/" [ method *( "/" argument ) ] ]
relAPathQuery   = aPath [ "?" aQuery ]
method          = ( ALPHA / "$" / "_" ) *( ALPHA / DIGIT / "$" / "_" )
argument        = boolArg
                / uintArg
                / intArg
                / addressArg
                / bytesArg
                / stringArg
boolArg         = [ "bool!" ] ( "true" / "false" )
uintArg         = [ "uint" [ intSizes ] "!" ] 1*DIGIT
intArg          = "int" [ intSizes ] "!" 1*DIGIT
intSizes        = "8" / "16" / "24" / "32" / "40" / "48" / "56" / "64" / "72" / "80" / "88" / "96" / "104" / "112" / "120" / "128" / "136" / "144" / "152" / "160" / "168" / "176" / "184" / "192" / "200" / "208" / "216" / "224" / "232" / "240" / "248" / "256"
addressArg      = [ "address!" ] ( address / domainName )
bytesArg        = [ "bytes!" ] bytes
                / "bytes1!0x" 1( HEXDIG HEXDIG )
                / "bytes2!0x" 2( HEXDIG HEXDIG )
                / "bytes3!0x" 3( HEXDIG HEXDIG )
                / "bytes4!0x" 4( HEXDIG HEXDIG )
                / "bytes5!0x" 5( HEXDIG HEXDIG )
                / "bytes6!0x" 6( HEXDIG HEXDIG )
                / "bytes7!0x" 7( HEXDIG HEXDIG )
                / "bytes8!0x" 8( HEXDIG HEXDIG )
                / "bytes9!0x" 9( HEXDIG HEXDIG )
                / "bytes10!0x" 10( HEXDIG HEXDIG )
                / "bytes11!0x" 11( HEXDIG HEXDIG )
                / "bytes12!0x" 12( HEXDIG HEXDIG )
                / "bytes13!0x" 13( HEXDIG HEXDIG )
                / "bytes14!0x" 14( HEXDIG HEXDIG )
                / "bytes15!0x" 15( HEXDIG HEXDIG )
                / "bytes16!0x" 16( HEXDIG HEXDIG )
                / "bytes17!0x" 17( HEXDIG HEXDIG )
                / "bytes18!0x" 18( HEXDIG HEXDIG )
                / "bytes19!0x" 19( HEXDIG HEXDIG )
                / "bytes20!0x" 20( HEXDIG HEXDIG )
                / "bytes21!0x" 21( HEXDIG HEXDIG )
                / "bytes22!0x" 22( HEXDIG HEXDIG )
                / "bytes23!0x" 23( HEXDIG HEXDIG )
                / "bytes24!0x" 24( HEXDIG HEXDIG )
                / "bytes25!0x" 25( HEXDIG HEXDIG )
                / "bytes26!0x" 26( HEXDIG HEXDIG )
                / "bytes27!0x" 27( HEXDIG HEXDIG )
                / "bytes28!0x" 28( HEXDIG HEXDIG )
                / "bytes29!0x" 29( HEXDIG HEXDIG )
                / "bytes30!0x" 30( HEXDIG HEXDIG )
                / "bytes31!0x" 31( HEXDIG HEXDIG )
                / "bytes32!0x" 32( HEXDIG HEXDIG )
stringArg       = "string!" *pchar [ "." fileExtension ]

aQuery          = attribute *( "&" attribute )
attribute       = attrName "=" attrValue
attrName        = "returns"
                / "returnTypes"
attrValue       = [ "(" [ retTypes ] ")" ]
retTypes        = retType *( "," retType )
retType         = retRawType *( "[" [ %x31-39 *DIGIT ] "]" )
retRawType      = "(" retTypes ")"
                / retBaseType
retBaseType      = "bool" / "uint" [ intSizes ] / "int" [ intSize ] / "address" / "bytes" [ bytesSizes ] / "string"
bytesSizes      = %x31-39              ; 1-9
                / ( "1" / "2" ) DIGIT  ; 10-29
                / "31" / "32"          ; 31-32

domainName      = *( unreserved / pct-encoded / sub-delims ) ; As in RFC 3986

fileExtension   = 1*( ALPHA / DIGIT )

address         = "0x" 20( HEXDIG HEXDIG )
bytes           = "0x" *( HEXDIG HEXDIG )

pchar           = unreserved / pct-encoded / sub-delims / ":" / "@" ; As in RFC 3986

pct-encoded     = "%" HEXDIG HEXDIG ; As in RFC 3986

unreserved      = ALPHA / DIGIT / "-" / "." / "_" / "~" ; As in RFC 3986
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
                / "*" / "+" / "," / ";" / "=" ; As in RFC 3986

ERC4804からの変更点

修正点 (Corrections)

  • 手動モード (Manual mode)
    • ERC4804ではパスとクエリはそのまま使用されていましたが、この規格ではMIMEタイプを決定するために使用されています。
  • 自動モード (Auto mode)
    • ERC4804ではクエリにreturns属性がない場合、返されるデータはABIエンコードされたbytes32として扱われていましたが、この規格では実際には返されるデータはABIエンコードされたバイト列として扱われます。

明確化 (Clarifications)

  • 正式仕様 (Formal specification)
    • この規格ではURL形式のABNF定義が追加されています。
  • Resolveモード (Resolve mode)
    • この規格ではResolveモードがどのように決定されるかの詳細が示されています。
  • 手動モード (Manual mode)
    • URIパーセントエンコーディングの扱い、返されるデータ、MIMEタイプの決定方法についての詳細が示されています。
  • 自動モード (Auto mode)
    • 引数の値のエンコード方法や、returns値の形式と取り扱いについての詳細が示されています。

修正点 (Modifications)

  • プロトコル名 (Protocol name)
    • ERC4804ではethereum-web3://やeth-web3://が定義されていましたが、この規格では削除されています。
  • 自動モード (Auto mode)
    • 対応する型
      • ERC4804ではuint256、bytes32、address、bytes、stringのみをサポートしていましたが、この規格ではこれに加えさらに多くの型がサポートされています。
    • 返される整数のエンコード
    • ERC4804では整数を文字列としてエンコードしていましたが、この規格ではEthereum JSON RPC仕様に従い、整数を0xで始まる16進数文字列としてエンコードしています。

補足

この提案の目的は、Ethereumに対して分散型プレゼンテーションレイヤーを追加することです。 このレイヤーを使用することで、人間が読みやすいURLを使ってオンチェーンでHTML/CSS/JPG/PNG/SVGなどのウェブコンテンツをレンダリングできるようにし、EVM(Ethereum Virtual Machine)を分散型のバックエンドとして活用できます。

主な原則

人間が読みやすい

Web3 URLは、Web2 URL(例:http://)と同様に人間にとって容易に認識できるものである必要があります。 そのため、アドレスの代わりに名前サービスからの名前を使用することで、読みやすさを向上させます。 また、16進数のcalldataの代わりに、人間が読みやすいメソッドと引数を使用してcalldataに変換します。

HTTP-URL標準との最大限の互換性

Web3 URLは、HTTP-URL標準と互換性を持つべきで、相対パス、クエリ、フラグメント、パーセントエンコーディングなどが含まれます。 これにより、既存のHTTP-URLのサポート(例:ブラウザによるサポート)を最小限の変更でWeb3 URLに拡張できます。 また、既存のWeb2ユーザーがこの標準についての追加知識を最小限に抑えてWeb3に移行することが容易になります。

シンプル

引数に明示的な型を指定する代わりに、address、bytes32、uint256などの引数の型を自動的に検出しています。 これにより、URLの長さを最小限に抑えて混乱を避けることができます。 必要に応じて、明示的な型もサポートされています。

柔軟

コントラクトはエンコーディングルールをオーバーライドできるため、ユーザーが特定したい実際のWebリソースをコントラクトが細かく制御できるようにします。

引用

Qi Zhou (@qizhou), Chao Pi (@pichaoqkc), Sam Wilson (@SamWilsn), Nicolas Deschildre (@nand2), "ERC-6860: Web3 URL to EVM Call Message Translation [DRAFT]," Ethereum Improvement Proposals, no. 6860, September 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6860.

最後に

今回は「HTTPスタイルのWeb3URLをEVM呼び出しメッセージに変換する仕組みを提案しているERC6860」についてまとめてきました! いかがだったでしょうか?

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

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