はじめに

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

今回は、EIP5792のwallet_sendCallsを拡張し、dAppsがウォレット呼び出しに必要なトークン残高や承認などの前提条件を指定できるようにする仕組みを提案しているERC7795についてまとめていきます!

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

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

概要

ERC7795とは、EIP5792のwallet_sendCallsメソッドを拡張し、dAppsがウォレットに対してトークンに関する前提条件を指定できるようにする仕組みのことです。

EIP5792は、dAppsがウォレットに対して複数の呼び出しをバッチで送信できるようにするwallet_sendCallsメソッドを定義した規格です。

ERC7795では、ERC20トークンの残高・承認要件を指定できます。

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

また、ERC721(NFT)の所有権・承認要件も指定できます。

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

さらに、ERC1155トークンの残高・承認要件も指定可能です。

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

これらの機能はwallet_sendCallsとwallet_getCapabilitiesRPCメソッドを通じて実装されます。

この規格の特徴は、ウォレットが前提条件を自動的に処理できる点にあります。 dAppsがトークン要件を指定すると、ウォレットはその要件を満たすために必要なトランザクション(承認やスワップなど)を自動的に先頭に追加します。

ERC7795では、ERC20の残高・承認、ERC721の所有権・承認、ERC1155の残高・承認に対応する6種類のケーパビリティを定義しています。 これらはEIP5792の既存のケーパビリティ発見メカニズム(wallet_getCapabilities)を活用するため、ウォレットは対応可能な要件のみを選択的に実装できます。 また、複数のケーパビリティを組み合わせて使用することも可能で、将来的に新しい要件タイプを段階的に追加できる拡張性も備えています。

ERC7795 ケーパビリティ概要

動機

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

単一ネットワーク依存による流動性の縮小

dAppsが1つのネットワーク上にのみ存在することはよくありますが、これによりdAppsがアクセスできる直接的な流動性が縮小します。 ほとんどのユーザーは限られた数のネットワークにのみ資金を持っており、ネットワーク数が増えるほど、dAppsが選択したネットワークとユーザーの資金があるネットワークが一致する可能性は低くなります。

「最終意図」を伝える手段の欠如

dAppsにはウォレットに対して「最終意図(final intent)」を伝える方法がないため、ユーザーに実行してほしい最後のアクション(トランザクションリクエスト)しか伝えることができません。 そのため、最終アクションの前提条件を満たすために必要な事前アクション(資金の統合やアセットの交換など)をユーザー自身が推測しなければなりません。 この推測プロセスはユーザーにとって煩雑で、UXの大幅な低下につながっています。

この提案による解決策

ERC7795は、dAppsがwallet_sendCallsのケーパビリティとしてトークン前提条件を指定できるようにします。 ウォレットはこれらの前提条件を解釈し、必要に応じてトランザクション(ブリッジ、スワップ、承認など)を自動的に先頭に追加することで、シームレスなユーザー体験を提供できます。

仕様

ケーパビリティ一覧

ERC7795では、以下の6つのケーパビリティを定義しています。

ケーパビリティ 対象トークン 説明
erc20MinBalance ERC20 最小残高要件
erc20MinAllowance ERC20 最小承認額要件
erc721Ownership ERC721 NFT所有権要件
erc721Approval ERC721 NFT承認要件
erc1155MinBalance ERC1155 最小残高要件
erc1155MinAllowance ERC1155 最小承認要件

ERC20

ERC20トークンに関するケーパビリティとして、最小残高要件と最小承認額要件の2つが定義されています。

erc20MinBalance

ERC20トークンの最小残高要件を指定するケーパビリティです。 dAppsはこのケーパビリティを使用して、呼び出しを実行する前にアカウントが特定のERC20トークンの最小残高を持っている必要があることをウォレットに通知します。 ウォレットはこの要件を満たすために、ブリッジやスワップなどのトランザクションを先頭に追加する場合があります。

