iT邦幫忙

2022 iThome 鐵人賽

DAY 11
0
Web 3

Smart Contract Development Breakdown系列 第 11

Day 11 - Optimal Gas Comsumption

  • 分享至 

  • xImage
  •  

Optimal Gas Comsumption

Synchronization Link Tree


Gas & Gas Fee

Gas和汽車耗油的概念一樣,每輛車在理想情況下(不會折舊)的單位耗油量、油箱容量是不變的,然而油價是會起伏的。同理,已部屬合約的Gas Consumption是固定不變的,真正導致每次部屬同樣合約(程式碼)、呼叫相同函式的 Gasfee 都不一樣的原因來自於 Gas Price 是不斷變動的

如果真的得徹底了解合約中耗費的Gas,我們可以利用 REMIX Debugging Step Detail 取得合約到底執行了哪些 Operation,再利用Ethereum Yellow Paper 中的定義計算 Gas Consumption。也就是說實際上是 Operational Complexity 決定了 Gas Cost。

Optimal Gas Comsumption

如何減少 gas 的耗費:

  • 減少鏈上的資料
  • 使用 event 而非 storage
  • 最佳化變數宣告
  • 其他高階或寫法的節省方法

儲存資料的地點

  • 我們遇到的問題是在以太坊區塊鏈中儲存資料實在是太貴了,所以想要找到一個便宜儲存資料的方法。目前根據儲存位置的不同,有幾種解決方式:
    • 將資料儲存在鏈外,只儲存 proof(hash),例如:Notary,Merkle Proof(將 root 儲存在鏈上)
    • 儲存在分散式資料庫或跨鏈機制、擴容方案,例如:IPFS、Stateless contracts、L2、Side Chain
    • 從底層的角度來看,我們已經把 Event 的內容儲存在編譯並交易的區塊上了,何不直接利用這些 Event 來查看和調用資料。
  • 節省的想法是:如果這些資料並不需要被智能合約直接使用,那我們就只要把它放在 log 裡就好。也就衍伸出兩種想法:Store Path on Cahin vs. Store String in Events。
  • Storing on Ethereum. Analyzing the costs

Quick Way

  1. 減少判斷與不必要的程式碼: 有一些很簡單的方法可以稍微降低 Gas 的消耗,例如使用 && 或者 || 來提早結束判斷,或者是在引入 Library 的時候,不要把所有 Library 的所有程式碼都引入,只選擇我們會用到的部分程式碼(有一定風險)。
  2. 使用 calldata: 甚至是強制將 visibility 設為 external 可以讓 memory storation 被設為 calldata。而將參數設為 calldata 而非 memory 可以節省 gas 的原因在於 calldata 參數是唯讀不可改的(可改就需要更多 opCodes 的支援)。
  3. 時間複雜度: 遍歷(iterate)或修改陣列中的元素是非常昂貴的。使用 mapping 會是較好的選擇,我們必須要在知道自己正做什麼的情況下才選擇 Array !
  4. Local 域: 在進行迴圈運算、條件運算時最好選擇 Local Variable 進行運算,最後再把結果賦值給狀態變數。關於 Local Variable,如果今天有一個動態陣列被宣告在 Global,那在 Function 裡面如果我們去宣告一個新的 Local Array 複製外面這個 Global Array,然後 Function 都使用這個 Local Array 也會比較節省 Gas!
  5. 型態選擇: 另外一些資料型態也會比較節省 gas,例如:我們只宣告會用到的長度的陣列(bytes32),或者是使用 bytes32uint 而非 string。以及最基本的使用 mapping 來避免 Looping 一個 array
  6. Optimizer: 還有一個可以快速節省 Gas 的方法,那就是使用 Optimizer,關於這個部分可以看官方文件
  7. Payable: 同時 Payable functions 也會比 Non-Payable 便宜一點,因為 Non-Payable functions 需要有一個多餘的 opCodes 去處理 revert 別的合約嘗試匯款到這個函式的這個行為,而 Payable 因為是可以接收 ether 的,就不用處理這個 exception 的 opCodes。

Closing

Reference

How to Calculate

Source: Yellow Paper

Advanced Technique

Hidden Parameters / Context

ConsenSys/gpact 中有使用到 Hidden Parameters 的技巧,可以把 AuthVal 與 Function Selector 包在一起進行呼叫。

補充:Function Selector 太後面會導致 Gas 增加,如果想要更省的話可以把函式分開成獨立的合約 Library Deploy。

Assembly

即便便用 unchecked 也無法省掉 Casting 還有 /0 的 SafeMath 檢查,但如果使用 Assembly 就可以真的減少,這就是 ABDKSolmate 來做 sqrt 逼近的差別。

或者是產生 Merkle Proof 的時候,OpenZeppelin 使用的方法也是使用組合語言做更有效率的 hash:Source


最後歡迎大家拍打餵食大學生0x2b83c71A59b926137D3E1f37EF20394d0495d72d


上一篇
Day 10 - Cross-Contract Calls
下一篇
Day 12 - Contract Proxy: OpenZeppelin Upgradable Proxy
系列文
Smart Contract Development Breakdown30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言