# [ERC6860] HTTPスタイルのURLでオンチェーンコンテンツにアクセスするWeb3 URLの仕組みを理解しよう！

> ERC6860とは、HTTPスタイルのWeb3 URL（例: web3://uniswap.eth/）をEVMのCall Messageに変換するプロトコルのことです。

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

### はじめに

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

https://www.amazon.co.jp/dp/B0DQDWM1YK

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

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://twitter.com/cardene777

https://zenn.dev/heku

https://qiita.com/cardene

https://cardene.substack.com/

https://mirror.xyz/0xACAc709e21e7a4A5a4458BDeeCCA0fc98A6a8A4D

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

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

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

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

## 概要

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

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

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

[\[ERC4804\] HTTP形式のWeb3 URLからコントラクトを呼び出すことができる仕組みを理解しよう！](/articles/837931ce60ca844aee13)

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の基本構文は以下の通りです。

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

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

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

Web3 URLの例は以下です。

```
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）になります。

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

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

#### 戻り値の処理

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

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

### オートモード

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

#### パス構造

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

```
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（ドメイン名として解析） |

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

#### 使用例

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

```
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形式で返される |

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

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

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

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

### 実践的な使用例

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

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

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

```
web3://w3url.eth/
```

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

#### NFTメタデータの取得

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

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

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

#### 別チェーンへのアクセス

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

```
web3://vitalikblog.eth:5/
```

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

#### 戻り値の型指定

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

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

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

#### 複数の戻り値

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

```
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で定義されています。

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

```
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などのドメイン名を指定します。

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

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

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

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

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

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

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

```
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ドメインの所有者が変わった場合、異なるコントラクトにリダイレクトされる可能性があります。

## 引用

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

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

https://github.com/web3-protocol/evm-browser

## 最後に

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

https://www.amazon.co.jp/dp/B0DQDWM1YK

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://twitter.com/cardene777

https://zenn.dev/heku

https://qiita.com/cardene

https://cardene.substack.com/

https://mirror.xyz/0xACAc709e21e7a4A5a4458BDeeCCA0fc98A6a8A4D
