Solidity語法隨筆(一)

assert() , require() 和 revert() 函數(shù)

Solidity 的錯誤處理模式
傳統(tǒng)方法:采用 throw 和 if ... throw 模式

例:
      這行代碼:
      if(msg.sender != owner) { throw; }

       完全等價于如下三種形式:
       if(msg.sender != owner) { revert(); }
       assert(msg.sender == owner);
       require(msg.sender == owner);
       注意在 assert() 和 require() 例子中的條件聲明,是 if 例子中條件塊取反,也就是用 ==代替了 != 。

區(qū)別:
assert():想象為一個過于自信的實現(xiàn)方式,即使有錯誤,也會執(zhí)行并扣除gas。
require():想象為一個更有禮貌些的實現(xiàn)方式,會發(fā)現(xiàn)錯誤,并且原諒所犯錯誤(譯注:不扣除 gas)。
revert():碰到無效代碼后,仍將回滾所有狀態(tài),但是會用兩種不同于“無效代碼”方式處理:允許返回一個數(shù)值,
將剩余gas返還調(diào)用者。

require()用于:

確認有效條件,例如輸入,
確認合約聲明變量是一致的
從調(diào)用到外部合約返回有效值
如果正確使用,分析工具會評估合約并分辨出引起 assert 調(diào)用錯誤的條件和函數(shù)。正確函數(shù)代碼將會避免引起調(diào)用錯誤的 assert 聲明;如果發(fā)生就意味著合約中存在需要修復(fù)的bug。

為了更清楚地解釋:require() 聲明失敗應(yīng)該被認為是正常和健壯的情況(跟 revert() 一樣);而當 assert() 聲明失敗時,則意味著有些東西失控了,需要修復(fù)代碼中的問題。

判斷正確使用場景:
require():

  • 驗證用戶輸入,即: require(input<20);
  • 驗證外部合約響應(yīng),即: require(external.send(amount));
  • 執(zhí)行合約前,驗證狀態(tài)條件,即: require(block.number > SOME_BLOCK_NUMBER) 或者 require(balance[msg.sender]>=amount)
  • 一般地,盡量使用 require 函數(shù)
  • 一般地,require 應(yīng)該在函數(shù)最開始的地方使用

revert():

  • 處理與 require() 同樣的類型,但是需要更復(fù)雜處理邏輯的場景

如果有復(fù)雜的 if/else 邏輯流,那么應(yīng)該考慮使用 revert() 函數(shù)而不是require()。記住,復(fù)雜邏輯意味著更多的代碼。

assert():

  • 檢查 overflow/underflow,即:c = a+b; assert(c > b)
  • 檢查非變量(invariants),即:assert(this.balance >= totalSupply);
  • 驗證改變后的狀態(tài)
  • 預(yù)防不應(yīng)該發(fā)生的條件
  • 一般地,盡量少使用 assert 調(diào)用
  • 一般地,assert 應(yīng)該在函數(shù)結(jié)尾處使用

基本上,require() 應(yīng)該被用于函數(shù)中檢查條件,assert() 用于預(yù)防不應(yīng)該發(fā)生的情況,但不應(yīng)該使條件錯誤。

另外,“除非認為之前的檢查(用 ifrequire )會導(dǎo)致無法驗證 overflow,否則不應(yīng)該盲目使用 assert 來檢查 overflow

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容