ethereum.forks.muir_glacier.vm.gas
Ethereum Virtual Machine (EVM) Gas.
.. contents:: Table of Contents :backlinks: none :local:
Introduction
EVM gas constants and calculators.
GasCosts ¶
Constant gas values for the EVM.
class GasCosts:
BASE¶
| 33 | BASE = Uint(2) |
|---|
VERY_LOW¶
| 34 | VERY_LOW = Uint(3) |
|---|
LOW¶
| 35 | LOW = Uint(5) |
|---|
MID¶
| 36 | MID = Uint(8) |
|---|
HIGH¶
| 37 | HIGH = Uint(10) |
|---|
SLOAD¶
| 40 | SLOAD = Uint(800) |
|---|
STORAGE_SET¶
| 43 | STORAGE_SET = Uint(20000) |
|---|
COLD_STORAGE_WRITE¶
| 44 | COLD_STORAGE_WRITE = Uint(5000) |
|---|
CALL_VALUE¶
| 47 | CALL_VALUE = Uint(9000) |
|---|
CALL_STIPEND¶
| 48 | CALL_STIPEND = Uint(2300) |
|---|
NEW_ACCOUNT¶
| 49 | NEW_ACCOUNT = Uint(25000) |
|---|
CODE_DEPOSIT_PER_BYTE¶
| 52 | CODE_DEPOSIT_PER_BYTE = Uint(200) |
|---|
ZERO¶
| 55 | ZERO = Uint(0) |
|---|
MEMORY_PER_WORD¶
| 56 | MEMORY_PER_WORD = Uint(3) |
|---|
FAST_STEP¶
| 57 | FAST_STEP = Uint(5) |
|---|
REFUND_STORAGE_CLEAR¶
| 60 | REFUND_STORAGE_CLEAR = 15000 |
|---|
REFUND_SELF_DESTRUCT¶
| 61 | REFUND_SELF_DESTRUCT = 24000 |
|---|
PRECOMPILE_ECRECOVER¶
| 64 | PRECOMPILE_ECRECOVER = Uint(3000) |
|---|
PRECOMPILE_SHA256_BASE¶
| 65 | PRECOMPILE_SHA256_BASE = Uint(60) |
|---|
PRECOMPILE_SHA256_PER_WORD¶
| 66 | PRECOMPILE_SHA256_PER_WORD = Uint(12) |
|---|
PRECOMPILE_RIPEMD160_BASE¶
| 67 | PRECOMPILE_RIPEMD160_BASE = Uint(600) |
|---|
PRECOMPILE_RIPEMD160_PER_WORD¶
| 68 | PRECOMPILE_RIPEMD160_PER_WORD = Uint(120) |
|---|
PRECOMPILE_IDENTITY_BASE¶
| 69 | PRECOMPILE_IDENTITY_BASE = Uint(15) |
|---|
PRECOMPILE_IDENTITY_PER_WORD¶
| 70 | PRECOMPILE_IDENTITY_PER_WORD = Uint(3) |
|---|
PRECOMPILE_BLAKE2F_PER_ROUND¶
| 71 | PRECOMPILE_BLAKE2F_PER_ROUND = Uint(1) |
|---|
PRECOMPILE_ECADD¶
| 72 | PRECOMPILE_ECADD = Uint(150) |
|---|
PRECOMPILE_ECMUL¶
| 73 | PRECOMPILE_ECMUL = Uint(6000) |
|---|
PRECOMPILE_ECPAIRING_BASE¶
| 74 | PRECOMPILE_ECPAIRING_BASE = Uint(45000) |
|---|
PRECOMPILE_ECPAIRING_PER_POINT¶
| 75 | PRECOMPILE_ECPAIRING_PER_POINT = Uint(34000) |
|---|
TX_BASE¶
| 78 | TX_BASE = Uint(21000) |
|---|
TX_CREATE¶
| 79 | TX_CREATE = Uint(32000) |
|---|
TX_DATA_PER_ZERO¶
| 80 | TX_DATA_PER_ZERO = Uint(4) |
|---|
TX_DATA_PER_NON_ZERO¶
| 81 | TX_DATA_PER_NON_ZERO = Uint(16) |
|---|
LIMIT_ADJUSTMENT_FACTOR¶
| 84 | LIMIT_ADJUSTMENT_FACTOR = Uint(1024) |
|---|
LIMIT_MINIMUM¶
| 85 | LIMIT_MINIMUM = Uint(5000) |
|---|
OPCODE_ADD¶
| 88 | OPCODE_ADD = VERY_LOW |
|---|
OPCODE_SUB¶
| 89 | OPCODE_SUB = VERY_LOW |
|---|
OPCODE_MUL¶
| 90 | OPCODE_MUL = LOW |
|---|
OPCODE_DIV¶
| 91 | OPCODE_DIV = LOW |
|---|
OPCODE_SDIV¶
| 92 | OPCODE_SDIV = LOW |
|---|
OPCODE_MOD¶
| 93 | OPCODE_MOD = LOW |
|---|
OPCODE_SMOD¶
| 94 | OPCODE_SMOD = LOW |
|---|
OPCODE_ADDMOD¶
| 95 | OPCODE_ADDMOD = MID |
|---|
OPCODE_MULMOD¶
| 96 | OPCODE_MULMOD = MID |
|---|
OPCODE_SIGNEXTEND¶
| 97 | OPCODE_SIGNEXTEND = LOW |
|---|
OPCODE_LT¶
| 98 | OPCODE_LT = VERY_LOW |
|---|
OPCODE_GT¶
| 99 | OPCODE_GT = VERY_LOW |
|---|
OPCODE_SLT¶
| 100 | OPCODE_SLT = VERY_LOW |
|---|
OPCODE_SGT¶
| 101 | OPCODE_SGT = VERY_LOW |
|---|
OPCODE_EQ¶
| 102 | OPCODE_EQ = VERY_LOW |
|---|
OPCODE_ISZERO¶
| 103 | OPCODE_ISZERO = VERY_LOW |
|---|
OPCODE_AND¶
| 104 | OPCODE_AND = VERY_LOW |
|---|
OPCODE_OR¶
| 105 | OPCODE_OR = VERY_LOW |
|---|
OPCODE_XOR¶
| 106 | OPCODE_XOR = VERY_LOW |
|---|
OPCODE_NOT¶
| 107 | OPCODE_NOT = VERY_LOW |
|---|
OPCODE_BYTE¶
| 108 | OPCODE_BYTE = VERY_LOW |
|---|
OPCODE_SHL¶
| 109 | OPCODE_SHL = VERY_LOW |
|---|
OPCODE_SHR¶
| 110 | OPCODE_SHR = VERY_LOW |
|---|
OPCODE_SAR¶
| 111 | OPCODE_SAR = VERY_LOW |
|---|
OPCODE_JUMP¶
| 112 | OPCODE_JUMP = MID |
|---|
OPCODE_JUMPI¶
| 113 | OPCODE_JUMPI = HIGH |
|---|
OPCODE_JUMPDEST¶
| 114 | OPCODE_JUMPDEST = Uint(1) |
|---|
OPCODE_CALLDATALOAD¶
| 115 | OPCODE_CALLDATALOAD = VERY_LOW |
|---|
OPCODE_EXTCODEHASH¶
| 116 | OPCODE_EXTCODEHASH = Uint(700) |
|---|
OPCODE_BLOCKHASH¶
| 117 | OPCODE_BLOCKHASH = Uint(20) |
|---|
OPCODE_COINBASE¶
| 118 | OPCODE_COINBASE = BASE |
|---|
OPCODE_POP¶
| 119 | OPCODE_POP = BASE |
|---|
OPCODE_MSIZE¶
| 120 | OPCODE_MSIZE = BASE |
|---|
OPCODE_PC¶
| 121 | OPCODE_PC = BASE |
|---|
OPCODE_GAS¶
| 122 | OPCODE_GAS = BASE |
|---|
OPCODE_ADDRESS¶
| 123 | OPCODE_ADDRESS = BASE |
|---|
OPCODE_ORIGIN¶
| 124 | OPCODE_ORIGIN = BASE |
|---|
OPCODE_CALLER¶
| 125 | OPCODE_CALLER = BASE |
|---|
OPCODE_CALLVALUE¶
| 126 | OPCODE_CALLVALUE = BASE |
|---|
OPCODE_CALLDATASIZE¶
| 127 | OPCODE_CALLDATASIZE = BASE |
|---|
OPCODE_CODESIZE¶
| 128 | OPCODE_CODESIZE = BASE |
|---|
OPCODE_GASPRICE¶
| 129 | OPCODE_GASPRICE = BASE |
|---|
OPCODE_TIMESTAMP¶
| 130 | OPCODE_TIMESTAMP = BASE |
|---|
OPCODE_NUMBER¶
| 131 | OPCODE_NUMBER = BASE |
|---|
OPCODE_GASLIMIT¶
| 132 | OPCODE_GASLIMIT = BASE |
|---|
OPCODE_DIFFICULTY¶
| 133 | OPCODE_DIFFICULTY = BASE |
|---|
OPCODE_RETURNDATASIZE¶
| 134 | OPCODE_RETURNDATASIZE = BASE |
|---|
OPCODE_CHAINID¶
| 135 | OPCODE_CHAINID = BASE |
|---|
OPCODE_PUSH¶
| 136 | OPCODE_PUSH = VERY_LOW |
|---|
OPCODE_DUP¶
| 137 | OPCODE_DUP = VERY_LOW |
|---|
OPCODE_SWAP¶
| 138 | OPCODE_SWAP = VERY_LOW |
|---|
OPCODE_RETURNDATACOPY_BASE¶
| 141 | OPCODE_RETURNDATACOPY_BASE = VERY_LOW |
|---|
OPCODE_RETURNDATACOPY_PER_WORD¶
| 142 | OPCODE_RETURNDATACOPY_PER_WORD = Uint(3) |
|---|
OPCODE_CALLDATACOPY_BASE¶
| 143 | OPCODE_CALLDATACOPY_BASE = VERY_LOW |
|---|
OPCODE_CODECOPY_BASE¶
| 144 | OPCODE_CODECOPY_BASE = VERY_LOW |
|---|
OPCODE_MLOAD_BASE¶
| 145 | OPCODE_MLOAD_BASE = VERY_LOW |
|---|
OPCODE_MSTORE_BASE¶
| 146 | OPCODE_MSTORE_BASE = VERY_LOW |
|---|
OPCODE_MSTORE8_BASE¶
| 147 | OPCODE_MSTORE8_BASE = VERY_LOW |
|---|
OPCODE_COPY_PER_WORD¶
| 148 | OPCODE_COPY_PER_WORD = Uint(3) |
|---|
OPCODE_CREATE_BASE¶
| 149 | OPCODE_CREATE_BASE = Uint(32000) |
|---|
OPCODE_EXP_BASE¶
| 150 | OPCODE_EXP_BASE = Uint(10) |
|---|
OPCODE_EXP_PER_BYTE¶
| 151 | OPCODE_EXP_PER_BYTE = Uint(50) |
|---|
OPCODE_KECCAK256_BASE¶
| 152 | OPCODE_KECCAK256_BASE = Uint(30) |
|---|
OPCODE_KECCACK256_PER_WORD¶
| 153 | OPCODE_KECCACK256_PER_WORD = Uint(6) |
|---|
OPCODE_LOG_BASE¶
| 154 | OPCODE_LOG_BASE = Uint(375) |
|---|
OPCODE_LOG_DATA_PER_BYTE¶
| 155 | OPCODE_LOG_DATA_PER_BYTE = Uint(8) |
|---|
OPCODE_LOG_TOPIC¶
| 156 | OPCODE_LOG_TOPIC = Uint(375) |
|---|
OPCODE_SELFDESTRUCT_BASE¶
| 157 | OPCODE_SELFDESTRUCT_BASE = Uint(5000) |
|---|
OPCODE_SELFDESTRUCT_NEW_ACCOUNT¶
| 158 | OPCODE_SELFDESTRUCT_NEW_ACCOUNT = Uint(25000) |
|---|
OPCODE_EXTERNAL_BASE¶
| 159 | OPCODE_EXTERNAL_BASE = Uint(700) |
|---|
OPCODE_BALANCE¶
| 160 | OPCODE_BALANCE = Uint(700) |
|---|
OPCODE_CALL_BASE¶
| 161 | OPCODE_CALL_BASE = Uint(700) |
|---|
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
| 164 | @dataclass |
|---|
class ExtendMemory:
cost¶
| 175 | cost: Uint |
|---|
expand_by¶
| 176 | 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.
| 179 | @dataclass |
|---|
class MessageCallGas:
cost¶
| 193 | cost: Uint |
|---|
sub_call¶
| 194 | 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:
| 198 | """ |
|---|---|
| 199 | Subtracts `amount` from `evm.gas_left`. |
| 200 | |
| 201 | Parameters |
| 202 | ---------- |
| 203 | evm : |
| 204 | The current EVM. |
| 205 | amount : |
| 206 | The amount of gas the current operation requires. |
| 207 | |
| 208 | """ |
| 209 | evm_trace(evm, GasAndRefund(int(amount))) |
| 210 | |
| 211 | if evm.gas_left < amount: |
| 212 | raise OutOfGasError |
| 213 | else: |
| 214 | 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:
| 218 | """ |
|---|---|
| 219 | Calculates the gas cost for allocating memory |
| 220 | to the smallest multiple of 32 bytes, |
| 221 | such that the allocated size is at least as big as the given size. |
| 222 | |
| 223 | Parameters |
| 224 | ---------- |
| 225 | size_in_bytes : |
| 226 | The size of the data in bytes. |
| 227 | |
| 228 | Returns |
| 229 | ------- |
| 230 | total_gas_cost : `ethereum.base_types.Uint` |
| 231 | The gas cost for storing data in memory. |
| 232 | |
| 233 | """ |
| 234 | size_in_words = ceil32(size_in_bytes) // Uint(32) |
| 235 | linear_cost = size_in_words * GasCosts.MEMORY_PER_WORD |
| 236 | quadratic_cost = size_in_words ** Uint(2) // Uint(512) |
| 237 | total_gas_cost = linear_cost + quadratic_cost |
| 238 | try: |
| 239 | return total_gas_cost |
| 240 | except ValueError as e: |
| 241 | 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:
| 247 | """ |
|---|---|
| 248 | Calculates the gas amount to extend memory. |
| 249 | |
| 250 | Parameters |
| 251 | ---------- |
| 252 | memory : |
| 253 | Memory contents of the EVM. |
| 254 | extensions: |
| 255 | List of extensions to be made to the memory. |
| 256 | Consists of a tuple of start position and size. |
| 257 | |
| 258 | Returns |
| 259 | ------- |
| 260 | extend_memory: `ExtendMemory` |
| 261 | |
| 262 | """ |
| 263 | size_to_extend = Uint(0) |
| 264 | to_be_paid = Uint(0) |
| 265 | current_size = ulen(memory) |
| 266 | for start_position, size in extensions: |
| 267 | if size == 0: |
| 268 | continue |
| 269 | before_size = ceil32(current_size) |
| 270 | after_size = ceil32(Uint(start_position) + Uint(size)) |
| 271 | if after_size <= before_size: |
| 272 | continue |
| 273 | |
| 274 | size_to_extend += after_size - before_size |
| 275 | already_paid = calculate_memory_gas_cost(before_size) |
| 276 | total_cost = calculate_memory_gas_cost(after_size) |
| 277 | to_be_paid += total_cost - already_paid |
| 278 | |
| 279 | current_size = after_size |
| 280 | |
| 281 | 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:
| 292 | """ |
|---|---|
| 293 | Calculates the MessageCallGas (cost and gas made available to the sub-call) |
| 294 | for executing call Opcodes. |
| 295 | |
| 296 | Parameters |
| 297 | ---------- |
| 298 | value: |
| 299 | The amount of `ETH` that needs to be transferred. |
| 300 | gas : |
| 301 | The amount of gas provided to the message-call. |
| 302 | gas_left : |
| 303 | The amount of gas left in the current frame. |
| 304 | memory_cost : |
| 305 | The amount needed to extend the memory in the current frame. |
| 306 | extra_gas : |
| 307 | The amount of gas needed for transferring value + creating a new |
| 308 | account inside a message call. |
| 309 | call_stipend : |
| 310 | The amount of stipend provided to a message call to execute code while |
| 311 | transferring value (ETH). |
| 312 | |
| 313 | Returns |
| 314 | ------- |
| 315 | message_call_gas: `MessageCallGas` |
| 316 | |
| 317 | """ |
| 318 | call_stipend = Uint(0) if value == 0 else call_stipend |
| 319 | if gas_left < extra_gas + memory_cost: |
| 320 | return MessageCallGas(gas + extra_gas, gas + call_stipend) |
| 321 | |
| 322 | gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) |
| 323 | |
| 324 | 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:
| 328 | """ |
|---|---|
| 329 | Calculates the maximum gas that is allowed for making a message call. |
| 330 | |
| 331 | Parameters |
| 332 | ---------- |
| 333 | gas : |
| 334 | The amount of gas provided to the message-call. |
| 335 | |
| 336 | Returns |
| 337 | ------- |
| 338 | max_allowed_message_call_gas: `ethereum.base_types.Uint` |
| 339 | The maximum gas allowed for making the message-call. |
| 340 | |
| 341 | """ |
| 342 | return gas - (gas // Uint(64)) |