ethereum.forks.bpo5.vm.gasethereum.forks.amsterdam.vm.gas
Ethereum Virtual Machine (EVM) Gas.
.. contents:: Table of Contents :backlinks: none :local:
Introduction
EVM gas constants and calculators.
GAS_JUMPDEST¶
| 28 | GAS_JUMPDEST = Uint(1) |
|---|
GAS_BASE¶
| 29 | GAS_BASE = Uint(2) |
|---|
GAS_VERY_LOW¶
| 30 | GAS_VERY_LOW = Uint(3) |
|---|
GAS_STORAGE_SET¶
| 31 | GAS_STORAGE_SET = Uint(20000) |
|---|
GAS_STORAGE_UPDATE¶
| 32 | GAS_STORAGE_UPDATE = Uint(5000) |
|---|
REFUND_STORAGE_CLEAR¶
| 33 | REFUND_STORAGE_CLEAR = 4800 |
|---|
GAS_LOW¶
| 34 | GAS_LOW = Uint(5) |
|---|
GAS_MID¶
| 35 | GAS_MID = Uint(8) |
|---|
GAS_HIGH¶
| 36 | GAS_HIGH = Uint(10) |
|---|
GAS_EXPONENTIATION¶
| 37 | GAS_EXPONENTIATION = Uint(10) |
|---|
GAS_EXPONENTIATION_PER_BYTE¶
| 38 | GAS_EXPONENTIATION_PER_BYTE = Uint(50) |
|---|
GAS_MEMORY¶
| 39 | GAS_MEMORY = Uint(3) |
|---|
GAS_KECCAK256¶
| 40 | GAS_KECCAK256 = Uint(30) |
|---|
GAS_KECCAK256_PER_WORD¶
| 41 | GAS_KECCAK256_PER_WORD = Uint(6) |
|---|
GAS_COPY¶
| 42 | GAS_COPY = Uint(3) |
|---|
GAS_BLOCK_HASH¶
| 43 | GAS_BLOCK_HASH = Uint(20) |
|---|
GAS_LOG¶
| 44 | GAS_LOG = Uint(375) |
|---|
GAS_LOG_DATA_PER_BYTE¶
| 45 | GAS_LOG_DATA_PER_BYTE = Uint(8) |
|---|
GAS_LOG_TOPIC¶
| 46 | GAS_LOG_TOPIC = Uint(375) |
|---|
GAS_CREATE¶
| 47 | GAS_CREATE = Uint(32000) |
|---|
GAS_CODE_DEPOSIT_PER_BYTE¶
| 48 | GAS_CODE_DEPOSIT_PER_BYTE = Uint(200) |
|---|
GAS_ZERO¶
| 49 | GAS_ZERO = Uint(0) |
|---|
GAS_NEW_ACCOUNT¶
| 50 | GAS_NEW_ACCOUNT = Uint(25000) |
|---|
GAS_CALL_VALUE¶
| 51 | GAS_CALL_VALUE = Uint(9000) |
|---|
GAS_CALL_STIPEND¶
| 52 | GAS_CALL_STIPEND = Uint(2300) |
|---|
GAS_SELF_DESTRUCT¶
| 53 | GAS_SELF_DESTRUCT = Uint(5000) |
|---|
GAS_SELF_DESTRUCT_NEW_ACCOUNT¶
| 54 | GAS_SELF_DESTRUCT_NEW_ACCOUNT = Uint(25000) |
|---|
GAS_ECRECOVER¶
| 55 | GAS_ECRECOVER = Uint(3000) |
|---|
GAS_P256VERIFY¶
| 56 | GAS_P256VERIFY = Uint(6900) |
|---|
GAS_SHA256¶
| 57 | GAS_SHA256 = Uint(60) |
|---|
GAS_SHA256_WORD¶
| 58 | GAS_SHA256_WORD = Uint(12) |
|---|
GAS_RIPEMD160¶
| 59 | GAS_RIPEMD160 = Uint(600) |
|---|
GAS_RIPEMD160_WORD¶
| 60 | GAS_RIPEMD160_WORD = Uint(120) |
|---|
GAS_IDENTITY¶
| 61 | GAS_IDENTITY = Uint(15) |
|---|
GAS_IDENTITY_WORD¶
| 62 | GAS_IDENTITY_WORD = Uint(3) |
|---|
GAS_RETURN_DATA_COPY¶
| 63 | GAS_RETURN_DATA_COPY = Uint(3) |
|---|
GAS_FAST_STEP¶
| 64 | GAS_FAST_STEP = Uint(5) |
|---|
GAS_BLAKE2_PER_ROUND¶
| 65 | GAS_BLAKE2_PER_ROUND = Uint(1) |
|---|
GAS_COLD_SLOAD¶
| 66 | GAS_COLD_SLOAD = Uint(2100) |
|---|
GAS_COLD_ACCOUNT_ACCESS¶
| 67 | GAS_COLD_ACCOUNT_ACCESS = Uint(2600) |
|---|
GAS_WARM_ACCESS¶
| 68 | GAS_WARM_ACCESS = Uint(100) |
|---|
GAS_CODE_INIT_PER_WORD¶
| 69 | GAS_CODE_INIT_PER_WORD = Uint(2) |
|---|
GAS_BLOBHASH_OPCODE¶
| 70 | GAS_BLOBHASH_OPCODE = Uint(3) |
|---|
GAS_POINT_EVALUATION¶
| 71 | GAS_POINT_EVALUATION = Uint(50000) |
|---|
GAS_PER_BLOB¶
| 73 | GAS_PER_BLOB = U64(2**17) |
|---|
BLOB_SCHEDULE_TARGET¶
| 74 | BLOB_SCHEDULE_TARGET = U64(14) |
|---|
BLOB_TARGET_GAS_PER_BLOCK¶
| 75 | BLOB_TARGET_GAS_PER_BLOCK = GAS_PER_BLOB * BLOB_SCHEDULE_TARGET |
|---|
BLOB_BASE_COST¶
| 76 | BLOB_BASE_COST = Uint(2**13) |
|---|
BLOB_SCHEDULE_MAX¶
| 77 | BLOB_SCHEDULE_MAX = U64(21) |
|---|
BLOB_MIN_GASPRICE¶
| 78 | BLOB_MIN_GASPRICE = Uint(1) |
|---|
BLOB_BASE_FEE_UPDATE_FRACTION¶
| 79 | BLOB_BASE_FEE_UPDATE_FRACTION = Uint(11684671) |
|---|
GAS_BLS_G1_ADD¶
| 81 | GAS_BLS_G1_ADD = Uint(375) |
|---|
GAS_BLS_G1_MUL¶
| 82 | GAS_BLS_G1_MUL = Uint(12000) |
|---|
GAS_BLS_G1_MAP¶
| 83 | GAS_BLS_G1_MAP = Uint(5500) |
|---|
GAS_BLS_G2_ADD¶
| 84 | GAS_BLS_G2_ADD = Uint(600) |
|---|
GAS_BLS_G2_MUL¶
| 85 | GAS_BLS_G2_MUL = Uint(22500) |
|---|
GAS_BLS_G2_MAP¶
| 86 | GAS_BLS_G2_MAP = Uint(23800) |
|---|
GAS_BLOCK_ACCESS_LIST_ITEM¶
| 88 | GAS_BLOCK_ACCESS_LIST_ITEM = Uint(2000) |
|---|
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
| 91 | @dataclass |
|---|
class ExtendMemory:
cost¶
| 102 | cost: Uint |
|---|
expand_by¶
| 103 | 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.
| 106 | @dataclass |
|---|
class MessageCallGas:
cost¶
| 120 | cost: Uint |
|---|
sub_call¶
| 121 | sub_call: Uint |
|---|
check_gas ¶
Checks if amount gas is available without charging it.
Raises OutOfGasError if insufficient gas.
Parameters
evm : The current EVM. amount : The amount of gas to check.
def check_gas(evm: Evm, amount: Uint) -> None:
| 125 | """ |
|---|---|
| 126 | Checks if `amount` gas is available without charging it. |
| 127 | Raises OutOfGasError if insufficient gas. |
| 128 | |
| 129 | Parameters |
| 130 | ---------- |
| 131 | evm : |
| 132 | The current EVM. |
| 133 | amount : |
| 134 | The amount of gas to check. |
| 135 | |
| 136 | """ |
| 137 | if evm.gas_left < amount: |
| 138 | raise OutOfGasError |
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:
| 142 | """ |
|---|---|
| 143 | Subtracts `amount` from `evm.gas_left`. |
| 144 | |
| 145 | Parameters |
| 146 | ---------- |
| 147 | evm : |
| 148 | The current EVM. |
| 149 | amount : |
| 150 | The amount of gas the current operation requires. |
| 151 | |
| 152 | """ |
| 153 | evm_trace(evm, GasAndRefund(int(amount))) |
| 154 | |
| 155 | if evm.gas_left < amount: |
| 156 | raise OutOfGasError |
| 157 | else: |
| 158 | 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:
| 162 | """ |
|---|---|
| 163 | Calculates the gas cost for allocating memory |
| 164 | to the smallest multiple of 32 bytes, |
| 165 | such that the allocated size is at least as big as the given size. |
| 166 | |
| 167 | Parameters |
| 168 | ---------- |
| 169 | size_in_bytes : |
| 170 | The size of the data in bytes. |
| 171 | |
| 172 | Returns |
| 173 | ------- |
| 174 | total_gas_cost : `ethereum.base_types.Uint` |
| 175 | The gas cost for storing data in memory. |
| 176 | |
| 177 | """ |
| 178 | size_in_words = ceil32(size_in_bytes) // Uint(32) |
| 179 | linear_cost = size_in_words * GAS_MEMORY |
| 180 | quadratic_cost = size_in_words ** Uint(2) // Uint(512) |
| 181 | total_gas_cost = linear_cost + quadratic_cost |
| 182 | try: |
| 183 | return total_gas_cost |
| 184 | except ValueError as e: |
| 185 | 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:
| 191 | """ |
|---|---|
| 192 | Calculates the gas amount to extend memory. |
| 193 | |
| 194 | Parameters |
| 195 | ---------- |
| 196 | memory : |
| 197 | Memory contents of the EVM. |
| 198 | extensions: |
| 199 | List of extensions to be made to the memory. |
| 200 | Consists of a tuple of start position and size. |
| 201 | |
| 202 | Returns |
| 203 | ------- |
| 204 | extend_memory: `ExtendMemory` |
| 205 | |
| 206 | """ |
| 207 | size_to_extend = Uint(0) |
| 208 | to_be_paid = Uint(0) |
| 209 | current_size = Uint(len(memory)) |
| 210 | for start_position, size in extensions: |
| 211 | if size == 0: |
| 212 | continue |
| 213 | before_size = ceil32(current_size) |
| 214 | after_size = ceil32(Uint(start_position) + Uint(size)) |
| 215 | if after_size <= before_size: |
| 216 | continue |
| 217 | |
| 218 | size_to_extend += after_size - before_size |
| 219 | already_paid = calculate_memory_gas_cost(before_size) |
| 220 | total_cost = calculate_memory_gas_cost(after_size) |
| 221 | to_be_paid += total_cost - already_paid |
| 222 | |
| 223 | current_size = after_size |
| 224 | |
| 225 | 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:
| 236 | """ |
|---|---|
| 237 | Calculates the MessageCallGas (cost and gas made available to the sub-call) |
| 238 | for executing call Opcodes. |
| 239 | |
| 240 | Parameters |
| 241 | ---------- |
| 242 | value: |
| 243 | The amount of `ETH` that needs to be transferred. |
| 244 | gas : |
| 245 | The amount of gas provided to the message-call. |
| 246 | gas_left : |
| 247 | The amount of gas left in the current frame. |
| 248 | memory_cost : |
| 249 | The amount needed to extend the memory in the current frame. |
| 250 | extra_gas : |
| 251 | The amount of gas needed for transferring value + creating a new |
| 252 | account inside a message call. |
| 253 | call_stipend : |
| 254 | The amount of stipend provided to a message call to execute code while |
| 255 | transferring value (ETH). |
| 256 | |
| 257 | Returns |
| 258 | ------- |
| 259 | message_call_gas: `MessageCallGas` |
| 260 | |
| 261 | """ |
| 262 | call_stipend = Uint(0) if value == 0 else call_stipend |
| 263 | if gas_left < extra_gas + memory_cost: |
| 264 | return MessageCallGas(gas + extra_gas, gas + call_stipend) |
| 265 | |
| 266 | gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) |
| 267 | |
| 268 | 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:
| 272 | """ |
|---|---|
| 273 | Calculates the maximum gas that is allowed for making a message call. |
| 274 | |
| 275 | Parameters |
| 276 | ---------- |
| 277 | gas : |
| 278 | The amount of gas provided to the message-call. |
| 279 | |
| 280 | Returns |
| 281 | ------- |
| 282 | max_allowed_message_call_gas: `ethereum.base_types.Uint` |
| 283 | The maximum gas allowed for making the message-call. |
| 284 | |
| 285 | """ |
| 286 | 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:
| 290 | """ |
|---|---|
| 291 | Calculates the gas to be charged for the init code in CREATE* |
| 292 | opcodes as well as create transactions. |
| 293 | |
| 294 | Parameters |
| 295 | ---------- |
| 296 | init_code_length : |
| 297 | The length of the init code provided to the opcode |
| 298 | or a create transaction |
| 299 | |
| 300 | Returns |
| 301 | ------- |
| 302 | init_code_gas: `ethereum.base_types.Uint` |
| 303 | The gas to be charged for the init code. |
| 304 | |
| 305 | """ |
| 306 | 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: HeaderHeader | PreviousHeader) -> U64:
| 312 | """ |
|---|---|
| 313 | Calculates the excess blob gas for the current block based |
| 314 | on the gas used in the parent block. |
| 315 | |
| 316 | Parameters |
| 317 | ---------- |
| 318 | parent_header : |
| 319 | The parent block of the current block. |
| 320 | |
| 321 | Returns |
| 322 | ------- |
| 323 | excess_blob_gas: `ethereum.base_types.U64` |
| 324 | The excess blob gas for the current block. |
| 325 | |
| 326 | """ |
| 327 | # At the fork block, these are defined as zero. |
| 328 | excess_blob_gas = U64(0) |
| 329 | blob_gas_used = U64(0) |
| 330 | base_fee_per_gas = Uint(0) |
| 331 | |
| 332 | if isinstance(parent_header, Header): |
| 333 | # After the fork block, read them from the parent header. |
| 334 | excess_blob_gas = parent_header.excess_blob_gas |
| 335 | blob_gas_used = parent_header.blob_gas_used |
| 336 | base_fee_per_gas = parent_header.base_fee_per_gas |
| 337 | |
| 338 | parent_blob_gas = excess_blob_gas + blob_gas_used |
| 339 | if parent_blob_gas < BLOB_TARGET_GAS_PER_BLOCK: |
| 340 | return U64(0) |
| 341 | |
| 342 | target_blob_gas_price = Uint(GAS_PER_BLOB) |
| 343 | target_blob_gas_price *= calculate_blob_gas_price(excess_blob_gas) |
| 344 | |
| 345 | base_blob_tx_price = BLOB_BASE_COST * base_fee_per_gas |
| 346 | if base_blob_tx_price > target_blob_gas_price: |
| 347 | blob_schedule_delta = BLOB_SCHEDULE_MAX - BLOB_SCHEDULE_TARGET |
| 348 | return ( |
| 349 | excess_blob_gas |
| 350 | + blob_gas_used * blob_schedule_delta // BLOB_SCHEDULE_MAX |
| 351 | ) |
| 352 | |
| 353 | 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:
| 357 | """ |
|---|---|
| 358 | Calculate the total blob gas for a transaction. |
| 359 | |
| 360 | Parameters |
| 361 | ---------- |
| 362 | tx : |
| 363 | The transaction for which the blob gas is to be calculated. |
| 364 | |
| 365 | Returns |
| 366 | ------- |
| 367 | total_blob_gas: `ethereum.base_types.Uint` |
| 368 | The total blob gas for the transaction. |
| 369 | |
| 370 | """ |
| 371 | if isinstance(tx, BlobTransaction): |
| 372 | return GAS_PER_BLOB * U64(len(tx.blob_versioned_hashes)) |
| 373 | else: |
| 374 | 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:
| 378 | """ |
|---|---|
| 379 | Calculate the blob gasprice for a block. |
| 380 | |
| 381 | Parameters |
| 382 | ---------- |
| 383 | excess_blob_gas : |
| 384 | The excess blob gas for the block. |
| 385 | |
| 386 | Returns |
| 387 | ------- |
| 388 | blob_gasprice: `Uint` |
| 389 | The blob gasprice. |
| 390 | |
| 391 | """ |
| 392 | return taylor_exponential( |
| 393 | BLOB_MIN_GASPRICE, |
| 394 | Uint(excess_blob_gas), |
| 395 | BLOB_BASE_FEE_UPDATE_FRACTION, |
| 396 | ) |
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:
| 400 | """ |
|---|---|
| 401 | Calculate the blob data fee for a transaction. |
| 402 | |
| 403 | Parameters |
| 404 | ---------- |
| 405 | excess_blob_gas : |
| 406 | The excess_blob_gas for the execution. |
| 407 | tx : |
| 408 | The transaction for which the blob data fee is to be calculated. |
| 409 | |
| 410 | Returns |
| 411 | ------- |
| 412 | data_fee: `Uint` |
| 413 | The blob data fee. |
| 414 | |
| 415 | """ |
| 416 | return Uint(calculate_total_blob_gas(tx)) * calculate_blob_gas_price( |
| 417 | excess_blob_gas |
| 418 | ) |