はじめに

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

今回は、スマートコントラクトで発生するエラー内容を標準化し、ユーザーや開発者がわかりやすく原因を特定できるようにする仕組みを提案しているERC838についてまとめていきます!

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

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

概要

ERC838は、スマートコントラクトのJSON ABI(Application Binary Interface)において、発生し得るエラー条件をどのようにエンコード(符号化)するかを定義するものです。 ABIとは、スマートコントラクトと外部プログラム(例えば、Webアプリやウォレットなど)がやり取りをする時の「通信仕様」のようなものです。

ERC838では、スマートコントラクトがエラーを起こした時に、その内容を標準化された形式で表現して外部のアプリケーションやライブラリ(例:web3.js)が簡単にその内容を復元できるようにする仕組みを定めています。

高水準のプログラミング言語(例:Solidityなど)では、開発者がエラーを「宣言」したり「送出(throw)」したりするための構文を提供することが想定されています。 コンパイラはそれらのエラーをREVERT命令(オペコード)の reason パラメータにエンコードし、クライアント側で再構築できるようにします。

つまりこの仕組みは、「スマートコントラクトのエラー情報をわかりやすく、機械的にも扱いやすい形で外部に伝えるための共通ルール」を作ることを目的としています。

動機

Ethereumのトランザクションにおいて、何が原因で失敗したのかをユーザーや開発者に明確に伝えることは非常に重要です。

これまでは、トランザクションが失敗すると単に「revert(失敗)」という結果だけが返り、具体的に何が問題だったのかがわかりにくい状況でした。 しかし、REVERTオペコードの導入により、スマートコントラクト開発者はエラー時に「理由」を文字列(string)としてエンコードして返すことができるようになりました。

Solidityでは、現在「文字列を受け取って REVERT 命令に渡す」実装が審査中であり、これによって低レベルのエラーメッセージ処理が可能になります。

ただし、単に文字列を返すだけでは不十分です。 エラーの構造や形式が標準化されていないと、クライアントや開発ツール側での扱いが難しく、エラーの意味を正しく理解するのが困難になります。

そのため、ERC838では以下のようなメリットを目指しています。

目的 説明
統一されたエラー形式の定義 各スマートコントラクトが異なる形式でエラーを返すのではなく、共通の形式にすることで再利用性を高めます。
開発効率の向上 コンパイラや開発ツールが自動的にエラー情報を処理できるようになり、開発者が手動で文字列を解析する必要がなくなります。
ユーザー体験の改善 フロントエンドやウォレットがエラー内容を人間に理解しやすい形で表示できるようになります。
デバッグの容易化 テストや実運用時に、どの関数や条件で失敗したのかを特定しやすくなります。

仕様

ERC838は、スマートコントラクトのJSON ABI(Application Binary Interface)にエラー情報をどのように記述するかを定めています。 この仕様に準拠するためには、コンパイラ(例:Solidityコンパイラ)は、関数やイベントと同様にエラー宣言(error declarations)もJSON ABIに含める必要があります。

エラーは、発生した不具合や条件不一致を構造化して表現するためのものです。 これにより、外部ツールやクライアント(例:web3.jsなど)がエラー内容を理解し、正確な原因をユーザーに伝えられるようになります。

エラーオブジェクトの構造

各エラーはJSON形式で表現され、必ず以下の3つの要素を含まなければなりません。

キー名 型 説明
type string 値は必ず "error" に固定されます。これは、このオブジェクトがエラー定義であることを示します。
name string エラーの名前(識別子)です。例:"InsufficientBalance"(残高不足)。
arguments 配列(オブジェクト) 関数の入力引数と同様の形式で、エラーが受け取るパラメータを定義します。各引数は name と type を持ちます。

例として、残高不足を表すエラーは以下のように定義されます。

json
{
  "type": "error",
  "name": "InsufficientBalance",
  "arguments": [
    { "name": "amount", "type": "uint256" }
  ]
}

このようにすることで、エラー自体がデータ構造として扱えるようになります。

エラーセレクタの計算とエンコード方法

関数やイベントと同様に、エラーにもセレクタ(selector)を持たせることができます。 セレクタとは、エラーの識別に使われるハッシュ値の一部で、エラーのシグネチャ(例:InsufficientBalance())から計算されます。

このセレクタは、REVERT命令のreason文字列に含められる必要があります。 クライアントはこのセレクタをもとにエラーを照合(lookup)し、どのエラーが発生したのかを特定できます。

さらに、エラーの引数(arguments)は、RLP(Recursive Length Prefix)エンコードというEthereumの標準的なデータエンコード方式を用いて変換されます。 これは、関数の戻り値をエンコードする方法と同じです。

このセレクタと引数の具体的なエンコード形式は、今後定義される予定ですが、Solidityの現在の実装では「自由形式の文字列の前に uint256(0) を付ける」構造を取ることで、将来的な拡張にも対応できるようにしています。

Solidityでの利用例

この仕様は、Solidityのような高水準言語で自然に使えるように設計されています。 以下はその一例です。

js
contract MyToken {
  error InsufficientFunds(uint256 amount);

  function transfer(address _to, uint256 _amount) {
    if (balances[msg.sender] <= _amount)
       throw InsufficientFunds(_amount);
    ...
  }
  ...
}

上記の例では、InsufficientFunds というエラーが定義されており、transfer 関数内で残高が不足している場合にエラーを送出(throw)します。 これにより、エラー情報はJSON ABI内に構造化され、フロントエンドやライブラリ側が簡単に内容を解析できるようになります。

可能な拡張

この仕様は将来的な拡張性も考慮して設計されています。 主な拡張案は以下の通りです。

NatSpecコメントによるエラーメッセージの定義

SolidityにはNatSpec(Ethereum Natural Specification Format)というコメント形式があり、コードのドキュメント化に使用されます。 エラー宣言の上にNatSpecコメントを追加することで、デフォルトのエラーメッセージを指定することができます。

さらに、エラーの引数をメッセージ内に埋め込むことも可能です。 以下の例では、amount の値が自動的にメッセージ内に挿入されます。

solidity
/// @notice You don't have enough funds to transfer `amount`.
error InsufficientFunds(uint256 amount);

これにより、ユーザーに対して「送付金額が不足しています」といった具体的なメッセージを動的に生成できます。

関数が投げる可能性のあるエラーの宣言

関数は、呼び出し側に対して「どのエラーを発生させる可能性があるか」を明示的に示すことができます。 この情報はJSON ABI内の関数定義に追加され、errorsキーの下にエラー一覧として記述されます。

例:

solidity
function transfer(address _to, uint256 _amount) throws(InsufficientFunds);

これにより、呼び出し側(クライアントや他のコントラクト)は、関数を実行する前にどのようなエラーが起こり得るかを事前に把握できます。 これはAPI設計における「型安全な例外処理」に近い考え方です。

エラーのオーバーロードに関する考慮点

今後、同じ名前のエラーに異なる引数を持たせる「エラーのオーバーロード(overloading)」をサポートする可能性もあります。 ただし、その場合、引数の型や順序が異なると異なるセレクタが生成されるため、エラー名が同じでも識別子は別のものになります。

そのため、実装時には将来的な拡張を考慮し、エラー名の付け方や引数の設計に注意が必要です。

引用

Federico Bond (@federicobond), Renan Rodrigues de Souza (@RenanSouza2), "ERC-838: ABI specification for REVERT reason string [DRAFT]," Ethereum Improvement Proposals, no. 838, August 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-838.

最後に

今回は「スマートコントラクトで発生するエラー内容を標準化し、ユーザーや開発者がわかりやすく原因を特定できるようにする仕組みを提案しているERC838」についてまとめてきました! いかがだったでしょうか?

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

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