require 和 assert 的區別以及 revert 和 throw 的區別
我正在查看文件
require
,並且正在尋找有關andassert
和throw
and之間區別的說明revert
。斷言(布爾條件):如果條件為假,則中止執行並恢復狀態更改(用於內部錯誤)
要求(布爾條件):如果條件為假,則中止執行並恢復狀態更改(用於格式錯誤的輸入)
特別是關於
assert
andrequire
,您如何在格式錯誤的輸入和內部錯誤之間劃清界限?
選擇
assert()
和時需要考慮兩個方面require()
氣體效率
字節碼分析
氣體效率
assert(false)
編譯為0xfe
,這是一個無效的操作碼,用完所有剩餘的氣體,並恢復所有更改。
require(false)
編譯到0xfd
哪個是REVERT
操作碼,這意味著它將退還剩餘的氣體。操作碼也可以返回一個值(對調試很有用),但我認為目前 Solidity 不支持該值。(2017-11-21)2.字節碼分析
來自文件(強調我的)
應該使用 require 函式來確保滿足有效條件,例如輸入或合約狀態變數,或者驗證來自外部合約呼叫的返回值。如果使用得當,分析工具可以評估您的合約,以確定將達到失敗斷言的條件和函式呼叫。正常執行的程式碼永遠不應到達失敗的斷言語句;如果發生這種情況,您的契約中有一個錯誤,您應該修復它。
以上摘錄是對靜止(截至 2017-11-21)實驗性和未記錄的
SMTChecker
.我使用一些啟發式方法來幫助我決定使用哪個。
用於
require()
:
- 驗證使用者輸入
- 驗證來自外部契約的響應,
即。採用
require(external.send(amount))
- 在執行狀態更改操作之前驗證狀態條件,例如在
owned
契約情況下- 一般來說,你應該
require
更頻繁地使用,- 通常,它將用於函式的開頭。
用於
assert()
:
- 檢查上溢/下溢
- 檢查不變數
- 進行更改後驗證契約狀態
- 避免永遠不可能的情況。
- 一般來說,你應該
assert
少用- 通常,它將在您的功能結束時使用。
基本上,
assert
只是為了防止發生任何非常糟糕的事情,但條件不可能評估為假。歷史註釋:
require()
和功能在assert()
拜占庭分叉之前被添加到 Solidity 中,在v0.4.10
. 在拜占庭之前,它們的行為相同,但已經編譯為不同的操作碼。這意味著在拜占庭之前部署的一些合約在分叉後表現不同,主要區別在於開始退還未使用的 gas。