ethereum.cancun.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) |
---|
GAS_STORAGE_CLEAR_REFUND
32 | GAS_STORAGE_CLEAR_REFUND = Uint(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_WORD
40 | GAS_KECCAK256_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
44 | GAS_LOG_DATA = Uint(8) |
---|
GAS_LOG_TOPIC
45 | GAS_LOG_TOPIC = Uint(375) |
---|
GAS_CREATE
46 | GAS_CREATE = Uint(32000) |
---|
GAS_CODE_DEPOSIT
47 | GAS_CODE_DEPOSIT = 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_INIT_CODE_WORD_COST
67 | GAS_INIT_CODE_WORD_COST = Uint(2) |
---|
GAS_BLOBHASH_OPCODE
68 | GAS_BLOBHASH_OPCODE = Uint(3) |
---|
GAS_POINT_EVALUATION
69 | GAS_POINT_EVALUATION = Uint(50000) |
---|
TARGET_BLOB_GAS_PER_BLOCK
71 | TARGET_BLOB_GAS_PER_BLOCK = U64(393216) |
---|
GAS_PER_BLOB
72 | GAS_PER_BLOB = Uint(2**17) |
---|
MIN_BLOB_GASPRICE
73 | MIN_BLOB_GASPRICE = Uint(1) |
---|
BLOB_GASPRICE_UPDATE_FRACTION
74 | BLOB_GASPRICE_UPDATE_FRACTION = Uint(3338477) |
---|
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
77 | @dataclass |
---|
class ExtendMemory:
cost
88 | cost: Uint |
---|
expand_by
89 | expand_by: Uint |
---|
MessageCallGas
Define the gas cost and stipend for executing the call opcodes.
cost
: ethereum.base_types.Uint
The non-refundable portion of gas reserved for executing the
call opcode.
stipend
: ethereum.base_types.Uint
The portion of gas available to sub-calls that is refundable
if not consumed
92 | @dataclass |
---|
class MessageCallGas:
cost
105 | cost: Uint |
---|
stipend
106 | stipend: 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:
110 | """ |
---|---|
111 | Subtracts `amount` from `evm.gas_left`. |
112 |
|
113 | Parameters |
114 | ---------- |
115 | evm : |
116 | The current EVM. |
117 | amount : |
118 | The amount of gas the current operation requires. |
119 |
|
120 | """ |
121 | evm_trace(evm, GasAndRefund(int(amount))) |
122 | |
123 | if evm.gas_left < amount: |
124 | raise OutOfGasError |
125 | else: |
126 | 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:
130 | """ |
---|---|
131 | Calculates the gas cost for allocating memory |
132 | to the smallest multiple of 32 bytes, |
133 | such that the allocated size is at least as big as the given size. |
134 |
|
135 | Parameters |
136 | ---------- |
137 | size_in_bytes : |
138 | The size of the data in bytes. |
139 |
|
140 | Returns |
141 | ------- |
142 | total_gas_cost : `ethereum.base_types.Uint` |
143 | The gas cost for storing data in memory. |
144 | """ |
145 | size_in_words = ceil32(size_in_bytes) // Uint(32) |
146 | linear_cost = size_in_words * GAS_MEMORY |
147 | quadratic_cost = size_in_words ** Uint(2) // Uint(512) |
148 | total_gas_cost = linear_cost + quadratic_cost |
149 | try: |
150 | return total_gas_cost |
151 | except ValueError: |
152 | raise OutOfGasError |
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:
158 | """ |
---|---|
159 | Calculates the gas amount to extend memory |
160 |
|
161 | Parameters |
162 | ---------- |
163 | memory : |
164 | Memory contents of the EVM. |
165 | extensions: |
166 | List of extensions to be made to the memory. |
167 | Consists of a tuple of start position and size. |
168 |
|
169 | Returns |
170 | ------- |
171 | extend_memory: `ExtendMemory` |
172 | """ |
173 | size_to_extend = Uint(0) |
174 | to_be_paid = Uint(0) |
175 | current_size = Uint(len(memory)) |
176 | for start_position, size in extensions: |
177 | if size == 0: |
178 | continue |
179 | before_size = ceil32(current_size) |
180 | after_size = ceil32(Uint(start_position) + Uint(size)) |
181 | if after_size <= before_size: |
182 | continue |
183 |
|
184 | size_to_extend += after_size - before_size |
185 | already_paid = calculate_memory_gas_cost(before_size) |
186 | total_cost = calculate_memory_gas_cost(after_size) |
187 | to_be_paid += total_cost - already_paid |
188 |
|
189 | current_size = after_size |
190 | |
191 | return ExtendMemory(to_be_paid, size_to_extend) |
calculate_message_call_gas
Calculates the MessageCallGas (cost and stipend) 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:
202 | """ |
---|---|
203 | Calculates the MessageCallGas (cost and stipend) for |
204 | executing call Opcodes. |
205 |
|
206 | Parameters |
207 | ---------- |
208 | value: |
209 | The amount of `ETH` that needs to be transferred. |
210 | gas : |
211 | The amount of gas provided to the message-call. |
212 | gas_left : |
213 | The amount of gas left in the current frame. |
214 | memory_cost : |
215 | The amount needed to extend the memory in the current frame. |
216 | extra_gas : |
217 | The amount of gas needed for transferring value + creating a new |
218 | account inside a message call. |
219 | call_stipend : |
220 | The amount of stipend provided to a message call to execute code while |
221 | transferring value(ETH). |
222 |
|
223 | Returns |
224 | ------- |
225 | message_call_gas: `MessageCallGas` |
226 | """ |
227 | call_stipend = Uint(0) if value == 0 else call_stipend |
228 | if gas_left < extra_gas + memory_cost: |
229 | return MessageCallGas(gas + extra_gas, gas + call_stipend) |
230 | |
231 | gas = min(gas, max_message_call_gas(gas_left - memory_cost - extra_gas)) |
232 | |
233 | 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:
237 | """ |
---|---|
238 | Calculates the maximum gas that is allowed for making a message call |
239 |
|
240 | Parameters |
241 | ---------- |
242 | gas : |
243 | The amount of gas provided to the message-call. |
244 |
|
245 | Returns |
246 | ------- |
247 | max_allowed_message_call_gas: `ethereum.base_types.Uint` |
248 | The maximum gas allowed for making the message-call. |
249 | """ |
250 | return gas - (gas // Uint(64)) |
init_code_cost
Calculates the gas to be charged for the init code in CREAT* 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:
254 | """ |
---|---|
255 | Calculates the gas to be charged for the init code in CREAT* |
256 | opcodes as well as create transactions. |
257 |
|
258 | Parameters |
259 | ---------- |
260 | init_code_length : |
261 | The length of the init code provided to the opcode |
262 | or a create transaction |
263 |
|
264 | Returns |
265 | ------- |
266 | init_code_gas: `ethereum.base_types.Uint` |
267 | The gas to be charged for the init code. |
268 | """ |
269 | return GAS_INIT_CODE_WORD_COST * ceil32(init_code_length) // Uint(32) |
calculate_excess_blob_gas
Calculated 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:
273 | """ |
---|---|
274 | Calculated the excess blob gas for the current block based |
275 | on the gas used in the parent block. |
276 |
|
277 | Parameters |
278 | ---------- |
279 | parent_header : |
280 | The parent block of the current block. |
281 |
|
282 | Returns |
283 | ------- |
284 | excess_blob_gas: `ethereum.base_types.U64` |
285 | The excess blob gas for the current block. |
286 | """ |
287 | parent_blob_gas = ( |
288 | parent_header.excess_blob_gas + parent_header.blob_gas_used |
289 | ) |
290 | if parent_blob_gas < TARGET_BLOB_GAS_PER_BLOCK: |
291 | return U64(0) |
292 | else: |
293 | return parent_blob_gas - TARGET_BLOB_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) -> Uint:
297 | """ |
---|---|
298 | Calculate the total blob gas for a transaction. |
299 |
|
300 | Parameters |
301 | ---------- |
302 | tx : |
303 | The transaction for which the blob gas is to be calculated. |
304 |
|
305 | Returns |
306 | ------- |
307 | total_blob_gas: `ethereum.base_types.Uint` |
308 | The total blob gas for the transaction. |
309 | """ |
310 | if isinstance(tx, BlobTransaction): |
311 | return GAS_PER_BLOB * Uint(len(tx.blob_versioned_hashes)) |
312 | else: |
313 | return Uint(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:
317 | """ |
---|---|
318 | Calculate the blob gasprice for a block. |
319 |
|
320 | Parameters |
321 | ---------- |
322 | excess_blob_gas : |
323 | The excess blob gas for the block. |
324 |
|
325 | Returns |
326 | ------- |
327 | blob_gasprice: `Uint` |
328 | The blob gasprice. |
329 | """ |
330 | return taylor_exponential( |
331 | MIN_BLOB_GASPRICE, |
332 | Uint(excess_blob_gas), |
333 | BLOB_GASPRICE_UPDATE_FRACTION, |
334 | ) |
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:
338 | """ |
---|---|
339 | Calculate the blob data fee for a transaction. |
340 |
|
341 | Parameters |
342 | ---------- |
343 | excess_blob_gas : |
344 | The excess_blob_gas for the execution. |
345 | tx : |
346 | The transaction for which the blob data fee is to be calculated. |
347 |
|
348 | Returns |
349 | ------- |
350 | data_fee: `Uint` |
351 | The blob data fee. |
352 | """ |
353 | return calculate_total_blob_gas(tx) * calculate_blob_gas_price( |
354 | excess_blob_gas |
355 | ) |