淺談Solidity與其他程式語言之差異-提高智能合約的安全性與節省Gas

更新於 2023/06/15閱讀時間約 12 分鐘
  Soildity是一種風格類似JavaScript的強型別高階語言,專門用來進行智能合約的開發及編程。使用前需要被編譯成EVM字節碼,然後在EVM或其他區塊鏈虛擬機上實行。
  仔細想想因為智能合約多涉及金流交易而且上鏈之後無法修改。此外,合約運行過程需要花費一定的Gas費用,因此做為智能合約的編程語言之一,Solidity會很重視安全性問題以及運算的複雜度。這導致Solidity的語法和寫法上有許多跟其他程式語言不同的地方。歡迎大家跟我一起來一邊學習Solidity、一邊看看Solidity有什麼有趣的獨特之處吧。

程式碼開頭

  當使用 Solidity 撰寫代碼時,為了避免編譯器出現警告,有兩行特定的註解需要添加。
  第一行註解用於指定該文件的使用許可(license)。這是一個可選的步驟,但在一些情況下,編譯器可能會提示你添加該註解。你可以在第一行註解中提供有關該文件的使用許可的相關信息。
  第二行註解用於指定編譯器的版本需求條件。這將確保你的代碼可以與指定版本的 Solidity 編譯器相容。你應該在第二行註解中明確指定所需的 Solidity 編譯器版本。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
  上述程式碼說明合約的授權許可證,這裡使用的是 MIT 授權。這是一種常見的做法,用於確定合約的授權許可證,以便其他開發者了解並遵守該許可證的規定。`pragma `關鍵字,它用於告訴編譯器使用的 Solidity 版本。在上面的例子中,`^0.8.4 `表示編譯器應使用 0.8.4 或更高版本的 Solidity。這是為了確保合約在特定的 Solidity 版本下進行編譯。

安全性

由於 Solidity 用於智能合約開發,被大量用作金流或價值有關的交易,安全性是非常重要的考慮因素。為大家統整 Solidity 具有的一些安全性的語法機制和設計模式,旨在防止常見的漏洞和攻擊,例如重入攻擊(reentrancy attack)、整數溢出等( overflow 、underflow)。
1.報錯:
  Solidity中有requirerevertassert 三種函式用於報錯並終止交易。requirerevert 被建議用來檢查合約狀態或 input,例如最常使用的 require 其實就有點像if 語法,當判定錯誤時整個交易會失敗,並且跳出預設的錯誤訊息。撰寫者可以用這方法來確保合約接收到的資料符合預期,且交易中止時可以拿回沒有用到的 Gas fee。而 revert 類似於 require 但是語法本身不帶有判斷功能,失敗訊息則需要用error 加以定義。最後 assert 則更適合用來檢查重要安全問題,因為他會吃掉所有Gas fee 所以通常將它擺在函式的最後面,以檢查最終的條件有沒有符合需求,不過此函式通常較少被使用。
2.限制權限:
  雖然別的程式語言也有類似的功能,但solidity 更大量使用修飾器(modifier)來限制函式的執行權限,例如只讓特定帳戶或合約才能執行某些操作。這有助於防止未授權的帳戶執行具有風險的操作,另外也減少重複的程式碼以節省Gas。
  以下列舉內建的modifier,都是很常用的功能:
  • public:指定函式或狀態變量為公開可訪問的,可以在合約內部和外部被調用或訪問。
  • private:指定函式或狀態變量為僅合約內部可訪問的,無法從合約外部進行調用或訪問。
  • internal:指定函式或狀態變量為合約內部和合約繼承者可訪問的,無法從合約外部進行訪問。
  • external:指定函式為僅能從合約外部調用的,無法在合約內部被直接調用。
  • payable:指定函式接受以太幣的支付,可以接收價值。
  另外撰寫人也可以自定義modifier來應付自己的需求,例如寫一個限定只有合約的擁有者才可以觸發的modifier
