天天看點

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

.