ethereum.forks.cancun.vm.gasethereum.forks.prague.vm.gas
Ethereum Virtual Machine (EVM) Gas.
.. contents:: Table of Contents :backlinks: none :local:
Introduction
EVM gas constants and calculators.
GAS_JUMPDEST¶
| 27 | GAS_JUMPDEST = Uint(1) |
|---|
GAS_BASE¶
| 28 | GAS_BASE = Uint(2) |
|---|
GAS_VERY_LOW¶
| 29 | GAS_VERY_LOW = Uint(3) |
|---|
GAS_STORAGE_SET¶
| 30 | GAS_STORAGE_SET = Uint(20000) |
|---|
GAS_STORAGE_UPDATE¶
| 31 | GAS_STORAGE_UPDATE = Uint(5000) |
|---|
REFUND_STORAGE_CLEAR¶
| 32 | REFUND_STORAGE_CLEAR = 4800 |
|---|
GAS_LOW¶
| 33 | GAS_LOW = Uint(5) |
|---|
GAS_MID¶
| 34 | GAS_MID = Uint(8) |
|---|
GAS_HIGH¶
| 35 | GAS_HIGH = Uint(10) |
|---|
GAS_EXPONENTIATION¶
| 36 | GAS_EXPONENTIATION = Uint(10) |
|---|
GAS_EXPONENTIATION_PER_BYTE¶
| 37 | GAS_EXPONENTIATION_PER_BYTE = Uint(50) |
|---|
GAS_MEMORY¶
| 38 | GAS_MEMORY = Uint(3) |
|---|
GAS_KECCAK256¶
| 39 | GAS_KECCAK256 = Uint(30) |
|---|
GAS_KECCAK256_PER_WORD¶
| 40 | GAS_KECCAK256_PER_WORD = Uint(6) |
|---|
GAS_COPY¶
| 41 | GAS_COPY = Uint(3) |
|---|
GAS_BLOCK_HASH¶
| 42 | GAS_BLOCK_HASH = Uint(20) |
|---|
GAS_LOG¶
| 43 | GAS_LOG = Uint(375) |
|---|
GAS_LOG_DATA_PER_BYTE¶
| 44 | GAS_LOG_DATA_PER_BYTE = Uint(8) |
|---|
GAS_LOG_TOPIC¶
| 45 | GAS_LOG_TOPIC = Uint(375) |
|---|
GAS_CREATE¶
| 46 | GAS_CREATE = Uint(32000) |
|---|
GAS_CODE_DEPOSIT_PER_BYTE¶
| 47 | GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) |
|---|
GAS_ZERO¶
| 48 | GAS_ZERO = Uint(0) |
|---|
GAS_NEW_ACCOUNT¶
| 49 | GAS_NEW_ACCOUNT = Uint(25000) |
|---|
GAS_CALL_VALUE¶
| 50 | GAS_CALL_VALUE = Uint(9000) |
|---|
GAS_CALL_STIPEND¶
| 51 | GAS_CALL_STIPEND = Uint(2300) |
|---|
GAS_SELF_DESTRUCT¶
| 52 | GAS_SELF_DESTRUCT = Uint(5000) |
|---|
GAS_SELF_DESTRUCT_NEW_ACCOUNT¶
| 53 | GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) |
|---|
GAS_ECRECOVER¶
| 54 | GAS_ECRECOVER = Uint(3000) |
|---|
GAS_SHA256¶
| 55 | GAS_SHA256 = Uint(60) |
|---|
GAS_SHA256_WORD¶
| 56 | GAS_SHA256_WORD = Uint(12) |
|---|
GAS_RIPEMD160¶
| 57 | GAS_RIPEMD160 = Uint(600) |
|---|
GAS_RIPEMD160_WORD¶
| 58 | GAS_RIPEMD160_WORD = Uint(120) |
|---|
GAS_IDENTITY¶
| 59 | GAS_IDENTITY = Uint(15) |
|---|
GAS_IDENTITY_WORD¶
| 60 | GAS_IDENTITY_WORD = Uint(3) |
|---|
GAS_RETURN_DATA_COPY¶
| 61 | GAS_RETURN_DATA_COPY = Uint(3) |
|---|
GAS_FAST_STEP¶
| 62 | GAS_FAST_STEP = Uint(5) |
|---|
GAS_BLAKE2_PER_ROUND¶
| 63 | GAS_BLAKE2_PER_ROUND = Uint(1) |
|---|
GAS_COLD_SLOAD¶
| 64 | GAS_COLD_SLOAD = Uint(2100) |
|---|
GAS_COLD_ACCOUNT_ACCESS¶
| 65 | GAS_COLD_ACCOUNT_ACCESS = Uint(2600) |
|---|
GAS_WARM_ACCESS¶
| 66 | GAS_WARM_ACCESS = Uint(100) |
|---|
GAS_CODE_INIT_PER_WORD¶
| 67 | GAS_CODE_INIT_PER_WORD = Uint(2) |
|---|
GAS_BLOBHASH_OPCODE¶
| 68 | GAS_BLOBHASH_OPCODE = Uint(3) |
|---|
GAS_POINT_EVALUATION¶
| 69 | GAS_POINT_EVALUATION = Uint(50000) |
|---|
GAS_PER_BLOB¶
| 71 | GAS_PER_BLOB = U64(2**17) |
|---|
BLOB_TARGET_GAS_PER_BLOCK¶
| 72 | BLOB_TARGET_GAS_PER_BLOCK = U64(393216) |
|---|---|
| 72 | BLOB_TARGET_GAS_PER_BLOCK = U64(786432) |
BLOB_MIN_GASPRICE¶
| 73 | BLOB_MIN_GASPRICE = Uint(1) |
|---|
BLOB_BASE_FEE_UPDATE_FRACTION¶
| 74 | BLOB_BASE_FEE_UPDATE_FRACTION = Uint(3338477) |
|---|---|
| 74 | BLOB_BASE_FEE_UPDATE_FRACTION = Uint(5007716) |
GAS_BLS_G1_ADD¶
| 76 | GAS_BLS_G1_ADD = Uint(375) |
|---|
GAS_BLS_G1_MUL¶
| 77 | GAS_BLS_G1_MUL = Uint(12000) |
|---|
GAS_BLS_G1_MAP¶
| 78 | GAS_BLS_G1_MAP = Uint(5500) |
|---|
GAS_BLS_G2_ADD¶
| 79 | GAS_BLS_G2_ADD = Uint(600) |
|---|
GAS_BLS_G2_MUL¶
| 80 | GAS_BLS_G2_MUL = Uint(22500) |
|---|
GAS_BLS_G2_MAP¶
| 81 | GAS_BLS_G2_MAP = Uint(23800) |
|---|
ExtendMemory ¶
Define the parameters for memory extension in opcodes.
cost: ethereum.base_types.Uint
The gas required to perform the extension
expand_by: ethereum.base_types.Uint
The size by which the memory will be extended
| 84 | @dataclass |
|---|
class ExtendMemory:
cost¶
| 95 | cost: Uint |
|---|
expand_by¶
| 96 | expand_by: Uint |
|---|
MessageCallGas ¶
Define the gas cost and gas given to the sub-call for executing the call opcodes.
cost: ethereum.base_types.Uint
The gas required to execute the call opcode, excludes
memory expansion costs.
sub_call: ethereum.base_types.Uint
The portion of gas available to sub-calls that is refundable
if not consumed.
| 99 | @dataclass |
|---|
class MessageCallGas:
cost¶
| 113 | cost: Uint |
|---|
sub_call¶
| 114 | sub_call: Uint |
|---|
charge_gas ¶
Subtracts amount from evm.gas_left.
Parameters
evm : The current EVM. amount : The amount of gas the current operation requires.
def charge_gas(evm: Evm, amount: Uint) -> None:
| 118 | """ |
|---|---|
| 119 | Subtracts `amount` from `evm.gas_left`. |
| 120 | |
| 121 | Parameters |
| 122 | ---------- |
| 123 | evm : |
| 124 | The current EVM. |
| 125 | amount : |
| 126 | The amount of gas the current operation requires. |
| 127 | |
| 128 | """ |
| 129 | evm_trace(evm, GasAndRefund(int(amount))) |
| 130 | |
| 131 | if evm.gas_left < amount: |
| 132 | raise OutOfGasError |
| 133 | else: |
| 134 | evm.gas_left -= amount |
calculate_memory_gas_cost ¶
Calculates the gas cost for allocating memory to the smallest multiple of 32 bytes, such that the allocated size is at least as big as the given size.
Parameters
size_in_bytes : The size of the data in bytes.
Returns
total_gas_cost : ethereum.base_types.Uint
The gas cost for storing data in memory.
def calculate_memory_gas_cost(size_in_bytes: Uint) -> Uint:
| 138 | """ |
|---|---|
| 139 | Calculates the gas cost for allocating memory |
| 140 | to the smallest multiple of 32 bytes, |
| 141 | such that the allocated size is at least as big as the given size. |
| 142 | |
| 143 | Parameters |
| 144 | ---------- |
| 145 | size_in_bytes : |
| 146 | The size of the data in bytes. |
| 147 | |
| 148 | Returns |
| 149 | ------- |
| 150 | total_gas_cost : `ethereum.base_types.Uint` |
| 151 | The gas cost for storing data in memory. |
| 152 | |
| 153 | """ |
| 154 | size_in_words = ceil32(size_in_bytes) // Uint(32) |
| 155 | linear_cost = size_in_words * GAS_MEMORY |
| 156 | quadratic_cost = size_in_words ** Uint(2) // Uint(512) |
| 157 | total_gas_cost = linear_cost + quadratic_cost |
| 158 | try: |
| 159 | return total_gas_cost |
| 160 | except ValueError as e: |
| 161 | raise OutOfGasError from e |
calculate_gas_extend_memory ¶
Calculates the gas amount to extend memory.
Parameters
memory : Memory contents of the EVM. extensions: List of extensions to be made to the memory. Consists of a tuple of start position and size.
Returns
extend_memory: ExtendMemory
def calculate_gas_extend_memory(memory: bytearray, extensions: List[Tuple[U256, U256]]) -> ExtendMemory:
| 167 | """ |
|---|---|
| 168 | Calculates the gas amount to extend memory. |
| 169 | |
| 170 | Parameters |
| 171 | ---------- |
| 172 | memory : |
| 173 | Memory contents of the EVM. |
| 174 | extensions: |
| 175 | List of extensions to be made to the memory. |
| 176 | Consists of a tuple of start position and size. |
| 177 | |
| 178 | Returns |
| 179 | ------- |
| 180 | extend_memory: `ExtendMemory` |
| 181 | |
| 182 | """ |
| 183 | size_to_extend = Uint(0) |
| 184 | to_be_paid = Uint(0) |
| 185 | current_size = Uint(len(memory)) |
| 186 | for start_position, size in extensions: |
| 187 | if size == 0: |
| 188 | continue |
| 189 | before_size = ceil32(current_size) |
| 190 | after_size = ceil32(Uint(start_position) + Uint(size)) |
| 191 | if after_size <= before_size: |
| 192 | continue |
| 193 | |
| 194 | size_to_extend += after_size - before_size |
| 195 | already_paid = calculate_memory_gas_cost(before_size) |
| 196 | total_cost = calculate_memory_gas_cost(after_size) |
| 197 | to_be_paid += total_cost - already_paid |
| 198 | |
| 199 | current_size = after_size |
| 200 | |
| 201 | return ExtendMemory(to_be_paid, size_to_extend) |
calculate_message_call_gas ¶
Calculates the MessageCallGas (cost and gas made available to the sub-call) for executing call Opcodes.
Parameters
value:
The amount of ETH that needs to be transferred.
gas :
The amount of gas provided to the message-call.
gas_left :
The amount of gas left in the current frame.
memory_cost :
The amount needed to extend the memory in the current frame.
extra_gas :
The amount of gas needed for transferring value + creating a new
account inside a message call.
call_stipend :
The amount of stipend provided to a message call to execute code while
transferring value (ETH).
Returns
message_call_gas: MessageCallGas
def calculate_message_call_gas(value: U256, gas: Uint, gas_left: Uint, memory_cost: Uint, extra_gas: Uint, call_stipend: Uint) -> MessageCallGas:
| 212 | """ |
|---|---|
| 213 | Calculates the MessageCallGas (cost and gas made available to the sub-call) |
| 214 | for executing call Opcodes. |
| 215 | |
| 216 | Parameters |
| 217 | ---------- |
| 218 | value: |
| 219 | The amount of `ETH` that needs to be transferred. |
| 220 | gas : |
| 221 | The amount of gas provided to the message-call. |
| 222 | gas_left : |
| 223 | The amount of gas left in the current frame. |
| 224 | memory_cost : |
| 225 | The amount needed to extend the memory in the current frame. |
| 226 | extra_gas : |
| 227 | The amount of gas needed for transferring value + creating a new |
| 228 | account inside a message call. |
| 229 | call_stipend : |
| 230 | The amount of stipend provided to a message call to execute code while |
| 231 | transferring value (ETH). |
| 232 | |
| 233 | Returns |
| 234 | ------- |
| 235 | message_call_gas: `MessageCallGas` |
| 236 | |
| 237 | """ |
| 238 | call_stipend = Uint(0) if value == 0 else call_stipend |
| 239 | if gas_left < extra_gas + memory_cost: |
| 240 | return MessageCallGas(gas + extra_gas, gas + call_stipend) |
| 241 | |
| 242 | gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) |
| 243 | |
| 244 | return MessageCallGas(gas + extra_gas, gas + call_stipend) |
max_message_call_gas ¶
Calculates the maximum gas that is allowed for making a message call.
Parameters
gas : The amount of gas provided to the message-call.
Returns
max_allowed_message_call_gas: ethereum.base_types.Uint
The maximum gas allowed for making the message-call.
def max_message_call_gas(gas: Uint) -> Uint:
| 248 | """ |
|---|---|
| 249 | Calculates the maximum gas that is allowed for making a message call. |
| 250 | |
| 251 | Parameters |
| 252 | ---------- |
| 253 | gas : |
| 254 | The amount of gas provided to the message-call. |
| 255 | |
| 256 | Returns |
| 257 | ------- |
| 258 | max_allowed_message_call_gas: `ethereum.base_types.Uint` |
| 259 | The maximum gas allowed for making the message-call. |
| 260 | |
| 261 | """ |
| 262 | return gas - (gas // Uint(64)) |
init_code_cost ¶
Calculates the gas to be charged for the init code in CREATE* opcodes as well as create transactions.
Parameters
init_code_length : The length of the init code provided to the opcode or a create transaction
Returns
init_code_gas: ethereum.base_types.Uint
The gas to be charged for the init code.
def init_code_cost(init_code_length: Uint) -> Uint:
| 266 | """ |
|---|---|
| 267 | Calculates the gas to be charged for the init code in CREATE* |
| 268 | opcodes as well as create transactions. |
| 269 | |
| 270 | Parameters |
| 271 | ---------- |
| 272 | init_code_length : |
| 273 | The length of the init code provided to the opcode |
| 274 | or a create transaction |
| 275 | |
| 276 | Returns |
| 277 | ------- |
| 278 | init_code_gas: `ethereum.base_types.Uint` |
| 279 | The gas to be charged for the init code. |
| 280 | |
| 281 | """ |
| 282 | return GAS_CODE_INIT_PER_WORD * ceil32(init_code_length) // Uint(32) |
calculate_excess_blob_gas ¶
Calculates the excess blob gas for the current block based on the gas used in the parent block.
Parameters
parent_header : The parent block of the current block.
Returns
excess_blob_gas: ethereum.base_types.U64
The excess blob gas for the current block.
def calculate_excess_blob_gas(parent_header: Header) -> U64:
| 286 | """ |
|---|---|
| 287 | Calculates the excess blob gas for the current block based |
| 288 | on the gas used in the parent block. |
| 289 | |
| 290 | Parameters |
| 291 | ---------- |
| 292 | parent_header : |
| 293 | The parent block of the current block. |
| 294 | |
| 295 | Returns |
| 296 | ------- |
| 297 | excess_blob_gas: `ethereum.base_types.U64` |
| 298 | The excess blob gas for the current block. |
| 299 | |
| 300 | """ |
| 301 | # At the fork block, these are defined as zero. |
| 302 | excess_blob_gas = U64(0) |
| 303 | blob_gas_used = U64(0) |
| 304 | |
| 305 | if isinstance(parent_header, Header): |
| 306 | # After the fork block, read them from the parent header. |
| 307 | excess_blob_gas = parent_header.excess_blob_gas |
| 308 | blob_gas_used = parent_header.blob_gas_used |
| 309 | |
| 310 | parent_blob_gas = excess_blob_gas + blob_gas_used |
| 311 | if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: |
| 312 | return U64(0) |
| 313 | |
| 314 | return parent_blob_gas - BLOB_TARGET_GAS_PER_BLOCK |
calculate_total_blob_gas ¶
Calculate the total blob gas for a transaction.
Parameters
tx : The transaction for which the blob gas is to be calculated.
Returns
total_blob_gas: ethereum.base_types.Uint
The total blob gas for the transaction.
def calculate_total_blob_gas(tx: Transaction) -> U64:
| 318 | """ |
|---|---|
| 319 | Calculate the total blob gas for a transaction. |
| 320 | |
| 321 | Parameters |
| 322 | ---------- |
| 323 | tx : |
| 324 | The transaction for which the blob gas is to be calculated. |
| 325 | |
| 326 | Returns |
| 327 | ------- |
| 328 | total_blob_gas: `ethereum.base_types.Uint` |
| 329 | The total blob gas for the transaction. |
| 330 | |
| 331 | """ |
| 332 | if isinstance(tx, BlobTransaction): |
| 333 | return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) |
| 334 | else: |
| 335 | return U64(0) |
calculate_blob_gas_price ¶
Calculate the blob gasprice for a block.
Parameters
excess_blob_gas : The excess blob gas for the block.
Returns
blob_gasprice: Uint
The blob gasprice.
def calculate_blob_gas_price(excess_blob_gas: U64) -> Uint:
| 339 | """ |
|---|---|
| 340 | Calculate the blob gasprice for a block. |
| 341 | |
| 342 | Parameters |
| 343 | ---------- |
| 344 | excess_blob_gas : |
| 345 | The excess blob gas for the block. |
| 346 | |
| 347 | Returns |
| 348 | ------- |
| 349 | blob_gasprice: `Uint` |
| 350 | The blob gasprice. |
| 351 | |
| 352 | """ |
| 353 | return taylor_exponential( |
| 354 | BLOB_MIN_GASPRICE, |
| 355 | Uint(excess_blob_gas), |
| 356 | BLOB_BASE_FEE_UPDATE_FRACTION, |
| 357 | ) |
calculate_data_fee ¶
Calculate the blob data fee for a transaction.
Parameters
excess_blob_gas : The excess_blob_gas for the execution. tx : The transaction for which the blob data fee is to be calculated.
Returns
data_fee: Uint
The blob data fee.
def calculate_data_fee(excess_blob_gas: U64, tx: Transaction) -> Uint:
| 361 | """ |
|---|---|
| 362 | Calculate the blob data fee for a transaction. |
| 363 | |
| 364 | Parameters |
| 365 | ---------- |
| 366 | excess_blob_gas : |
| 367 | The excess_blob_gas for the execution. |
| 368 | tx : |
| 369 | The transaction for which the blob data fee is to be calculated. |
| 370 | |
| 371 | Returns |
| 372 | ------- |
| 373 | data_fee: `Uint` |
| 374 | The blob data fee. |
| 375 | |
| 376 | """ |
| 377 | return Uint(calculate_total_blob_gas(tx)) * calculate_blob_gas_price( |
| 378 | excess_blob_gas |
| 379 | ) |