【開發智能合約 — Solidity系列】實作篇Ep.5 - 錯誤處理的機制(Error Handling)
Solidity語言的錯誤檢查提供了Require()、Revert()、Assert(),這三種方便的API調用,而這三種用途分別不同,畢竟牽涉到瓦斯費的問題,因此才會與過往的程式語言有些許的差異,
Require
require()通常會被使用在輸入值的驗證檢查,因為它的特性主要是能夠退回剩餘的Gas fee,我們也知道瓦斯費在區塊鏈的成本是昂貴的,因此這些檢查都有助於不必要的浪費,主要使用方式為:
require(判斷式, 訊息)
... contract Example { ... function withdraw(uint amount) public pure { uint total = 100; /// @dev 提款的數量必須低於總額度 /// @notice 使用require(), 當條件不滿足時將退回剩下的瓦斯費,所以通常會放在前面 require(amount <= total, "amount must less then total"); ... } }
Revert
revert()顧名思義為撤銷的意思,也就是通常不符合某些條件時則進行撤銷,與reqiure一樣是會退回剩餘的Gas fee,那看到這邊可能心裡會產生一些疑問,比如說為什麼不用require就好了呢? 兩者語意事實上是有差異的。
- require表述的是「必須要滿足什麼條件」。
- revert則表述「當什麼條件未被滿足」時進行撤回。
/// @dev 自訂錯誤類型: 資金不足 /// @param requested 要求的資金 /// @param available 可用的資金 error NotEnoughFunds(uint requested, uint available); function ... { /// @dev 提款的金額不能大於存款 /// @notice 若提出的金額超過存款總額,則退回撤銷並退回狀態。 if (amount > total) { revert NotEnoughFunds(amount, total); } }
另外revert使用的方式有以下三種:
revert CustomError(…)
revert(”message”)
revert()
剛開始可能會有些霧裡看花,這麼多不同的承接方式與參數,但撰寫一段時間過後就會相當熟練,且在合適的時機使用正確的方式。
Assert
assert()跟require()一樣,算是進行檢核的機制,必須滿足某些條件才能繼續執行,但最大的差異在於當條件不滿足時,會耗盡Gas fee,因此通常用來處理比較嚴重且不易發生的錯誤,例如邊界值、特殊條件…等程式內部錯誤,也是最不常被使用的錯誤處理方法。
/// @dev 提款的額度必須是正整數 assert(amount > 0);
Try … Catch
相信這種語法如果有在開發其他程式的朋友應該非常熟悉,沒錯,Solidity亦提供這種錯誤處理機制,但值得注意的是在智能合約的世界中僅適合外部調用,白話來說就是A合約去嘗試使用B合約的功能,語法結構主要為:
try ...使用A合約進行什麼操作 { ...成功之後的處理 } catch ...什麼類型的錯誤 { ...進行什麼處理 } catch ...什麼類型的錯誤 { ...進行什麼處理 }
而錯誤的捕捉類型又分為以下四種方式,分別說明:
contract Example { ... } contract Runner { Example public example; constructor() { example = new Example(); } function exec() public view { uint errorCount = 0; try example.withdraw(101) { // 提款成功之後... } catch Error(string memory /*reason*/) { // 這種錯誤類型主要是處理帶有錯誤訊息的錯誤處理函數: require(..., "錯誤訊息")、revert("撤銷訊息") errorCount++; } catch Panic(uint /*errorCode*/) { // 這種錯誤類型主要處理assert(...)這種內部錯誤 errorCount++; } catch (bytes memory /*lowLevelData*/) { // 這種錯誤通常發生在更低階的處理,像是在解譯(decode)的階段 errorCount++; } catch { // 如果不想知道錯誤訊息或者原因時,可以直接用catch { ... }進行錯誤的對應處理。 } } }
結語
原來一個簡單的錯誤處理背後其實並不簡單…,與「金錢」有關的產品或服務最重要的莫過於嚴謹的審查機制,因此很多錯誤都是不能被容忍的,故而錯誤處理的機制就顯得非常重要,處理方式也相較於大部分程式語言有所不同,主要是因為納入了Gas fee的緣故,以此為鑑,當開發者進行開發智能合約時的錯誤處理也要非常小心,哪個使用情境要用哪一種錯誤處理的技巧並且不浪費Gas fee的狀況下,真的是對於智能合約開發者來說是一大挑戰,相信我們只要讀懂這些錯誤處理的概念後,未來開發時就會特別注意。
今天的範例都在這裡「📦 solidity-remix-toturial/Ep5」歡迎自行取用。
下一篇我們來談談可視範圍吧:
⏭️【開發智能合約 — Solidity系列】實作篇Ep.6 — 關於可視範圍(Visibility)
喜歡撰寫文章的你,不妨來了解一下:
Web3.0時代下為創作者、閱讀者打造的專屬共贏平台 — 為什麼要加入?
歡迎加入一起練習寫作,賺取知識,累積財富!
資源參考
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!
- 来自作者
- 相关推荐