はじめに

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

今回は、ユーザーが署名するEIP712メッセージの内容を、ウォレットがコントラクトから取得して人間にわかりやすく表示する仕組みを提案しているERC6384についてまとめていきます!

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

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

概要

ERC6384は、evalEIP712Buffer という関数を提案しています。 この関数は、EIP712形式の署名データ(バッファ)を受け取り、それに対応する人間が読める形式の説明文を返すものです。

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

EIP-712は、オフチェーンでの構造化署名に関する標準仕様であり、MetaMaskなどのウォレットで広く採用されています。もともとは「人間にとって可読であること」が目標のひとつでしたが、実際にはその目標は十分に達成されていません。これにより、多くのユーザーが署名の内容を理解せず、結果として詐欺に遭う事例が発生しています。

動機

EIP712は、ガス代がかからないユーザー体験を実現できることから、ERC2612やOpenSeaなどで活用されています。 しかし、可読性が不十分なため、ユーザーはオフチェーンで提示された署名要求が何を意味するのか理解できず、不正なトランザクションに署名してしまうリスクがあります。

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

例えば、悪意のあるフィッシングサイトは、ユーザーにEIP712メッセージの署名を求めることで、NFTを0円で出品させてしまうといった攻撃を行っています。 現在のウォレットUIは、そうした署名の意味を十分に伝えることができていません。

ERC6384では、EIP712の検証対象となるコントラクト(verifyingContract)自身に署名メッセージの意味を解釈・説明させるevalEIP712Buffer 関数を追加することで、以下のような利点が得られます。

  • コントラクトはメッセージの正確な意味を理解しており、オフチェーンとオンチェーン両方で再利用可能な解釈コードを提供できる。
  • コントラクトの開発者は、署名内容を明確にすることで詐欺防止に貢献できるインセンティブがある。
  • 信頼すべき第三者を挟まず、スマートコントラクト自身が可読性を担保する。
  • view 関数として提供されるため、ガス代が不要でWeb3の利便性を維持できる。
  • Web3の構成可能性(composability)を損なわずに実装可能。

このように、evalEIP712Buffer はセキュリティとUXを両立させるための、現実的かつスケーラブルなソリューションとして設計されています。

MiceyMask-non-compliant.png

ZenGo-EIP-compliant-warning.png

仕様

EIP712では、オフチェーン署名をスマートコントラクトに結び付けるための verifyingContract フィールドがすでに存在しています。 ERC6384では、この verifyingContract に対して署名内容を人間が読める形式で返す view 関数の実装が必要です。

関数

ERC6384に準拠する全てのコントラクトは、以下の関数を実装しなければなりません。

js
/**
 * @dev Returns the expected result of the offchain message.
 */
function evalEIP712Buffer(
    bytes32 domainHash,
    string memory primaryType,
    bytes memory typedDataBuffer
) external view returns (string[] memory);

EIP712メッセージに関する3つの入力を受け取り、署名の意味を説明する文字列の配列を返します。

入力パラメータ

  • domainHash
    • EIP712のdomainSeparator。eip712Domain構造体をハッシュ化したもの。
  • primaryType
    • EIP712で定義される主要タイプ。
    • メッセージのエンコードの中心となる構造体の名前。
  • typedDataBuffer
    • メッセージ本体をABIエンコードしたバイト列。

出力

ユーザーに向けて署名の意味を説明するためのテキスト群である、string[] を返します。 ウォレットはこれらの文字列をエンドユーザーに表示する必要があります。 ウォレットは必要に応じて補足情報(例:コントラクトアドレスを名前に変換)を加えることも可能ですが、返された文字列にはHTMLなどのフォーマット情報を含めではいけないです。 表示に関しては、不正な入力の可能性も考慮して慎重にレンダリングする必要があります。

ウォレットにおける扱い

  • ウォレットは、署名前に evalEIP712Buffer をコントラクトに呼び出すことで、「オンチェーンのシミュレーションに相当するUX」をユーザーに提供できます。
  • この関数名・引数シグネチャは固定されるため、EIP712の構造に変更を加える必要はありません。

非対応ケースへの対応

  • EIP712の domainSeparatorに verifyingContract が含まれていない場合、ウォレットはこの関数を利用して説明を取得してはいけないです。
  • このようなケースでは、ウォレットは従来のEIP712表示方法にフォールバックする必要があります。

補足

typedDataBufferのABIエンコード形式について

署名データをコントラクトに渡す方法として、typedDataBuffer をABIエンコードされたバイト列として設計したのは、より汎用的な手法のためです。

