solidity中assert()和require()的區別淺析


共同點

在看差別之前,我們先了解他們之間的共同點:

  • assert()require()語句都需要滿足括號中的條件,才能進行下面的操作
  • 若不滿足則拋出錯誤

以下三個語句的功能完全相同:

if(msg.sender != owner) { revert(); }

assert(msg.sender == owner);

require(msg.sender == owner);

差異化分析

gas效率

assert(false)編譯為0xfe,這是一個無效的操作碼,故將消耗掉所有剩余的gas,並恢復所有的操作

require(false)編譯為0xfd,這是revert()的操作碼,它將退還所有剩余的gas,同時可以返回一個值(自定義的報錯信息)

字節碼輸出分析

require()函數應用於滿足輸入或合約狀態變量等有效條件,或驗證調用外部合約的返回值等,總之require()語句的失敗報錯應該被看作一個正常的判斷語句流程不通過的事件,而assert()語句的失敗報錯,意味着發生了代碼層面的錯誤事件,很大可能是合約中有一個bug需要修復。

故此,使用require()的情況有:

  • 驗證用戶輸入,例如require(input_var>100);
  • 驗證外部合約的調用結果,例如require(external.send(amount));
  • 在執行狀態更改操作之前驗證狀態條件,例如require(block.number > 49999)require(balance[msg.sender]>=amount)

一般來說,使用require()的頻率更多,通常應用於函數的開頭

使用assert()的情況有:

  • 檢查溢出(上溢出或者下溢出)
  • 檢查不變量
  • 更改后驗證狀態
  • 預防永遠不會發生的情況

一般來說,使用assert()的頻率較少,通常用於函數的結尾

基本上,require()應該是您檢查條件的功能,assert()只是為了防止發生任何非常糟糕的事情,但條件不應該等於為false.

另外,不能盲目的使用require()去檢查溢出問題,只有在你認為之前的檢查過程中(require()或if語句)不會產生溢出的情況下使用。


參考資料:

https://ethereum.stackexchange.com/questions/15166/difference-between-require-and-assert-and-the-difference-between-revert-and-thro


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM