跳至主要內容
本頁面使用機器翻譯自英語,可能包含錯誤或不清楚的語言。如需最準確的信息,請參閱英文原文。由於更新頻繁,部分內容可能與英文原文有出入。請加入我們在 Crowdin 上的努力,幫助我們改進本頁面的翻譯。 (Crowdin translation page, Contributing guide)

執行氣體

氣體是 "內在氣體 "和 "執行氣體 "的總和。 在這裡,我們將重點討論如何計算 "執行氣體"。

備註

執行氣體相關硬分叉更改可在本頁底部找到。 轉到 Hardfork Changes

概述

在三種不同的情況下,執行合同時會收取執行費。 有時,某些政策可能會被省略。

  • 第一種也是最常見的一種是 "constantGas"。 這是計算操作的固有費用。
  • 其次,氣體可被扣除,以形成從屬報文調用或合同創建的付款;這構成 "CREATE"、"CALL "和 "CALLCODE "付款的一部分。
  • 最後,由於內存使用量增加,可能會收取氣體費用。

在一個賬戶的執行過程中,應支付的內存使用費總額與 32 字節的最小倍數成正比,而 32 字節的最小倍數是包括所有內存索引(無論是讀取還是寫入)的範圍。 這筆費用是按時支付的;因此,如果引用的內存區域至少比先前索引的內存區域大 32 字節,就會產生額外的內存使用費。 由於這筆費用,地址超過 32 位界限的可能性很小。 儘管如此,實施方案必須能夠管理這種可能發生的情況。

存儲費的行為略有細微差別。 為了鼓勵最大限度地減少存儲空間的使用(這與所有節點上都有一個更大的狀態數據庫直接對應),從存儲空間中清除條目的操作的執行費用不僅可以免除,而且還可以獲得合格的退款;事實上,這種退款實際上是提前支付的,因為初始使用存儲位置的成本要比正常使用高得多。

操作碼氣體時間表

費用表 G 是由 37 個標量值組成的元組,這些標量值與交易可能產生的若干抽象操作的相對費用(以瓦斯為單位)相對應。 此外,還有氣體項目,用於計算由 CALL_* 操作碼調用的預編譯合約的氣體。

代表操作碼 "常數氣體 "的標量值

名稱價值代碼中的名稱操作碼
G_base2GasQuickStepADDRESS, ORIGIN, CALLER, CALLVALUE, CALLDATASIZE, CODESIZE, GASPRICE, COINBASE, TIMESTAMP, NUMBER, PREVRANDAO(originally it was DIFFICULTY), GASLIMIT, RETURNDATASIZE, POP, PC, MSIZE, GAS, CHAINID, BASEFEE, PUSH0, BLOBBASEFEE
G_verylow3GasFastestStepADD, SUB, LT, GT, SLT, SGT, EQ, ISZERO, AND, OR, XOR, NOT, BYTE, CALLDATALOAD, MLOAD, MSTORE, MSTORE8, PUSH, DUP, SWAP, BLOBHASH, MCOPY
G_low5GasFastStepMUL, DIV, SDIV, MOD, SMOD, SIGNEXTEND, SELFBALANCE
G_mid8GasMidStepADDMOD, MULMOD, JUMP
G_high10GasSlowStepJUMPI
G_selfdestruct5000SelfdestructGasSELFDESTRUCT
G_warmStorageReadCost100WarmStorageReadCostEIP2929EXTCODECOPY, EXTCODESIZE, EXTCODEHASH, BALANCE, CALL, CALLCODE, STATICCALL, DELEGATECALL, TSTORE, TLOAD
G_blockhash20GasExtStepBLOCKHASH
G_jumpdest1JumpdestGasJUMPDEST
G_sha330Sha3GasSHA3
G_create32000CreateGasCREATE, CREATE2

用於根據內存和日誌使用量計算氣體的標量值

NameValueName in CodeDescription
G_memory3MemoryGas擴展存儲器時,每增加一個字所需支付的氣體量
G_copy3CopyGas複製 "操作的部分付款,乘以複製字數,四捨五入
G_log375LogGas為 "LOG "操作支付部分費用
G_logdata8LogDataGas為 "LOG "操作數據中的每個字節支付的氣體量
G_logtopic375LogTopicGas為 "LOG "操作的每個主題支付的氣體量

用於計算特定操作碼氣體的標量值

