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