共同點
在看差別之前,我們先了解他們之間的共同點:
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語句)不會產生溢出的情況下使用。
參考資料:
