我最近在重新學solidity,鞏固一下細節,也寫一個「Solidity 極簡入門」,供小白們使用(編程大佬可以另找教程),每週更新1-3 講。
所有代碼和教程開源在github:github.com/AmazingAng/WTFSolidity
這一講,我們介紹solidity 三種拋出異常的方法:error,require 和assert,並比較三種方法的gas 消耗。
異常
寫智能合約經常會出bug,solidity 中的異常命令幫助我們debug。
Error
Error 是solidity0.8 版本新加的內容,方便且高效(省gas)的向用戶解釋操作失敗的原因。人們可以在contract 之外定義異常。下面,我們定義一個TransferNotOwner 異常,當用戶不是代幣owner 的時候嘗試轉賬,會拋出錯誤:
在執行當中,error 必須搭配revert(回退)命令使用。
我們定義了一個transferOwner1() 函數,他會檢查代幣的owner 是不是發起人,如果不是,就會拋出TransferNotOwner 異常;如果是的話,就會轉賬。
Require
require 命令是solidity0.8 版本之前拋出異常的常用方法,目前很多主流合約仍然還在使用它。他很好用,唯一的缺點就是gas 隨著描述異常的字符串長度增加,比error 命令要高。使用方法:require(檢查條件,」異常的描述」),當檢查條件不成立的時候,就會拋出異常。
我們用require 命令重寫一下上面的transferOwner 函數:
Assert
assert 命令一般用於程序員寫程序debug,因為他不能解釋拋出異常的原因(比require 少個字符串)。他的用法很簡單,assert(檢查條件),當檢查條件不成立的時候,就會拋出異常。
我們用assert 命令重寫一下上面的transferOwner 函數:
三種方法的gas 比較
我們比較一下三種拋出異常的gas 消耗,方法很簡單,部署合約,分別運行寫的transferOwner 函數的三個版本。
error 方法gas 消耗:24445require 方法gas 消耗:24743assert 方法gas 消耗:24446
我們可以看到,error 方法gas cost 最少,其次是assert,require 方法消耗gas 最多!因此,error 既可以告知用戶拋出異常的原因,又能省gas,大家要多用!
總結
這一講,我們介紹solidity 三種拋出異常的方法:error,require 和assert,並比較了三種方法的gas 消耗。結論:error 既可以告知用戶拋出異常的原因,又能省gas。
推特: @0xAA_Science
社區: Discord | 微信群|官網wtf.academy
所有代碼和教程開源在github: github.com/AmazingAng/WTFSolidity