Gas

氣體消耗:從儲存讀取還是從靜態讀取?

  • April 7, 2022

我只是想知道從儲存中讀取一個變數需要多少氣體,而不是提供一個靜態數字。

例如

uint256 public someNumber = 123;

function doSomething(...) ... {
.... someNumber * 5 ......
}

相對

function doSomething(...) ... {
.... 123 * 5 ......
}

差異有多大(我不知道/表示。它是微不足道的還是改變有影響力和代價高昂)?我想知道是否值得擁有一個可以稍後更改的動態變數,而不是一個靜態數字來優化氣體使用。

在版本 1 中,編譯器需要使用以下SLOAD指令從儲存中讀取:

PUSH32 storage_slot // 3 gas
SLOAD // 2K gas average (2100 with cold access / 1900 otherwise)

在版本 2 中,編譯器只會直接推送值:

PUSH32 123 // 3 gas

所以是的,差異很大,只有在必要時才使用儲存。

您可以使用以下程式碼輕鬆檢查它(我只使用彙編來最大限度地減少編譯器對 gas 成本計算的偏差,您可以完全可靠地完成它並獲得類似的東西):

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

contract TestGasCost {

   uint256 public someNumber = 123;

   function sload() public view returns (uint256 value, uint256 gasCost) {        
       assembly 
       {
           gasCost := gas()
           let _value := sload(someNumber.slot)
           gasCost := sub(gasCost, gas())

           value := _value
       }

       // Returns value: 123 , gasCost: 2110
   }

   function push() public view returns (uint256 value, uint256 gasCost) { 
       assembly 
       {
           gasCost := gas()
           let _value := 123
           gasCost := sub(gasCost, gas())

           value := _value
       }

       // Returns value: 123, gasCost: 10

   }

}

再次看到 2100 gas 成本的差異,這與第一個版本中的冷儲存訪問成本一致SLOAD。Opcodes gas 價格可能會發生變化,因此不要總是完全依賴這些值,但可以肯定地說,儲存總是比堆棧貴幾個數量級。

引用自:https://ethereum.stackexchange.com/questions/125504