Solidity 智慧合約字節碼優化

胡家維 Hu Kenneth
My blockchain development Journey
4 min readSep 21, 2023

source : https://medium.com/@uzair.afzal/smart-contract-bytecode-downsizing-6bcfeb237a4c by M. Uzair Afzal

Solidity 智能合約字節碼大小的最大限制在 24 kb — 25 kb 之間。具有超出此範圍的字節碼的合約無法部署到以太坊主網路。來自官方文件:

2016 年 11 月 22 日, Spurious Dragon 硬分叉引入了EIP-170,增加了 24.576 kb 的智能合約大小限制。”

讓我們仔細看看,更好地理解為什麼我們有這樣的限制,以及如何將合約字節碼大小保持在 24K 位元組以下。

以太坊區塊鏈:優化智慧合約字節碼大小

為什麼有字節碼限制?

為了防止 DoS(拒絕服務)攻擊,最大數量有限制。可以部署到區塊鏈的合約的大小(部署字節碼的大小)。

原因

當合約大小增加時,呼叫者的Gas 使用量不會增加太多,因為他們只需支付函數執行所需的Gas 使用量,但礦工運作函數的資源使用量會增加,因為他們必須將更大的合約讀入RAM現在。因此,攻擊者可以建立一個非常大的合約,然後呼叫其中的一個小函數。這或許會讓攻擊者付出不到一美元的代價,但礦工的 RAM 可能會因為讀取如此巨大的合約而崩潰,從而掛起他們的系統。鑑於所有礦工都運行每筆交易,每個人的電腦都會被凍結,所有人的網路服務都會中斷。這就是為什麼合約規模限制至關重要。

如何節省字節碼大小?

若要減少合約的位元組大小,請遵循以下提示(根據它們對合約字節碼大小減少的影響標記為“中”“大” ):

  • [ MEDIUM ]:組合函數:不要建立多個函數,而是將程式碼組合成一個函數
  • [ MEDIUM ]:內嵌函數呼叫:不是建立函數,而是在同一呼叫函數中處理函數。放棄其他功能。
  • [ MEDIUM ] 建立較少的記憶體變數:不要在記憶體中的函數內創建大量變數。相反,直接使用來自 calldata 的傳入參數
  • [ MEDIUM ]:自訂錯誤和小錯誤字串:應使用小錯誤字串和自訂錯誤(例如錯誤 Unauthorized();),而不是長字串。來自 Solidity 文件:

「Solidity 0.8.4 中引入了自訂錯誤。它們是減少合約大小的好方法,因為它們被 ABI 編碼為選擇器(就像函數一樣)”

  • [ LARGE ]:使用編譯器最佳化:編譯器最佳化可以做很多事情,例如刪除未使用的程式碼、重新排序函數呼叫、內聯函數、組合函數等。在 Hardhat 設定檔中 — 如果讀者熟悉 Hardhat生態系統並使用它- 添加此程式碼以在編譯過程中啟用編譯器最佳化:
solidity: {
compilers: [
{
version: "0.8.21",
settings: {
optimizer: {
enabled: SHOULD_ENABLE_OPTIMIZATION, // true or false
runs: OPTIMIZER_RUNS,
/*
Runs:
Default: 200
Min: 1
Max: 4.2 billion = (2 ^ 32) - 1

Runs determine for how many function calls a
contract function should be optimized. According
to the docs:
> 01. Smaller value means cheap deployment but expensive function calls
> 02. Larger value means expensive deployment but cheaper function
*/
},
},
},
],
},

閱讀Solidity 官方文檔,以更好地了解運行參數及其對智能合約優化的影響。現在,當您使用以下命令編譯合約時:

npx hardhat compile

它們將在編譯過程中進行最佳化。

  • [ LARGE ]:單獨合約:將您的合約拆分為多個合約。這對於減少單一合約的字節碼大小有巨大的影響
  • [ LARGE ]:更多函式庫用法:來自以太坊文件:

“庫與合約類似,但其目的是僅在特定位址部署一次,並且透過 DELEGATECALL 重複使用其程式碼。”

使用函式庫,而不是自己編寫所有內容。庫使用“delegateCall”來保留上下文並運行外部程式碼來修改呼叫者的合約狀態。因此,當函式庫函數不是內部函數時(因為內部成員由子級繼承!),它們可以節省大量字節碼大小。然而,如果它們是內部的,它們將全部添加到基礎合約中,從而增加其大小。例如,OpenZeppelin的幾個函式庫中的幾乎所有函數都標記為「內部」。因此,它們被添加到基礎合約中,增加了合約的字節碼大小。

直到下一次,

Uzair

--

--

胡家維 Hu Kenneth
My blockchain development Journey

撰寫任何事情,O型水瓶混魔羯,咖啡愛好者,Full stack/blockchain Web3 developer,Founder of Blockchain&Dapps meetup ,Udemy teacher。 My Linktree: https://linktr.ee/kennethhutw