3.interface(接口):
  interface是智能合約的骨架,interface乍看下像是一個合約,不過具有一些約束條件:
  • 不能包含狀態變量
  • 不能包含建構子(constructor
  • 不能繼承除 interface外的其他合约
  • 所有函數都必需是 external且不能有函数體
  • 繼承 interface 的合约必需實現包含但不限於interface定義的所有功能
通過定義一個 interface,可以在多個合約中實現相同的介面,從而達到代碼的共享和重用。例如常見ERC20或ERC721的interface,可以提供合約之間的標準化介面,促進代碼重用和測試,同時提高代碼的可讀性和可維護性。
4.數學運算安全 :
  使用 OpenZeppelin 的 SafeMath 函式庫 可以有效的避免數學運算時可能造成的漏洞,例如整數溢位、加減乘除順序造成的整數與浮點數格式問題。使用SafeMath函式庫可以確保數值大小適用於指定的資料型態。另外,在remix IDE的0.8.0編譯版本以後,也有檢查整數溢位的功能。
5.Checks-Effects-Interactions Pattern(檢查-影響-交互模式):
  Checks-Effects-Interactions 模式是一種在撰寫智能合約時的設計模式,旨在提高合約的安全性和可預測性。該模式強調合約應該按照特定的順序執行操作,先進行檢查,再執行內部操作,最後進行交互操作 :
  • Checks(檢查):在合約執行任何操作之前,應該先進行必要的檢查和驗證。這些檢查可以包括驗證調用者的權限、檢查數據的有效性、驗證合約狀態的一致性等。通過進行檢查,可以避免不必要的操作和防止潛在的漏洞。
  • Effects(影響):在確定檢查通過後,合約應該執行相應的操作並修改合約的狀態。這些操作可以包括更新變量的值、修改數據結構、觸發事件等。在此階段,合約應該只對自身的狀態進行修改,而不應該與其他合約或外部世界進行交互。
  • Interactions(交互):在完成所有內部操作後,合約可以與其他合約或外部世界進行交互。這包括與其他合約進行調用、發送資金、觸發事件等。在進行交互操作時,合約應該謹慎處理,確保適當的權限檢查和數據驗證,以防止意外情況和安全漏洞。
  Checks-Effects-Interactions 模式的目的是確保合約操作的順序和一致性,從而減少潛在的漏洞和不可預測的行為,提高合約的可靠性、可讀性和維護性,使合約的行為更易於理解和追蹤。例如 token 額度的改變應該在 token 所有權的轉移之前,被用來避免重入攻擊。

節省Gas

在以太坊區塊鏈上執行智能合約或執行運算需要消耗 Gas,也就說明的執行合約需要消耗一定的以太幣。撰寫程式的工程師需要再考慮實現合約功能和預期的使用情況下,最有效的程式設計,來減少 Gas 費用並達到適當的成本效益。因此撰寫 solidity 時有一些可靠的方法可以降低 Gas 的使用:
1.使用 mapping (映射):
  solidity 中的 mapping 資料結構常用作表示「使用者ID-錢包地址」、「錢包地址-餘額」之間的關係,該結構由於在設計上具有包括儲存空間較小和高效查找的優點而被大量使用:
  • 儲存空間效率:mapping 使用哈希表(Hash Table)的數據結構,將鍵(Key)映射到值(Value)。相較於陣列或其他結構,mapping 具有較小的儲存空間需求。在 Solidity 中,只有被使用的鍵值對才會佔用實際儲存空間。
  • 高效查找時間:由於 mapping 使用哈希表,查找特定鍵的值的操作時間複雜度是常數級別(O(1)),這意味著在mapping中查找特定鍵的操作速度與映射的大小無關。
  • 適合關聯數據:mapping 非常適合用於關聯數據,例如將地址映射到餘額、ID映射到物品等。這樣的關聯數據結構常見於智能合約中的代幣餘額、所有權追蹤等場景。
  雖然mapping在 Solidity 中有這些優點,但在撰寫時還是需要小心使用。因為mapping可能存在一些坑,例如需要處理未初始化鍵的情況,以及不支援迭代等。
2.減少迴圈的使用或避免複雜的迴圈:
  由於迴圈需要重複執行相同的操作,並且每次迭代都需要消耗一定的計算資源,因此 solidity 裡面使用迴圈會大量的耗費 Gas fee,特別是跌代次數過多、多重迴圈結構、在迴圈中呼叫外部資源進行讀取,都會大大地加劇運算量。有些智能合約就是不當的使用迴圈使得部署之後無法使用,因為該合約在交易過程耗費的Gas fee大於區塊開採Gas的上限。
3.考慮使用event (事件)還是 新變量 :
  event 會在合約中設定好的條件下被觸發,並且將 event 的數據儲存在區塊鏈上永久保存並供檢視,因此常被用作監視或處理合約異常狀態的手段之一。 因此如果不是需要追蹤合約內部狀態的改變而是向外表達狀態時,使用 event 就會比創建一個新變量更適用,而且 event 所消耗的 Gas 也比較少。
4.選擇適當的儲存位置:
  solidity數據儲存位置有三類:storagememorycalldata。默認情況下數據都會存成 storage,存成 storage 的資料會放在區塊鏈上,所需的 gas 費用也比 memorycalldata 還要高。所以如果只是在合約運行中暫時需要用到的變量,可以存成 memory calldata 就好。而 calldata 相較於 memory 是唯讀的,因此從外部給值之後就不能修改值,用意在保護數據。
5.使用繼承( Inheritance ):
  solidity具有物件導向的性質,其中合約、建構子(constructor)、修飾器(modifier)可以被繼承。選擇合適的父合約來繼承相對應的功能可以避免重複成冗的程式碼,並可以節省部署時 Gas 的使用量。繼承被大量使用者驗證過的合約看來也是一個較安全的選擇。

交易

智能合約跟虛擬貨幣的交易實在密不可分,以太坊上的交易內容經常牽扯到ETH的接收與發送。Solidity也有提供專用的接收、發送ETH的函式,給撰寫智能合約的工程師使用。
1. 接收ETH:
  包括receivefallback兩種函式。receive函式在一個合約中只能有一個,而且只用於接收ETH。fallback函式可以用於接收ETH或ERC20等,它可以在調用合約不存在的函式時被觸發,所以也被用於代理合約。fallbackreceive需要`external` 與`payable`來修飾以接收ETH。
2.發送ETH:
  可以使用transfer()send()call(),其中call()沒有Gas的限制,所以使用call函式時接收方的接收函式就可以寫的比較複雜。而transfersend函式就有2300 Gas的限制,撰寫人需要考慮接收方的接收函式不能太複雜,不然交易會失敗。其中transfer在交易失敗時會自帶revert功能。
  在合約安全性方面Alice提供了一篇文章介紹常用的合約掃描工具,讀者可以利用這些工具掃描合約。如果未來還有發現其他Solidity與其他程式語言的差異,我會再與大家分享,如果各位讀者還有其他想知道或是想分享的,歡迎各位留言給我知道。也期待solidity語言在未來能有更有趣的發展~
___________________________________________________________________________
作者阿原目前從事區塊鏈資料分析工作,對區塊鏈的經濟架構、事件發展有很大的興趣,並希望能將相關的區塊鏈知識分析並且統整給大家。如果喜歡我的文章,或是想獲得更多區塊鏈大小事,歡迎關注我的vocus帳號
另外,我已經加入由趨勢科技防詐達人所成立的方格子專題-《區塊鏈生存守則》,在那裡我會跟其他優質的創作者一起帶大家深入瞭解區塊鏈,並隨時向大家更新區塊鏈資安事件。
> 追蹤《區塊鏈生存守則》學習如何在區塊鏈的世界保護自己
> 關注防詐達人獲得其他最新詐騙情報
avatar-img
33會員
176內容數
我們整理了web3相關的熱門資安問題,包含加密貨幣投資詐騙、盜版NFT、空投釣魚和區塊鏈重大資安事件懶人包等等,並提供最完整的辨識方法教學,讓大家從0到1學習如何保護自己
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
防詐達人的沙龍 的其他內容
近日有幣安用戶收到來自幣安的遷移通知,稱幣安就用戶即將關閉服務,並附上一個很像是幣安的釣魚連結。請小心!網址一定要看清楚,一不小心輸入帳號密碼可能會導致幣安帳戶被盜,損失大筆資金。
繼前陣子的「您所在地區帳戶將終止服務」幣安釣魚簡訊後,近期又出現假幣安郵件,通知收件者點擊按鈕以領取比特幣,實際上按鈕連結到的是幣安釣魚頁面,一旦登入你的幣安帳戶將會被盜用,甚至虛擬貨幣瞬間被轉走
今天我們會開始深入探討到EVM(以太坊虛擬機)上的一點點基礎知識。 若您是一個常常在etherscan.io上追蹤交易的朋友,一定對上面提到的各項資訊並不陌生。但我們觀察一筆交易時會發現,etherscan.io又額外提供了Internel Txns,這又是什麼呢?本篇將一同來探討。
近年來隨著元宇宙Metaverse的聲浪,NFT與虛擬貨幣變成人人嚮往的新投資商機,NFT遊戲也以邊玩邊賺錢「Play to earn」模式吸引眾多玩家。然而,近期開始出現一些「假NFT遊戲」,打著元宇宙的旗幟實行真投資詐騙,企圖欺騙想踏入幣圈的新手
在前幾篇的文章中。有和各位分享了使用Ganache來模擬一個以太坊主網進行交易,也嘗試使用了web3.py來開發區塊鏈互動程式。相信對您而言,一定有更深入探索區塊鏈交易的需求。本篇想和各位介紹一個Ganache的神奇功能:解鎖任意帳號
在上一篇文章中,有和您分享了使用Ganache模擬了一個以太坊主網。想必您已經迫不及待的想對它進行更深入的了解了。本篇預計會使用Python來和您建立好的模擬網路進行互動。在開發套件的細節上我們並不會很深入的地為您進行解釋,而會透過一些簡單的例子來引導一個學習的方向。
近日有幣安用戶收到來自幣安的遷移通知,稱幣安就用戶即將關閉服務,並附上一個很像是幣安的釣魚連結。請小心!網址一定要看清楚,一不小心輸入帳號密碼可能會導致幣安帳戶被盜,損失大筆資金。
繼前陣子的「您所在地區帳戶將終止服務」幣安釣魚簡訊後,近期又出現假幣安郵件,通知收件者點擊按鈕以領取比特幣,實際上按鈕連結到的是幣安釣魚頁面,一旦登入你的幣安帳戶將會被盜用,甚至虛擬貨幣瞬間被轉走
今天我們會開始深入探討到EVM(以太坊虛擬機)上的一點點基礎知識。 若您是一個常常在etherscan.io上追蹤交易的朋友,一定對上面提到的各項資訊並不陌生。但我們觀察一筆交易時會發現,etherscan.io又額外提供了Internel Txns,這又是什麼呢?本篇將一同來探討。
近年來隨著元宇宙Metaverse的聲浪,NFT與虛擬貨幣變成人人嚮往的新投資商機,NFT遊戲也以邊玩邊賺錢「Play to earn」模式吸引眾多玩家。然而,近期開始出現一些「假NFT遊戲」,打著元宇宙的旗幟實行真投資詐騙,企圖欺騙想踏入幣圈的新手
在前幾篇的文章中。有和各位分享了使用Ganache來模擬一個以太坊主網進行交易,也嘗試使用了web3.py來開發區塊鏈互動程式。相信對您而言,一定有更深入探索區塊鏈交易的需求。本篇想和各位介紹一個Ganache的神奇功能:解鎖任意帳號
在上一篇文章中,有和您分享了使用Ganache模擬了一個以太坊主網。想必您已經迫不及待的想對它進行更深入的了解了。本篇預計會使用Python來和您建立好的模擬網路進行互動。在開發套件的細節上我們並不會很深入的地為您進行解釋,而會透過一些簡單的例子來引導一個學習的方向。
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
在繪本的世界裡,無字繪本的起源帶著一種教學的色彩。這些書籍沒有文字,目的在於讓年輕的讀者試圖從圖像中挖掘出隱藏的話語。這類書籍明確提出了一個原則:「讓圖片說話」。最初,這類無字繪本是為那些還未學會閱讀的孩子設計的。許多設計理念普遍認為,既然孩子不會讀文字,那麼他們應該能夠輕易地解讀一系列的圖像。
Thumbnail
人人都有自己的恐懼 如何去面對每一次的恐懼來臨呢? 如果不曾直面也許就難以長出相對的勇氣 / 在長濱僻靜時的自我探索中 聊到過我害怕昆蟲 但夥伴覺得我很勇敢 因為當我們一起在室內遇到小蜘蛛時我的反應 但蜘蛛不是我最怕的 我最怕的是大蟑螂 或者說會飛的、移動速度
Thumbnail
被稱為「離別的一族」的長壽種伊歐夫人,外表從青少年時期便停止生長。某天,梅薩蒂軍進攻族地,伊歐夫人就此死散流離,而少女瑪琪亞因此開始了無止盡的流浪。她在途中撿到一名襁褓中的孤兒。四季流轉,艾瑞爾抽長為少年,瑪琪亞卻依舊是少女模樣,在動盪的時代與心緒裡,他們相處的時光因而逐漸生變,再度面臨漫長的別離…
Thumbnail
前言: 央行在昨天6/13的理監事會議後,宣佈今天6/14上路第6波選擇性信用管制,主要內容有兩點,第1點是「調升存款準備率1碼(0.25%)」第2點是「調降自然人特定地區第2戶購屋貸款最高成數上限為6成」,所謂的「特定地區」就是直轄市六都與新竹縣市。
Thumbnail
文章將搜尋引擎的運作原理分為三個段落進行介紹,並強調網站結合有效的SEO策略對提升曝光度的重要性。
Thumbnail
為什麼會有合約的誕生? 大家想過這個問題嗎? 試想,當陌生人與陌生人之間如果要產生與金錢相關的交易時,在沒有第三方機構的見證下,我想一般人應該也會存在著「不信任」的狀況產生,因此造就了「合約」的誕生,而這個「合約」主要目的在於確保雙方能夠在不損害對方的利益下完成交易的一種約定,其中包括了雙方的資訊、
昨晚睡觉前,我把手机放在枕头边,躺在床上,听Youtbue 上,一位叫做LT视界的大咖讲解沈栋发表的《红色赌盘》中的一些细节。 这位大咖的分析非常到位。我之前也听过很多沈栋在台湾的访谈节目。我当初对于这位作者的印象还不错,觉得他思路很敏捷,谈吐不凡,见识广,的确是很有感染力,吸引力和洞察力。是个了不
今日看到一句话让我感触颇深,想到了成长与经历这些字眼,觉得有道理便记下这段话; 离群索居者,不是野兽便是神灵。 尤其是在学生时代这种感觉尤为强烈,却不知都是一群连价值观都没形成的孩子。这种现象在学校中尤为突出。 被孤立的人啊!愿你成为上帝的宠儿。
「臨時工」的定義:今天有上工有收入,沒上工沒有收入,沒有任何假別的適用。 「計時人員」的定義:今天因故無法上班需要請假,至於是什麼假,得依據「勞工請假規則」去定義。 「臨時工」的「勞動契約」就沒有從屬性的適用。 舉例 「人格」從屬性:既然有做有錢沒做沒錢,也無需請假告知。惟有簽訂為「定期契約工」時,
Thumbnail
面對朋友在文創市集的鎩羽,也整理了目前文創市集的窘境與概況,回到閒聊的話題:藝術工作者在面對目前社群媒體型態,形象的展現是否會影響藝術商品? 其實整個藝術市場是一個「象徵交換」,藝術工作者透過創作的作品,將自我的意識、美學、思想等概念透過作品的符碼、符號來呈現,收藏家因自身的主觀認同與喜愛、或主觀的
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
在繪本的世界裡,無字繪本的起源帶著一種教學的色彩。這些書籍沒有文字,目的在於讓年輕的讀者試圖從圖像中挖掘出隱藏的話語。這類書籍明確提出了一個原則:「讓圖片說話」。最初,這類無字繪本是為那些還未學會閱讀的孩子設計的。許多設計理念普遍認為,既然孩子不會讀文字,那麼他們應該能夠輕易地解讀一系列的圖像。
Thumbnail
人人都有自己的恐懼 如何去面對每一次的恐懼來臨呢? 如果不曾直面也許就難以長出相對的勇氣 / 在長濱僻靜時的自我探索中 聊到過我害怕昆蟲 但夥伴覺得我很勇敢 因為當我們一起在室內遇到小蜘蛛時我的反應 但蜘蛛不是我最怕的 我最怕的是大蟑螂 或者說會飛的、移動速度
Thumbnail
被稱為「離別的一族」的長壽種伊歐夫人,外表從青少年時期便停止生長。某天,梅薩蒂軍進攻族地,伊歐夫人就此死散流離,而少女瑪琪亞因此開始了無止盡的流浪。她在途中撿到一名襁褓中的孤兒。四季流轉,艾瑞爾抽長為少年,瑪琪亞卻依舊是少女模樣,在動盪的時代與心緒裡,他們相處的時光因而逐漸生變,再度面臨漫長的別離…
Thumbnail
前言: 央行在昨天6/13的理監事會議後,宣佈今天6/14上路第6波選擇性信用管制,主要內容有兩點,第1點是「調升存款準備率1碼(0.25%)」第2點是「調降自然人特定地區第2戶購屋貸款最高成數上限為6成」,所謂的「特定地區」就是直轄市六都與新竹縣市。
Thumbnail
文章將搜尋引擎的運作原理分為三個段落進行介紹,並強調網站結合有效的SEO策略對提升曝光度的重要性。
Thumbnail
為什麼會有合約的誕生? 大家想過這個問題嗎? 試想,當陌生人與陌生人之間如果要產生與金錢相關的交易時,在沒有第三方機構的見證下,我想一般人應該也會存在著「不信任」的狀況產生,因此造就了「合約」的誕生,而這個「合約」主要目的在於確保雙方能夠在不損害對方的利益下完成交易的一種約定,其中包括了雙方的資訊、
昨晚睡觉前,我把手机放在枕头边,躺在床上,听Youtbue 上,一位叫做LT视界的大咖讲解沈栋发表的《红色赌盘》中的一些细节。 这位大咖的分析非常到位。我之前也听过很多沈栋在台湾的访谈节目。我当初对于这位作者的印象还不错,觉得他思路很敏捷,谈吐不凡,见识广,的确是很有感染力,吸引力和洞察力。是个了不
今日看到一句话让我感触颇深,想到了成长与经历这些字眼,觉得有道理便记下这段话; 离群索居者,不是野兽便是神灵。 尤其是在学生时代这种感觉尤为强烈,却不知都是一群连价值观都没形成的孩子。这种现象在学校中尤为突出。 被孤立的人啊!愿你成为上帝的宠儿。
「臨時工」的定義:今天有上工有收入,沒上工沒有收入,沒有任何假別的適用。 「計時人員」的定義:今天因故無法上班需要請假,至於是什麼假,得依據「勞工請假規則」去定義。 「臨時工」的「勞動契約」就沒有從屬性的適用。 舉例 「人格」從屬性:既然有做有錢沒做沒錢,也無需請假告知。惟有簽訂為「定期契約工」時,
Thumbnail
面對朋友在文創市集的鎩羽,也整理了目前文創市集的窘境與概況,回到閒聊的話題:藝術工作者在面對目前社群媒體型態,形象的展現是否會影響藝術商品? 其實整個藝術市場是一個「象徵交換」,藝術工作者透過創作的作品,將自我的意識、美學、思想等概念透過作品的符碼、符號來呈現,收藏家因自身的主觀認同與喜愛、或主觀的