如何在 Solidity 智慧合約中優化瓦斯費用
本指南提供實用的逐步演練,說明在 Solidity 中撰寫智慧型契約時,如何優化瓦斯成本。
為什麼瓦斯最佳化很重要?
氣體最佳化是智慧型契約開發的重要部分。 它有助於確保智慧型契約即使在網路高度擁塞的情況下,仍能保持高效率與成本效益。 透過降低合約執行的計算開銷,開發人員可以降低交易費用、加快確認時間,並改善其 dApp 的整體可擴展性。
對開發人員而言,氣體最佳化就是編寫乾淨、安全且可預測的程式碼,以減少不必要的計算。 對使用者而言,這是確保他們能與您的合約互動,而無需支付過高的費用。
為什麼對 Kaia 特別重要
隨著超過 83 個 Mini dApp 的推出,Kaia 區塊鏈已經成為交易量領先的 EVM 相容鏈,其主要動力來自這些上鏈應用程式的爆炸性增長。
每個 Mini dApp 都依賴智慧型契約來執行上鏈動作。 無論是鑄造物品、下注或管理遊戲中的資產,每一次契約互動都會消耗瓦斯。 如果不進行優化,這些 dApp 可能很快就會變得太昂貴,讓使用者無法與之互動,尤其是在規模較大的情況下。
這就是為什麼瓦斯效率不僅僅是一個很好的條件。 這是必要的。 在 Kaia 上進行建置的開發人員必須確保每個函式呼叫都經過最佳化,在保留功能性與安全 性的同時,將成本降至最低。
氣體最佳化技術
儲存包裝
在區塊鏈上儲存和檢索資料是最耗氣的作業之一,尤其是當資料必須跨交易和區塊持續存在時。 在 Solidity 中,這些資料會儲存在合約儲存中,這是永久性的,並且會產生瓦斯成本。 為了降低這些成本,開發人員必須仔細優化儲存的使用方式,尤其是在宣告狀態變數時。
Kaia 虛擬機器 (KVM) 將合約資料儲存在稱為儲存槽的單元中。 每個儲存槽正好可以容納 256 位元組 (32 位元組) 的資料。 Solidity 資料類型有不同的大小 - 例如,bool 是 1 位元組,而位址是 20 位元組。
透過一種稱為儲存包裝的技術,我們可以將較小的變數緊密排列,使其能夠容納在單一 32 位元組的儲存槽中。 這有助於減少瓦斯用量,因為從一個儲存槽讀取或寫入的成本遠低於存取多個儲存槽。
讓我們考慮以下範例:
分解:
在未最佳化版本 (SlotUnOptimized) 中,Solidity 會這樣儲存結構:
- 位址至 -> 需要 20 位元組 -> 儲存在插槽 0 中
- uint256 numConfirmations -> 需要 32 位元組 -> 儲存在插槽 1 中
- uint80 值 (10 位元組) 和 bool 執行 (1 位元組) -> 儲存於插槽 2
儘管value和executed變數很小,除非明確地重新排序,否則 Solidity 會因為對齊填充的關係,將它們放在自己的儲存槽中。 因此,此結構使用 3 個儲存槽,也就是儲存作業的瓦斯成本是一般的 3 倍。 但是,address (20 位元組) + uint80 (10 位元組) + bool (1 位元組)
的總大小為 31 位元組,落在單一插槽的 32 位元組限制之內。 只要重新排列宣告的順序,讓較小的變數集中在一起,Solidity 就可以將它們打包到同一個槽中。 這就是儲存包裝的精髓。
如上圖所示,在最佳化版本 (SlotOptimized) 中,所有較小的變數都會彼此相鄰放置,讓編譯器可以將變數儲存在較少的插槽中 - 降低部署和執行時的瓦斯成本。
快取記憶體儲存
除了變數在儲存槽中的佈局方式之外,瞭解與存取和修改儲存相關的瓦斯成本也很重要。
Kaia 虛擬機器上每個儲存插槽的成本: 初始化 (第一次寫入) 需 20,000 gas 更新 (後續寫入) 需 5,000 gas 正因如此,將直接儲存讀取和寫入的次數降至最低是非常重要的,尤其是在經常被呼叫的函式中。 一種有效的模式是,當您需要在函式中多次存取儲存變數時,將它們快取至記憶體中。
讓我們考慮以下範例: