【Solidity基礎】requireとassertの違い




requireとassert

Solidityでは関数の入力値の確認に対してrequireを使用し、結果の確認にassertを使います。期待通りの値であればそのまま処理を続行し、期待に反する値の場合はそれまでの処理を全てなかったことにします。この処理を戻すことをrevert(リバート)といいます。

requireとassertではrevert後の処理が異なるのでそれに関して説明をしたいと思います。

require

下記はzeppelin-solidityのStandardToken.solのtransferFrom関数です。関数の最初の3行でrequireを使って入力値の確認をしています。

1行目は_toアドレスがゼロアカウントじゃないかチェックしています。2行目は送金する額が送金者の残高以下かチェックしています。3行目は送金者がコントラクト実行者に対して送金を許可している額以下かチェックしています。

この関数では3つのrequireを処理できたら実際に送金処理が行われます。このように重要な処理を行う関数のはじめにrequireを使って入力値のバリデーションを行うのがセオリーです。

もし、残高よりも大きい額を送金しようとした場合は2行目で引っかかり、それまで処理したものは全てrevertされ元に戻ります。またrevertまでに使用したgasは戻ってきませんが残ったgasは返却されます。

function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
  require(_to != address(0));
  require(_value <= balances[_from]);
  require(_value <= allowed[_from][msg.sender]);

  balances[_from] = balances[_from].sub(_value);
  balances[_to] = balances[_to].add(_value);
  allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
  Transfer(_from, _to, _value);
  return true;
}

assert

下記はzeppelin-solidityのSafeERC20.solのsafeTransferFrom関数です。上記で使用した関数をラップして送金が失敗した場合(trueが帰ってこない場合)に処理を元に戻してくれます。

assertはそれまでに使用したgasだけでなく残りもガスも使用してしまいます。gasを全部使用してしまうということはそれ以上何も処理をできないことになるので繰り返し処理をしてしまうようなバグに対しては有効な対策になりそうですが、ユーザーライクな処理ではないので使い所が難しそうです。

なので、関数の入力値のチェックには使わず、最終的な結果に対してassertでチェックをするのが良さそうです。

function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
  assert(token.transferFrom(from, to, value));
}

まとめ

requireの使い所は分かりやすいですがassertをどこで使うべきかはなかなか判断が難しそうだなと思いました。gasを消費しきってそれ以降の処理をさせたくない時、または繰り返し処理をしてしまうと困る箇所にはassertなのかもしれませんが今の自分の知識でははっきりと判断できそうにないです。

誰か詳しい方コメントでもいいので教えていただけたらと嬉しいです。

おすすめ書籍

Ethereumを使ったDApps開発を学びたいなら今だとこの1冊が1番良いです!開発環境の構築から使うべきツール、フレームワーク、実装方法・注意点まで網羅的に解説されている書籍なのでおすすめです。出版も2018年1月ということでかなり新しい本で、DMM Bitcoinを作っているネクストカレンシー所属の方が書いているので信頼できます。

ビットコインとブロックチェーンの詳細をしっかりと学びたい方にはこちらの書籍が非常におすすめです。ウォレットの仕組み、楕円曲線暗号、P2Pプロトコル、公開鍵暗号などビットコインを支える技術について詳細に解説されています。また、サンプルコードを通して実際に手を動かして学べるので非常に濃い内容となっています。

The following two tabs change content below.

髙妻智一

2013年CyberAgent新卒入社 スマホゲームを作る子会社に所属し、サーバーサイドのエンジニアを担当。2年目の終わりから新規子会社の立ち上げに参加し、サーバーサイドのエンジニアリーダーとしてサービースのリリースから運用までを担当。 2018年仮想通貨のスマホウォレットを提供するGinco Incにブロックチェーンエンジニアとして入社。






よく読まれている関連記事はこちら




コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です