代替案として構造体(typedData)そのものを渡すことも考えられましたが、コントラクトごとに異なる構造体定義を必要とするため汎用的ではありません。 ABIエンコードであればどのような型でも1つの形式で扱えるため、柔軟性と互換性が向上します。

戻り値を文字列配列にした理由

戻り値を string ではなく string[] にしたのは、複数の操作を含む署名メッセージに対応するためです。

例えば、複数のトークンを一括送信するようなケースでは、それぞれの送信を別の文字列で説明することで、ウォレット側がユーザーに対して分かりやすく個別表示できます。 この設計により、ユーザーは複雑な署名内容の各要素を個別に理解できるようになります。

他の解決策との比較

サードパーティサービスの利用

現在、多くのユーザーはサードパーティのサービスに署名データを送信し、内容の意味を解説してもらう方法を取っています。 しかし、これにはいくつかの欠点があります。

  • 拡張性がない
    • サービス提供者がすべてのdApp固有の構造を把握する必要がある
  • 正確性の保証がない
    • 第三者による推測的な解釈であり、誤解やミスが起こる可能性がある
  • セキュリティ・プライバシー上の懸念:信頼すべき第三者の存在が新たな依存関係を生む

ドメイン名とのバインディング

もう一つの方法として、EIP712の eip712Domain に含まれるWeb2ドメイン名と署名の発信元を照合する手法もあります。

しかしこの方法にも欠点があります。

  • Web3の構成可能性(composability)を損なうことにより、異なるdApp同士の連携が困難になる。
  • ドメインがハッキングされた場合正当なドメインから不正な署名が届くリスクがある。
  • WalletConnectなど一部の接続手段では、Web2ドメインの真正性を検証できない。

互換性

このEIPをサポートしないスマートコントラクトやウォレットが存在しても、問題はありません。

  • 非対応のコントラクトに対しては、ウォレットはこれまで通りのEIP-712署名表示を行います。
  • 非対応のウォレットは evalEIP712Buffer を呼び出さず、現状の動作を維持します。

このように、新機能を導入しても既存のシステムに影響を与えることはありません。

セキュリティ

想定される脅威モデル

ERC6384が対応する攻撃の典型例は、悪意あるWeb2インターフェース(dApp)が、ユーザーにとって不利益なEIP712メッセージを提示し、それにユーザーが署名してしまうケースです。

メッセージの内容は攻撃者が任意に制御できるため、信頼することはできません。 一方で、メッセージが送信される先のスマートコントラクト(verifyingContract)は正当な主体によって管理されていると想定されており、信頼できるものとみなされます。 攻撃者は、ユーザーが署名したEIP712メッセージを後日オンチェーンで実行し、不正な取引を成立させようとします。

なお、もし被害者自身がその取引を直接送信していた場合、通常のトランザクションシミュレーションだけで十分だったはずです。 ERC6384が想定しているのは、オフチェーン署名とオンチェーン実行の分断を突いた攻撃です。

悪意あるコントラクトのリスク

ERC6384に対して、悪意あるスマートコントラクトが evalEIP712Buffer を悪用し、細工された文字列をウォレットに返して脆弱性を突こうとするリスクも考えられます。

この場合に備え、ウォレットは文字列を「信用できない入力」として扱い、安全に表示処理する必要があります。 HTMLやスクリプトなどの挿入を防ぐ表示処理(サニタイズ処理)を行うことが推奨されます。

提案手法の安全性分析

ERC6384の設計は、以下の理由から安全性が高いと考えられます。

説明文は、信頼されたスマートコントラクトによって生成されます。 攻撃者は、スマートコントラクトのアドレスを指定する必要があります。 そのため、攻撃者が自由に偽の説明文を作ることはできません。 署名メッセージの一部として説明文を含める方式では、その説明文自体も攻撃者に制御されてしまうため、安全性は保てません。 ERC6384では説明文をコントラクト側が生成することで、その問題を回避しています。 evalEIP712Buffer関数にはview修飾子が付与されており、オンチェーンの状態を変更できないため、スマートコントラクトの他の機能に悪影響を与えることはありません。

引用

Tal Be'ery tal@zengo.com, RoiV (@DeVaz1), "ERC-6384: Human-readable offline signatures [DRAFT]," Ethereum Improvement Proposals, no. 6384, January 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6384.

最後に

今回は「ユーザーが署名するEIP712メッセージの内容を、ウォレットがコントラクトから取得して人間にわかりやすく表示する仕組みを提案しているERC6384」についてまとめてきました! いかがだったでしょうか?

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

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