【開發智能合約 — Solidity系列】實作篇Ep.5 - 錯誤處理的機制(Error Handling)

更新於 發佈於 閱讀時間約 7 分鐘

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的文章請看這裡…

資源參考

留言
avatar-img
留言分享你的想法!
avatar-img
阿Han的沙龍
129會員
284內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
阿Han的沙龍的其他內容
2023/08/01
 相信常常聽到元宇宙的世界裡有一個並不陌生又有點距離的名詞「XR擴展實境」,包含了三大核心技術,分別為VR、AR與MR,其中VR與AR較為貼近我們的生活,那三者究竟有何不同呢? 就讓我們持續的看下去吧! VR 虛轉實,把假的變成真的 說到VR最直覺的就是想到VR頭盔吧,它可以帶給我
Thumbnail
2023/08/01
 相信常常聽到元宇宙的世界裡有一個並不陌生又有點距離的名詞「XR擴展實境」,包含了三大核心技術,分別為VR、AR與MR,其中VR與AR較為貼近我們的生活,那三者究竟有何不同呢? 就讓我們持續的看下去吧! VR 虛轉實,把假的變成真的 說到VR最直覺的就是想到VR頭盔吧,它可以帶給我
Thumbnail
2023/06/30
什麼是零知識證明(Zero-knowledge proof) 是一種密碼學的概念,用於在不揭示具體信息的情況下,證明某個主張的正確性。它允許一方(稱為證明者)向另一方(稱為驗證者)證明某個陳述的真實性,而無需透露任何關於陳述的具體細節..., 這根本文字天書啊,底下讓我們用白話文來說一下唄! 「我必
Thumbnail
2023/06/30
什麼是零知識證明(Zero-knowledge proof) 是一種密碼學的概念,用於在不揭示具體信息的情況下,證明某個主張的正確性。它允許一方(稱為證明者)向另一方(稱為驗證者)證明某個陳述的真實性,而無需透露任何關於陳述的具體細節..., 這根本文字天書啊,底下讓我們用白話文來說一下唄! 「我必
Thumbnail
2023/05/31
一套大型的智能合約通常都會拆分成許多小合約,並且透過匯入的方式拼裝而成,而這樣的匯入在Solidity世界中就是「Import」,就讓我們來看看「Import」到底怎麼運用吧! 假設目錄結構如下 example.sol other.sol 我們引入的方式就會是: import ‘./other.so
Thumbnail
2023/05/31
一套大型的智能合約通常都會拆分成許多小合約,並且透過匯入的方式拼裝而成,而這樣的匯入在Solidity世界中就是「Import」,就讓我們來看看「Import」到底怎麼運用吧! 假設目錄結構如下 example.sol other.sol 我們引入的方式就會是: import ‘./other.so
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
  Soildity是一種風格類似JavaScript的強型別高階語言,專門用來進行智能合約的開發及編程。本文敘述solidity的獨特之處。   
Thumbnail
  Soildity是一種風格類似JavaScript的強型別高階語言,專門用來進行智能合約的開發及編程。本文敘述solidity的獨特之處。   