パラメータ
フィールド 型 説明
version string ケーパビリティのバージョン
chainId 0x${string} チェーンID(16進数)
owner 0x${string} 残高を確認するアドレス
token 0x${string} ERC20トークンのコントラクトアドレス
minAmount 0x${string} 必要な最小残高(16進数)
使用例
javascript
{
  "capabilities": {
    "erc20MinBalance": {
      "version": "1.0",
      "chainId": "0x01",
      "owner": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
      "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "minAmount": "0x0f4240" // 1,000,000 = 1 USDC (6 decimals)
    }
  }
}

erc20MinAllowance

ERC20トークンの最小承認額要件を指定するケーパビリティです。 dAppsはこのケーパビリティを使用して、呼び出しを実行する前に特定のアドレスに対するERC20トークンの最小承認額が必要であることをウォレットに通知します。 ウォレットはこの要件を満たすために、approveトランザクションを先頭に追加する場合があります。

パラメータ
フィールド 型 説明
version string ケーパビリティのバージョン
chainId 0x${string} チェーンID(16進数)
owner 0x${string} 承認元のアドレス
operator 0x${string} 承認先のオペレーターアドレス
token 0x${string} ERC20トークンのコントラクトアドレス
minAmount 0x${string} 必要な最小承認額(16進数)

このケーパビリティはオーナーがトークンの残高を持っていることを意味しません。承認額が指定した量以上であることのみを要求します。

使用例
javascript
{
  "capabilities": {
    "erc20MinAllowance": {
      "version": "1.0",
      "chainId": "0x01",
      "owner": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
      "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
      "operator": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
      "minAmount": "0x0f4240" // Uniswap Router に USDC を承認
    }
  }
}

ERC721

ERC721トークン(NFT)に関するケーパビリティとして、所有権要件と承認要件の2つが定義されています。

erc721Ownership

ERC721トークン(NFT)の所有権要件を指定するケーパビリティです。 dAppsはこのケーパビリティを使用して、呼び出しを実行する前にアカウントが特定のNFTを所有している必要があることをウォレットに通知します。 ウォレットはこの要件を満たすために、NFTの購入などのトランザクションを先頭に追加する場合があります。

パラメータ
フィールド 型 説明
version string ケーパビリティのバージョン
chainId 0x${string} チェーンID(16進数)
owner 0x${string} 所有者のアドレス
token 0x${string} ERC721トークンのコントラクトアドレス
tokenId 0x${string} 必要なトークンID(16進数)
使用例
javascript
{
  "capabilities": {
    "erc721Ownership": {
      "version": "1.0",
      "chainId": "0x01",
      "owner": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
      "token": "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
      "tokenId": "0x10" // BAYC #16 の所有権が必要
    }
  }
}

erc721Approval

ERC721トークン(NFT)の承認要件を指定するケーパビリティです。 dAppsはこのケーパビリティを使用して、呼び出しを実行する前に特定のオペレーターに対するNFTの承認が必要であることをウォレットに通知します。

このケーパビリティはオーナーがトークンを所有していることを意味しません。承認が設定されていることのみを要求します。

パラメータ
フィールド 型 説明
version string ケーパビリティのバージョン
chainId 0x${string} チェーンID(16進数)
owner 0x${string} 承認元のアドレス
operator 0x${string} 承認先のオペレーターアドレス
token 0x${string} ERC721トークンのコントラクトアドレス
tokenId 0x${string} 承認が必要なトークンID(16進数)
使用例
javascript
{
  "capabilities": {
    "erc721Approval": {
      "version": "1.0",
      "chainId": "0x01",
      "owner": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
      "operator": "0x00000000006c3852cbEf3e08E8dF289169EdE581",
      "token": "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
      "tokenId": "0x10" // OpenSea Seaport に BAYC #16 を承認
    }
  }
}

ERC1155

ERC1155トークンに関するケーパビリティとして、最小残高要件と最小承認要件の2つが定義されています。

erc1155MinBalance

ERC1155トークンの最小残高要件を指定するケーパビリティです。 dAppsはこのケーパビリティを使用して、呼び出しを実行する前にアカウントが特定のERC1155トークンの最小残高を持っている必要があることをウォレットに通知します。

パラメータ
フィールド 型 説明
version string ケーパビリティのバージョン
chainId 0x${string} チェーンID(16進数)
owner 0x${string} 残高を確認するアドレス
token 0x${string} ERC1155トークンのコントラクトアドレス
tokenId 0x${string} トークンID(16進数)
minAmount 0x${string} 必要な最小残高(16進数)
使用例
javascript
{
  "capabilities": {
    "erc1155MinBalance": {
      "version": "1.0",
      "chainId": "0x01",
      "owner": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
      "token": "0x631998e91476da5b870d741192fc5cbc55f5a52e",
      "tokenId": "0x10",
      "minAmount": "0x0f4240" // Token ID 16 の残高が指定量以上必要
    }
  }
}

erc1155MinAllowance

ERC1155トークンの最小承認要件を指定するケーパビリティです。 dAppsはこのケーパビリティを使用して、呼び出しを実行する前に特定のアドレスに対するERC1155トークンの承認が必要であることをウォレットに通知します。

このケーパビリティはオーナーがトークンの残高を持っていることを意味しません。承認額が指定した量以上であることのみを要求します。

パラメータ
フィールド 型 説明
version string ケーパビリティのバージョン
chainId 0x${string} チェーンID(16進数)
owner 0x${string} 承認元のアドレス
operator 0x${string} 承認先のオペレーターアドレス
token 0x${string} ERC1155トークンのコントラクトアドレス
tokenId 0x${string} トークンID(16進数)
minAmount 0x${string} 必要な最小承認額(16進数)
使用例
javascript
{
  "capabilities": {
    "erc1155MinAllowance": {
      "version": "1.0",
      "chainId": "0x01",
      "owner": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
      "operator": "0x00000000006c3852cbEf3e08E8dF289169EdE581",
      "token": "0x631998e91476da5b870d741192fc5cbc55f5a52e",
      "tokenId": "0x10",
      "minAmount": "0x0f4240" // OpenSea Seaport に承認
    }
  }
}

補足

完全な使用例

以下は、複数のケーパビリティを組み合わせたwallet_sendCallsの完全な使用例です。

javascript
{
  "method": "wallet_sendCalls",
  "params": [{
    "version": "1.0",
    "from": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
    "calls": [
      {
        "to": "0xDeFiProtocol",
        "data": "0x...",
        "value": "0x0",
        "chainId": "0x01"
      }
    ],
    "capabilities": {
      "erc20MinBalance": {
        "version": "1.0",
        "chainId": "0x01",
        "owner": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
        "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
        "minAmount": "0x5F5E100"
      },
      "erc20MinAllowance": {
        "version": "1.0",
        "chainId": "0x01",
        "owner": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
        "token": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
        "operator": "0xDeFiProtocol",
        "minAmount": "0x5F5E100"
      }
    }
  }]
}

この例では、以下の前提条件を指定しています。

  • USDCの残高が100以上であること
  • DeFiプロトコルに対してUSDCの承認が100以上であること

ウォレットの動作

ウォレットは指定されたケーパビリティに基づいて、以下のように動作します。

sequenceDiagram
    participant dApp
    participant Wallet
    participant Blockchain

    dApp->>Wallet: wallet_sendCalls (with capabilities)
    Wallet->>Wallet: 前提条件を確認
    alt 前提条件が満たされていない場合
        Wallet->>Wallet: 必要なトランザクションを生成
        Wallet->>Blockchain: 前提条件を満たすTx
    end
    Wallet->>Blockchain: 元のcallsを実行
    Blockchain-->>Wallet: 結果
    Wallet-->>dApp: レスポンス

この図は、dAppsがwallet_sendCallsでケーパビリティを指定した場合のウォレットの処理フローを示しています。

  1. dAppsがケーパビリティ付きのwallet_sendCallsをウォレットに送信します。
  2. ウォレットは指定された前提条件(残高要件、承認要件など)を確認します。
  3. 前提条件が満たされていない場合、ウォレットは必要なトランザクション(スワップ、ブリッジ、approve呼び出しなど)を自動的に生成します。
  4. 前提条件を満たすトランザクションを先に実行し、その後に元のcallsを実行します。
  5. すべてのトランザクションが完了したら、結果をdAppsに返します。

