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