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