この仕組みにより、dAppsは複雑なトランザクション順序を自分で管理する必要がなくなり、ウォレットが最適な方法で前提条件を処理できます。

ケーパビリティのサポート確認

ウォレットがこれらのケーパビリティをサポートしているかどうかは、wallet_getCapabilitiesメソッドで確認できます。

javascript
{
  "method": "wallet_getCapabilities",
  "params": ["0xUserAddress"]
}

レスポンス例を以下に示します。

javascript
{
  "0x1": {
    "erc20MinBalance": { "supported": true, "versions": ["1.0"] },
    "erc20MinAllowance": { "supported": true, "versions": ["1.0"] },
    "erc721Ownership": { "supported": true, "versions": ["1.0"] },
    "erc721Approval": { "supported": true, "versions": ["1.0"] },
    "erc1155MinBalance": { "supported": true, "versions": ["1.0"] },
    "erc1155MinAllowance": { "supported": true, "versions": ["1.0"] }
  }
}

互換性

EIP5792との関係

ERC7795は以下の規格と関係があります。

規格 関係性 備考
EIP5792 拡張 wallet_sendCallsのケーパビリティとして実装
ERC20 対象 残高・承認要件を指定可能
ERC721 対象 所有権・承認要件を指定可能
ERC1155 対象 残高・承認要件を指定可能

ユースケース

以下の2つの具体的なユースケースが紹介されています。

EOAウォレットでのブリッジを使ったマーケットプレイス購入

ユーザーがチェーンA上でERC721トークンを購入したいが、資金はチェーンBにしかない場合を考えます。 dAppsはwallet_sendCallsを使い、マーケットプレイスのトランザクションとともにチェーンA上の資金要件をケーパビリティとして指定します。 EOAウォレットは、前提条件を満たすために必要なトランザクション(ブリッジなど)への署名をユーザーに促し、メインのトランザクションを実行する前にそれらが完了していることを保証します。

EOAウォレットでのブリッジを使ったマーケットプレイス購入

スマートコントラクトウォレットでのブリッジ・スワップ・支払い

dAppsがユーザーに対してチェーンB上のトークンZでの支払いを要求するが、ユーザーはチェーンA上にトークンYしか持っていない場合を考えます。 dAppsは支払いトランザクションとともにチェーンB上のトークンZ残高要件をケーパビリティとして指定します。 スマートコントラクトウォレットは、必要なすべてのトランザクション(ブリッジ・スワップ・支払い)に一度に署名することをユーザーに求め、適切な順序で実行します。 署名済みトランザクションはバンドラーに同時に送信でき、ウォレットが切断されても操作が完了できます。

スマートコントラクトウォレットでのブリッジ・スワップ・支払い

後方互換性

ERC7795はEIP5792のケーパビリティシステムを使用しているため、このケーパビリティをサポートしていないウォレットでも、単純にケーパビリティを無視して通常のwallet_sendCallsとして処理することができます。

セキュリティ

セキュリティに関する考慮事項として、以下の点に注意が必要です。

過度な承認

dAppsが必要以上の承認額を要求する可能性があります。

ウォレットは要求された承認額をユーザーに明示し、必要に応じて調整できるようにすべきです。 また、無制限承認(type(uint256).max)の要求には特に注意が必要です。

悪意のあるdApps

悪意のあるdAppsがユーザーの資産を狙った前提条件を設定する可能性があります。

ウォレットは前提条件を満たすために実行するトランザクションの詳細をユーザーに表示し、明示的な承認を得るべきです。

トランザクション順序の操作

前提条件を満たすトランザクションと元のcallsの間でフロントランニング攻撃が発生する可能性があります。

ウォレットは可能な限りアトミックな実行(バッチトランザクション)を使用すべきです。

ウォレット開発者は、前提条件を満たすために自動的に実行するトランザクションについて、ユーザーに明確な同意を求める必要があります。

引用

最後に

今回は「ERC7795によるdAppsがウォレットにトークン前提条件を指定できる仕組み」についてまとめてきました! いかがだったでしょうか?

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

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