アルゴリズムとかオーダーとか

仕事で勉強したことなどをまとめてます

Solidityのassertとrequireとrevertの違い

Solidityでは引数などの値の妥当性を検証するためにassertとrequire関数が用意されています。また、コードの実行をストップさせるためのrevert()関数もあります。今回はこれらの関数の挙動についてまとめてみました。

assert(condition)

assert関数はconditionがfalseを返した場合、そこでcontractの実行を停止し、contractの状態を実行前に戻して残りのすべてのガスを消費します。
assertをコンパイルするとopcode=0xfeになり、evm上では0xfeは未定義のopcodeなので動作が停止されます。

require(condition)

require関数はconsitiongafalseを返した場合、そこでcontractの実行を停止し、contractの状態を実行前に戻して残りのガスをcallerに返却します。
assertと違い、requireでは使った分のガスだけが消費されます。
requireをコンパイルすると、revert opcodeに変換されます。

revert(message)

revert関数はそこでcontractの実行を停止し、contractの状態を実行前に戻して残りのガスをcallerに返却します。
revert関数は評価する条件を持ちません。そこにコードが到達した時点でエラーと見なす場合に使います。
また、opcodeとしてはエラーメッセージを返却可能ですが、solidityではエラーメッセージの返却部分は未実装です。エラーメッセージを受け取りたい場合は、assembly codeを書く必要があります。
なお、昔のバージョンにあったthrowキーワードはrevertへと置き換えらえました。(deprecatedですが一応使えます。throwを書くとコンパイル時にrevertに変換されます。)

まとめ

基本的にはgasを全部消費してしまうassertよりはrequireを使う方が良さそうな気がします。また現状ではrevert関数はわざわざ使う必要はなさそうです。
assertとrequireのどちらを使うといいのかはSolidityのドキュメントに推奨例を書いてますので参考にしてみてください。