Thumbnail
簡單的來說就是把同類型常用的功能打包在一起,讓其他開發者能夠重複使用,達到資源有效利用的效果,以軟體開發來說就是減少多餘的程式碼,而Solidity語言中,Library可以視為物件導向中的靜態類別,不需要產生實體就能使用,因此能有效的減少Gas。 當我們剛完成一份合約時難免因為設計尚未考慮周全而導
Thumbnail
簡單的來說就是把同類型常用的功能打包在一起,讓其他開發者能夠重複使用,達到資源有效利用的效果,以軟體開發來說就是減少多餘的程式碼,而Solidity語言中,Library可以視為物件導向中的靜態類別,不需要產生實體就能使用,因此能有效的減少Gas。 當我們剛完成一份合約時難免因為設計尚未考慮周全而導
Thumbnail
Solidity支援兩種特殊的函數,分別是Fallback以及Receive,一個是處理合約中不存在的功能時進行的回退機制,而另一個Receive則是負責收款後的動作,但兩者稱為特殊函數的原因主要是跟我們一般函數不同的地方於它們是屬於匿名的函數,也就是不用給定Function名稱,因此才會較為特殊,
Thumbnail
Solidity支援兩種特殊的函數,分別是Fallback以及Receive,一個是處理合約中不存在的功能時進行的回退機制,而另一個Receive則是負責收款後的動作,但兩者稱為特殊函數的原因主要是跟我們一般函數不同的地方於它們是屬於匿名的函數,也就是不用給定Function名稱,因此才會較為特殊,
Thumbnail
Solidity語言的錯誤檢查提供了Require()、Revert()、Assert(),這三種方便的API調用,而這三種用途分別不同,畢竟牽涉到瓦斯費的問題,因此才會與過往的程式語言有些許的差異, require()通常會被使用在輸入值的驗證檢查,因為它的特性主要是能夠退回剩餘的Gas fee,
Thumbnail
Solidity語言的錯誤檢查提供了Require()、Revert()、Assert(),這三種方便的API調用,而這三種用途分別不同,畢竟牽涉到瓦斯費的問題,因此才會與過往的程式語言有些許的差異, require()通常會被使用在輸入值的驗證檢查,因為它的特性主要是能夠退回剩餘的Gas fee,
Thumbnail
資料型態在合約當中扮演著什麼角色呢? 我們在「【開發智能合約 — Solidity系列】實作篇Ep.2 — 合約中的基本組成元素」有介紹過狀態變數可以儲存一些變化值,而儲存什麼類型的值就是所謂的資料型態,不同的資料型態可以處理的事物也有所不同,因此我們也需要了解一些基本的資料型態以及特性之後,未來開
Thumbnail
資料型態在合約當中扮演著什麼角色呢? 我們在「【開發智能合約 — Solidity系列】實作篇Ep.2 — 合約中的基本組成元素」有介紹過狀態變數可以儲存一些變化值,而儲存什麼類型的值就是所謂的資料型態,不同的資料型態可以處理的事物也有所不同,因此我們也需要了解一些基本的資料型態以及特性之後,未來開
Thumbnail
上一篇我們談到「【開發智能合約 — Solidity系列】實作篇Ep.1 — 看懂智能合約的脈絡」,大致上理解每個檔案的每份合約都是一個個的區塊,而這一個篇章主要著重於合約中的每個區塊的組成元素進行分項說明。 今天的範例會以簡單的銀行存款與提款流程進行示範,過程中將一步步的使用上述7種元素完成功能,
Thumbnail
上一篇我們談到「【開發智能合約 — Solidity系列】實作篇Ep.1 — 看懂智能合約的脈絡」,大致上理解每個檔案的每份合約都是一個個的區塊,而這一個篇章主要著重於合約中的每個區塊的組成元素進行分項說明。 今天的範例會以簡單的銀行存款與提款流程進行示範,過程中將一步步的使用上述7種元素完成功能,
Thumbnail
本篇章會以實際的程式碼來說明開發Solidity的組成脈絡與重要的區塊,讓我們不再害怕閱讀艱澀難懂的程式碼,並且具備基礎知識以後也能看懂外面的合約。 開源程式碼常常會面臨到法律的問題,因此License的宣告就變得非常重要,而Solidity也考慮到這一塊,因此特別規劃了一塊License宣告的區塊
Thumbnail
本篇章會以實際的程式碼來說明開發Solidity的組成脈絡與重要的區塊,讓我們不再害怕閱讀艱澀難懂的程式碼,並且具備基礎知識以後也能看懂外面的合約。 開源程式碼常常會面臨到法律的問題,因此License的宣告就變得非常重要,而Solidity也考慮到這一塊,因此特別規劃了一塊License宣告的區塊
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News