Solidity

require 和 assert 的區別以及 revert 和 throw 的區別

  • January 22, 2022

我正在查看文件require,並且正在尋找有關andassertthrowand之間區別的說明revert

斷言(布爾條件):如果條件為假,則中止執行並恢復狀態更改(用於內部錯誤)

要求(布爾條件):如果條件為假,則中止執行並恢復狀態更改(用於格式錯誤的輸入)

特別是關於assertand require,您如何在格式錯誤的輸入和內部錯誤之間劃清界限?

選擇assert()和時需要考慮兩個方面require()

  1. 氣體效率

  2. 字節碼分析

  3. 氣體效率


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。

引用自:https://ethereum.stackexchange.com/questions/15166