ethereum.shanghai.vm.instructions.environmentethereum.cancun.vm.instructions.environment
Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. contents:: Table of Contents :backlinks: none :local:
Introduction
Implementations of the EVM environment related instructions.
address
Pushes the address of the current executing account to the stack.
Parameters
evm : The current EVM frame.
def address(evm: Evm) -> None:
42 | """ |
---|---|
43 | Pushes the address of the current executing account to the stack. |
44 |
|
45 | Parameters |
46 | ---------- |
47 | evm : |
48 | The current EVM frame. |
49 |
|
50 | """ |
51 | # STACK |
52 | pass |
53 | |
54 | # GAS |
55 | charge_gas(evm, GAS_BASE) |
56 | |
57 | # OPERATION |
58 | push(evm.stack, U256.from_be_bytes(evm.message.current_target)) |
59 | |
60 | # PROGRAM COUNTER |
61 | evm.pc += 1 |
balance
Pushes the balance of the given account onto the stack.
Parameters
evm : The current EVM frame.
def balance(evm: Evm) -> None:
65 | """ |
---|---|
66 | Pushes the balance of the given account onto the stack. |
67 |
|
68 | Parameters |
69 | ---------- |
70 | evm : |
71 | The current EVM frame. |
72 |
|
73 | """ |
74 | # STACK |
75 | address = to_address(pop(evm.stack)) |
76 | |
77 | # GAS |
78 | if address in evm.accessed_addresses: |
79 | charge_gas(evm, GAS_WARM_ACCESS) |
80 | else: |
81 | evm.accessed_addresses.add(address) |
82 | charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) |
83 | |
84 | # OPERATION |
85 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
86 | balance = get_account(evm.env.state, address).balance |
87 | |
88 | push(evm.stack, balance) |
89 | |
90 | # PROGRAM COUNTER |
91 | evm.pc += 1 |
origin
Pushes the address of the original transaction sender to the stack. The origin address can only be an EOA.
Parameters
evm : The current EVM frame.
def origin(evm: Evm) -> None:
95 | """ |
---|---|
96 | Pushes the address of the original transaction sender to the stack. |
97 | The origin address can only be an EOA. |
98 |
|
99 | Parameters |
100 | ---------- |
101 | evm : |
102 | The current EVM frame. |
103 |
|
104 | """ |
105 | # STACK |
106 | pass |
107 | |
108 | # GAS |
109 | charge_gas(evm, GAS_BASE) |
110 | |
111 | # OPERATION |
112 | push(evm.stack, U256.from_be_bytes(evm.env.origin)) |
113 | |
114 | # PROGRAM COUNTER |
115 | evm.pc += 1 |
caller
Pushes the address of the caller onto the stack.
Parameters
evm : The current EVM frame.
def caller(evm: Evm) -> None:
119 | """ |
---|---|
120 | Pushes the address of the caller onto the stack. |
121 |
|
122 | Parameters |
123 | ---------- |
124 | evm : |
125 | The current EVM frame. |
126 |
|
127 | """ |
128 | # STACK |
129 | pass |
130 | |
131 | # GAS |
132 | charge_gas(evm, GAS_BASE) |
133 | |
134 | # OPERATION |
135 | push(evm.stack, U256.from_be_bytes(evm.message.caller)) |
136 | |
137 | # PROGRAM COUNTER |
138 | evm.pc += 1 |
callvalue
Push the value (in wei) sent with the call onto the stack.
Parameters
evm : The current EVM frame.
def callvalue(evm: Evm) -> None:
142 | """ |
---|---|
143 | Push the value (in wei) sent with the call onto the stack. |
144 |
|
145 | Parameters |
146 | ---------- |
147 | evm : |
148 | The current EVM frame. |
149 |
|
150 | """ |
151 | # STACK |
152 | pass |
153 | |
154 | # GAS |
155 | charge_gas(evm, GAS_BASE) |
156 | |
157 | # OPERATION |
158 | push(evm.stack, evm.message.value) |
159 | |
160 | # PROGRAM COUNTER |
161 | evm.pc += 1 |
calldataload
Push a word (32 bytes) of the input data belonging to the current environment onto the stack.
Parameters
evm : The current EVM frame.
def calldataload(evm: Evm) -> None:
165 | """ |
---|---|
166 | Push a word (32 bytes) of the input data belonging to the current |
167 | environment onto the stack. |
168 |
|
169 | Parameters |
170 | ---------- |
171 | evm : |
172 | The current EVM frame. |
173 |
|
174 | """ |
175 | # STACK |
176 | start_index = pop(evm.stack) |
177 | |
178 | # GAS |
179 | charge_gas(evm, GAS_VERY_LOW) |
180 | |
181 | # OPERATION |
182 | value = buffer_read(evm.message.data, start_index, U256(32)) |
183 | |
184 | push(evm.stack, U256.from_be_bytes(value)) |
185 | |
186 | # PROGRAM COUNTER |
187 | evm.pc += 1 |
calldatasize
Push the size of input data in current environment onto the stack.
Parameters
evm : The current EVM frame.
def calldatasize(evm: Evm) -> None:
191 | """ |
---|---|
192 | Push the size of input data in current environment onto the stack. |
193 |
|
194 | Parameters |
195 | ---------- |
196 | evm : |
197 | The current EVM frame. |
198 |
|
199 | """ |
200 | # STACK |
201 | pass |
202 | |
203 | # GAS |
204 | charge_gas(evm, GAS_BASE) |
205 | |
206 | # OPERATION |
207 | push(evm.stack, U256(len(evm.message.data))) |
208 | |
209 | # PROGRAM COUNTER |
210 | evm.pc += 1 |
calldatacopy
Copy a portion of the input data in current environment to memory.
This will also expand the memory, in case that the memory is insufficient to store the data.
Parameters
evm : The current EVM frame.
def calldatacopy(evm: Evm) -> None:
214 | """ |
---|---|
215 | Copy a portion of the input data in current environment to memory. |
216 |
|
217 | This will also expand the memory, in case that the memory is insufficient |
218 | to store the data. |
219 |
|
220 | Parameters |
221 | ---------- |
222 | evm : |
223 | The current EVM frame. |
224 |
|
225 | """ |
226 | # STACK |
227 | memory_start_index = pop(evm.stack) |
228 | data_start_index = pop(evm.stack) |
229 | size = pop(evm.stack) |
230 | |
231 | # GAS |
232 | words = ceil32(Uint(size)) // 32 |
233 | copy_gas_cost = GAS_COPY * words |
234 | extend_memory = calculate_gas_extend_memory( |
235 | evm.memory, [(memory_start_index, size)] |
236 | ) |
237 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
238 | |
239 | # OPERATION |
240 | evm.memory += b"\x00" * extend_memory.expand_by |
241 | value = buffer_read(evm.message.data, data_start_index, size) |
242 | memory_write(evm.memory, memory_start_index, value) |
243 | |
244 | # PROGRAM COUNTER |
245 | evm.pc += 1 |
codesize
Push the size of code running in current environment onto the stack.
Parameters
evm : The current EVM frame.
def codesize(evm: Evm) -> None:
249 | """ |
---|---|
250 | Push the size of code running in current environment onto the stack. |
251 |
|
252 | Parameters |
253 | ---------- |
254 | evm : |
255 | The current EVM frame. |
256 |
|
257 | """ |
258 | # STACK |
259 | pass |
260 | |
261 | # GAS |
262 | charge_gas(evm, GAS_BASE) |
263 | |
264 | # OPERATION |
265 | push(evm.stack, U256(len(evm.code))) |
266 | |
267 | # PROGRAM COUNTER |
268 | evm.pc += 1 |
codecopy
Copy a portion of the code in current environment to memory.
This will also expand the memory, in case that the memory is insufficient to store the data.
Parameters
evm : The current EVM frame.
def codecopy(evm: Evm) -> None:
272 | """ |
---|---|
273 | Copy a portion of the code in current environment to memory. |
274 |
|
275 | This will also expand the memory, in case that the memory is insufficient |
276 | to store the data. |
277 |
|
278 | Parameters |
279 | ---------- |
280 | evm : |
281 | The current EVM frame. |
282 |
|
283 | """ |
284 | # STACK |
285 | memory_start_index = pop(evm.stack) |
286 | code_start_index = pop(evm.stack) |
287 | size = pop(evm.stack) |
288 | |
289 | # GAS |
290 | words = ceil32(Uint(size)) // 32 |
291 | copy_gas_cost = GAS_COPY * words |
292 | extend_memory = calculate_gas_extend_memory( |
293 | evm.memory, [(memory_start_index, size)] |
294 | ) |
295 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
296 | |
297 | # OPERATION |
298 | evm.memory += b"\x00" * extend_memory.expand_by |
299 | value = buffer_read(evm.code, code_start_index, size) |
300 | memory_write(evm.memory, memory_start_index, value) |
301 | |
302 | # PROGRAM COUNTER |
303 | evm.pc += 1 |
gasprice
Push the gas price used in current environment onto the stack.
Parameters
evm : The current EVM frame.
def gasprice(evm: Evm) -> None:
307 | """ |
---|---|
308 | Push the gas price used in current environment onto the stack. |
309 |
|
310 | Parameters |
311 | ---------- |
312 | evm : |
313 | The current EVM frame. |
314 |
|
315 | """ |
316 | # STACK |
317 | pass |
318 | |
319 | # GAS |
320 | charge_gas(evm, GAS_BASE) |
321 | |
322 | # OPERATION |
323 | push(evm.stack, U256(evm.env.gas_price)) |
324 | |
325 | # PROGRAM COUNTER |
326 | evm.pc += 1 |
extcodesize
Push the code size of a given account onto the stack.
Parameters
evm : The current EVM frame.
def extcodesize(evm: Evm) -> None:
330 | """ |
---|---|
331 | Push the code size of a given account onto the stack. |
332 |
|
333 | Parameters |
334 | ---------- |
335 | evm : |
336 | The current EVM frame. |
337 |
|
338 | """ |
339 | # STACK |
340 | address = to_address(pop(evm.stack)) |
341 | |
342 | # GAS |
343 | if address in evm.accessed_addresses: |
344 | charge_gas(evm, GAS_WARM_ACCESS) |
345 | else: |
346 | evm.accessed_addresses.add(address) |
347 | charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) |
348 | |
349 | # OPERATION |
350 | # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. |
351 | codesize = U256(len(get_account(evm.env.state, address).code)) |
352 | |
353 | push(evm.stack, codesize) |
354 | |
355 | # PROGRAM COUNTER |
356 | evm.pc += 1 |
extcodecopy
Copy a portion of an account's code to memory.
Parameters
evm : The current EVM frame.
def extcodecopy(evm: Evm) -> None:
360 | """ |
---|---|
361 | Copy a portion of an account's code to memory. |
362 |
|
363 | Parameters |
364 | ---------- |
365 | evm : |
366 | The current EVM frame. |
367 |
|
368 | """ |
369 | # STACK |
370 | address = to_address(pop(evm.stack)) |
371 | memory_start_index = pop(evm.stack) |
372 | code_start_index = pop(evm.stack) |
373 | size = pop(evm.stack) |
374 | |
375 | # GAS |
376 | words = ceil32(Uint(size)) // 32 |
377 | copy_gas_cost = GAS_COPY * words |
378 | extend_memory = calculate_gas_extend_memory( |
379 | evm.memory, [(memory_start_index, size)] |
380 | ) |
381 | |
382 | if address in evm.accessed_addresses: |
383 | charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) |
384 | else: |
385 | evm.accessed_addresses.add(address) |
386 | charge_gas( |
387 | evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost |
388 | ) |
389 | |
390 | # OPERATION |
391 | evm.memory += b"\x00" * extend_memory.expand_by |
392 | code = get_account(evm.env.state, address).code |
393 | value = buffer_read(code, code_start_index, size) |
394 | memory_write(evm.memory, memory_start_index, value) |
395 | |
396 | # PROGRAM COUNTER |
397 | evm.pc += 1 |
returndatasize
Pushes the size of the return data buffer onto the stack.
Parameters
evm : The current EVM frame.
def returndatasize(evm: Evm) -> None:
401 | """ |
---|---|
402 | Pushes the size of the return data buffer onto the stack. |
403 |
|
404 | Parameters |
405 | ---------- |
406 | evm : |
407 | The current EVM frame. |
408 | """ |
409 | # STACK |
410 | pass |
411 | |
412 | # GAS |
413 | charge_gas(evm, GAS_BASE) |
414 | |
415 | # OPERATION |
416 | push(evm.stack, U256(len(evm.return_data))) |
417 | |
418 | # PROGRAM COUNTER |
419 | evm.pc += 1 |
returndatacopy
Copies data from the return data buffer code to memory
Parameters
evm : The current EVM frame.
def returndatacopy(evm: Evm) -> None:
423 | """ |
---|---|
424 | Copies data from the return data buffer code to memory |
425 |
|
426 | Parameters |
427 | ---------- |
428 | evm : |
429 | The current EVM frame. |
430 | """ |
431 | # STACK |
432 | memory_start_index = pop(evm.stack) |
433 | return_data_start_position = pop(evm.stack) |
434 | size = pop(evm.stack) |
435 | |
436 | # GAS |
437 | words = ceil32(Uint(size)) // 32 |
438 | copy_gas_cost = GAS_RETURN_DATA_COPY * words |
439 | extend_memory = calculate_gas_extend_memory( |
440 | evm.memory, [(memory_start_index, size)] |
441 | ) |
442 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
443 | if Uint(return_data_start_position) + Uint(size) > len(evm.return_data): |
444 | raise OutOfBoundsRead |
445 | |
446 | evm.memory += b"\x00" * extend_memory.expand_by |
447 | value = evm.return_data[ |
448 | return_data_start_position : return_data_start_position + size |
449 | ] |
450 | memory_write(evm.memory, memory_start_index, value) |
451 | |
452 | # PROGRAM COUNTER |
453 | evm.pc += 1 |
extcodehash
Returns the keccak256 hash of a contract’s bytecode Parameters
evm : The current EVM frame.
def extcodehash(evm: Evm) -> None:
457 | """ |
---|---|
458 | Returns the keccak256 hash of a contract’s bytecode |
459 | Parameters |
460 | ---------- |
461 | evm : |
462 | The current EVM frame. |
463 | """ |
464 | # STACK |
465 | address = to_address(pop(evm.stack)) |
466 | |
467 | # GAS |
468 | if address in evm.accessed_addresses: |
469 | charge_gas(evm, GAS_WARM_ACCESS) |
470 | else: |
471 | evm.accessed_addresses.add(address) |
472 | charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) |
473 | |
474 | # OPERATION |
475 | account = get_account(evm.env.state, address) |
476 | |
477 | if account == EMPTY_ACCOUNT: |
478 | codehash = U256(0) |
479 | else: |
480 | codehash = U256.from_be_bytes(keccak256(account.code)) |
481 | |
482 | push(evm.stack, codehash) |
483 | |
484 | # PROGRAM COUNTER |
485 | evm.pc += 1 |
self_balance
Pushes the balance of the current address to the stack.
Parameters
evm : The current EVM frame.
def self_balance(evm: Evm) -> None:
489 | """ |
---|---|
490 | Pushes the balance of the current address to the stack. |
491 |
|
492 | Parameters |
493 | ---------- |
494 | evm : |
495 | The current EVM frame. |
496 |
|
497 | """ |
498 | # STACK |
499 | pass |
500 | |
501 | # GAS |
502 | charge_gas(evm, GAS_FAST_STEP) |
503 | |
504 | # OPERATION |
505 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
506 | balance = get_account(evm.env.state, evm.message.current_target).balance |
507 | |
508 | push(evm.stack, balance) |
509 | |
510 | # PROGRAM COUNTER |
511 | evm.pc += 1 |
base_fee
Pushes the base fee of the current block on to the stack.
Parameters
evm : The current EVM frame.
def base_fee(evm: Evm) -> None:
515 | """ |
---|---|
516 | Pushes the base fee of the current block on to the stack. |
517 |
|
518 | Parameters |
519 | ---------- |
520 | evm : |
521 | The current EVM frame. |
522 |
|
523 | """ |
524 | # STACK |
525 | pass |
526 | |
527 | # GAS |
528 | charge_gas(evm, GAS_BASE) |
529 | |
530 | # OPERATION |
531 | push(evm.stack, U256(evm.env.base_fee_per_gas)) |
532 | |
533 | # PROGRAM COUNTER |
534 | evm.pc += 1 |
blob_hash
Pushes the versioned hash at a particular index on to the stack.
Parameters
evm : The current EVM frame.
def blob_hash(evm: Evm) -> None:
538 | """ |
---|---|
539 | Pushes the versioned hash at a particular index on to the stack. |
540 |
|
541 | Parameters |
542 | ---------- |
543 | evm : |
544 | The current EVM frame. |
545 |
|
546 | """ |
547 | # STACK |
548 | index = pop(evm.stack) |
549 | |
550 | # GAS |
551 | charge_gas(evm, GAS_BLOBHASH_OPCODE) |
552 | |
553 | # OPERATION |
554 | if index < len(evm.env.blob_versioned_hashes): |
555 | blob_hash = evm.env.blob_versioned_hashes[index] |
556 | else: |
557 | blob_hash = Bytes32(b"\x00" * 32) |
558 | push(evm.stack, U256.from_be_bytes(blob_hash)) |
559 | |
560 | # PROGRAM COUNTER |
561 | evm.pc += 1 |
blob_base_fee
Pushes the blob base fee on to the stack.
Parameters
evm : The current EVM frame.
def blob_base_fee(evm: Evm) -> None:
565 | """ |
---|---|
566 | Pushes the blob base fee on to the stack. |
567 |
|
568 | Parameters |
569 | ---------- |
570 | evm : |
571 | The current EVM frame. |
572 |
|
573 | """ |
574 | # STACK |
575 | pass |
576 | |
577 | # GAS |
578 | charge_gas(evm, GAS_BASE) |
579 | |
580 | # OPERATION |
581 | blob_base_fee = calculate_blob_gas_price(evm.env.excess_blob_gas) |
582 | push(evm.stack, U256(blob_base_fee)) |
583 | |
584 | # PROGRAM COUNTER |
585 | evm.pc += 1 |