NameValueName in CodeDescription
G_sset20000SstoreSetGas設定存儲值時支付的氣量
G_sreset5000SstoreResetGas存儲值保持不變為零或設置為零時支付的氣量
G_coldSloadCost2100ColdSloadCostEIP2929存儲值不在訪問列表中時支付的氣量
R_sclear15000SstoreClearsScheduleRefundEIP3529G_sreset - G_coldSloadCost + TxAccessListStorageKeyGas (1900)
G_exp10ExpGasPartial payment
G_expbyte50ExpByte乘以 "ceil(log_256(指數)) "時的部分付款
G_selfdestruct5000SelfdestructGas為 "SELFDESTRUCT "操作支付的氣體量
G_callvalue9000CallValueTransferGas為非零價值轉移支付的氣量
G_callstipend2300CallStipend呼叫開始時為非零值轉移提供的免費氣體
G_newaccount25000CallNewAccountGas創建賬戶時已支付的汽油金額。 它也可以定義為帶有 "SELFDESTRUCT "操作的 "CreateBySelfdestructGas"。
G_codedeposit200CreateDataGas為創建成功將代碼置入狀態的合同而按字節支付的氣體量
G_sha3word6Sha3WordGas輸入數據 "SHA3 "時,每個字所支付的氣體量(四捨五入)。
G_InitCodeWord2InitCodeWordGas為 "CREATE"、"CREATE2 "的每個初始代碼單詞支付的氣體量

預編合同天然氣成本表

預編譯合約是一種特殊的合約,通常執行復雜的加密計算,並由其他合約啟動。

以下是卡亞預編譯合同的天然氣成本表。 輸入 "是預編譯合同的字節數組輸入。

AddressPrecompiled contractsGas Cost
0x01ecrecover3,000
0x02sha256hash字數(輸入)* 12 + 60
0x03ripemd160hash字數(輸入)* 120 + 600
0x04dataCopy字數(輸入)* 3 + 15
0x05bigModExp查看代碼 此處
0x06bn256Add150
0x07bn256ScalarMul6,000
0x08bn256Pairing配對數(輸入)* 34,000 + 45,000
0x09blake2fbigEndian(getRounds(input[0:4]))
0x0Akzg50,000
0x3FDvmLoglen(input) * 20 + 100
0x3FEfeePayer300
0x3FFvalidateSender數組(輸入)* 5,000

執行合同的氣體計算邏輯

一次交易的天然氣成本通過下述方法計算。 首先,根據交易類型和輸入添加氣體。 然後,如果合約被執行,操作碼將被逐個執行,直到執行結束或出現 "STOP "操作。 在此過程中,將根據為每個操作碼定義的 "constantGas "和額外定義的氣體計算方法收取費用。

在此,我將簡要說明合同執行過程中使用上述費用表變量的天然氣計算邏輯。 由於本解釋假設的是一般情況,因此沒有考慮回退等異常情況。

  • 將每個操作碼中定義的 "constantGas "添加到 gas 中
    • 例如,如果操作碼為 MUL,則在 gas 中添加 `G_low
    • 例如,如果操作碼是 CREATE2,則在 gas 中添加 `G_create
  • 添加通過額外定義的氣體計算方法計算出的氣體
    • 對於 LOG'N',其中 N 為 [0,1,2,3,4],將 G_log + memoryGasCost * g_logdata + N x G_logtopic 添加到氣體中
    • 對於 EXP,將 G_exp + byteSize(stack.back(1)) x G_expbyte 加入氣體中
    • 對於CALLDATACOPYCODECOPYRETURNDATACOPY,在氣體中添加wordSize(stack.back(2)) x G_copy
    • 用於 EXTCODECOPY
      • wordSize(stack.back(3)) x G_copy 添加到氣體中
      • [eip2929] 如果地址不在 AccessList 中,則將其添加到 AccessList 中,並將G_coldSloadCost - G_warmStorageReadCost 添加到氣體中。
    • 用於 EXTCODESIZEEXTCODEHASHBALANCE
      • [eip2929] 如果地址不在 AccessList 中,則將其添加到 AccessList 中,並將G_coldSloadCost - G_warmStorageReadCost 添加到氣體中。
    • 對於 SHA3,將 G_sha3 + wordSize(stack.back(1)) x G_sha3word 添加到氣體中。
    • 對於 RETURNREVERTMLoadMStore8MStore,將 memoryGasCost 添加到氣體中
    • 對於 "CREATE",在氣體中添加 "memoryGasCost + size(contract.code) x G_codedeposit + wordsize(initcode) x G_InitCodeWord
    • 對於 CREATE2,將 memoryGasCost + size(data) x G_sha3word + size(contract.code) x G_codedeposit + wordsize(initcode) x G_InitCodeWord 添加到氣體中
    • 對於 "SSTORE"、
      • [eip2929] 如果槽(contractAddr, 槽)不在 AccessList 中,則將其添加到 AccessList 中,並將 G_coldSloadCost 添加到氣體中。
      • 如果只是讀取插槽(無操作),則將 G_warmStorageReadCost 添加到 gas
      • 如果創建了一個新槽,則將 G_sset 添加到 gas
      • 如果它刪除了插槽,則在 gas 中添加 G_sreset-G_coldSloadCost 並在 refund 中添加 R_sclear
      • 如果重新創建過一次插槽,則在氣體中加入 G_warmStorageReadCost 並從退款中減去 R_sclear
      • 如果它刪除了之前存在過的插槽,則在退款時添加 R_sclear
      • 如果重置為原來不存在的插槽,則在 gas 中添加 G_warmStorageReadCost 並在退款中添加 G_sset - G_warmStorageReadCost
      • 如果重置為原來的現有插槽,則在 gas 中添加 G_warmStorageReadCost 並在 refund 中添加 `G_sreset - G_coldSloadCost - G_warmStorageReadCost
    • 用於 SLOAD
      • [eip2929] 如果槽(contractAddr, 槽)不在 AccessList 中,則將其添加到 AccessList 中,並將 G_coldSloadCost 添加到氣體中。
      • [eip2929] 如果槽(contractAddr, 槽)位於 AccessList 中,則將 G_warmStorageReadCost 添加到氣體中。
    • 用於 CALLCALLCODEDELEGATECALLSTATICCALL
      • [eip2929] 如果地址不在 AccessList 中,則將其添加到 AccessList 中,並將 G_coldSloadCost 添加到氣體中
      • 如果它是 CALLCALLCODE,如果它傳輸值,則在 gas 中添加 `G_callvalue
      • 如果是 CALL',如果是轉賬,如果是新賬戶,則在 gas 中添加 G_newaccount
      • 如果受話人合同是預編譯合同,則計算預編譯合同天然氣成本,並將其添加到天然氣成本中。
      • 將 "內存燃氣成本 + 可用燃氣 - 可用燃氣/64,其中可用燃氣 = 合同.燃氣 - 燃氣 "添加到燃氣中
    • 用於 SELFDESTRUCT
      • [eip2929] 如果地址不在 AccessList 中,則將其添加到 AccessList 中,並將 G_coldSloadCost 添加到氣體中
      • 如果是轉移值,如果是新賬戶,則將 G_newaccount 加入 gas

Hardfork changes

HardforkNew ItemsChange
Cancun EVMBLOBBASEFEE (0x49) opcode
BLOBHASH (0x50) opcode
TSTORE (0x5C) opcode
TLOAD (0x5D) opcode
MCOPY(0x5E) opcode
kzg (0x0A) precompiled contract
完全支持 accessList,通過 tx args 添加到 accessList
的存儲
access 變得溫暖了。
Shanghai EVMPUSH0 (0x5F) opcode溫暖的硬幣基地,因此訪問
coinbase 的氣體成本始終是溫暖的

開始在 Create, Create2 操作碼
中為每個字的 initcode 添加 2 個氣體
Korereduction in refunds
- removes refund for SELFDESTRUCT (0xFF), SSTORE (0x55)
- capped the refund to gasUsed/5 (it was gasUsed/2)

increase gas cost for state access opcodes
- accessList is introduced here but it's not yet supported.
London EVMBASEFEE (0x48) opcodemodExp (0x05) precompiled contract
use new gas calculation logic.
Become more accurate.
Istanbul EVMCHAINID (0x46) 操作碼
SELFBALANCE (0x47) 操作碼
blake2f (0x09) 預編譯合同
降低 BN256 預編譯合同的氣體成本
- Bn256Add (0x06):500->150
- Bn256ScalarMul (0x07):40,000->6,000
- BN256Pairing (0x08):
-- BaseGas:100,000->45,000
-- PerPointGas:80,000->34,000

SSTORE (0x55) 的新氣體計算邏輯。
- 引進冷藏庫。
- 首次接入的燃氣費用增加。

增加重存儲訪問的氣體成本
- SLOAD(0x54):200->800
- BALANCE(0x31):400->700
- EXTCODEHASH(0x3F):400->700
讓這個頁面變得更好