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.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.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.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 | charge_gas(evm, GAS_WARM_ACCESS) |
347 | else: |
348 | evm.accessed_addresses.add(address) |
349 | charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) |
350 | |
351 | # OPERATION |
352 | # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. |
353 | codesize = U256(len(get_account(evm.env.state, address).code)) |
354 | |
355 | push(evm.stack, codesize) |
356 | |
357 | # PROGRAM COUNTER |
358 | 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:
362 | """ |
---|---|
363 | Copy a portion of an account's code to memory. |
364 |
|
365 | Parameters |
366 | ---------- |
367 | evm : |
368 | The current EVM frame. |
369 |
|
370 | """ |
371 | # STACK |
372 | address = to_address(pop(evm.stack)) |
373 | memory_start_index = pop(evm.stack) |
374 | code_start_index = pop(evm.stack) |
375 | size = pop(evm.stack) |
376 | |
377 | # GAS |
378 | words = ceil32(Uint(size)) // Uint(32) |
379 | copy_gas_cost = GAS_COPY * words |
380 | extend_memory = calculate_gas_extend_memory( |
381 | evm.memory, [(memory_start_index, size)] |
382 | ) |
383 | |
384 | if address in evm.accessed_addresses: |
385 | charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) |
386 | else: |
387 | evm.accessed_addresses.add(address) |
388 | charge_gas( |
389 | evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost |
390 | ) |
391 | |
392 | # OPERATION |
393 | evm.memory += b"\x00" * extend_memory.expand_by |
394 | code = get_account(evm.env.state, address).code |
395 | value = buffer_read(code, code_start_index, size) |
396 | memory_write(evm.memory, memory_start_index, value) |
397 | |
398 | # PROGRAM COUNTER |
399 | 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:
403 | """ |
---|---|
404 | Pushes the size of the return data buffer onto the stack. |
405 |
|
406 | Parameters |
407 | ---------- |
408 | evm : |
409 | The current EVM frame. |
410 | """ |
411 | # STACK |
412 | pass |
413 | |
414 | # GAS |
415 | charge_gas(evm, GAS_BASE) |
416 | |
417 | # OPERATION |
418 | push(evm.stack, U256(len(evm.return_data))) |
419 | |
420 | # PROGRAM COUNTER |
421 | 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:
425 | """ |
---|---|
426 | Copies data from the return data buffer code to memory |
427 |
|
428 | Parameters |
429 | ---------- |
430 | evm : |
431 | The current EVM frame. |
432 | """ |
433 | # STACK |
434 | memory_start_index = pop(evm.stack) |
435 | return_data_start_position = pop(evm.stack) |
436 | size = pop(evm.stack) |
437 | |
438 | # GAS |
439 | words = ceil32(Uint(size)) // Uint(32) |
440 | copy_gas_cost = GAS_RETURN_DATA_COPY * words |
441 | extend_memory = calculate_gas_extend_memory( |
442 | evm.memory, [(memory_start_index, size)] |
443 | ) |
444 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
445 | if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): |
446 | raise OutOfBoundsRead |
447 | |
448 | evm.memory += b"\x00" * extend_memory.expand_by |
449 | value = evm.return_data[ |
450 | return_data_start_position : return_data_start_position + size |
451 | ] |
452 | memory_write(evm.memory, memory_start_index, value) |
453 | |
454 | # PROGRAM COUNTER |
455 | 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:
459 | """ |
---|---|
460 | Returns the keccak256 hash of a contract’s bytecode |
461 | Parameters |
462 | ---------- |
463 | evm : |
464 | The current EVM frame. |
465 | """ |
466 | # STACK |
467 | address = to_address(pop(evm.stack)) |
468 | |
469 | # GAS |
470 | if address in evm.accessed_addresses: |
471 | charge_gas(evm, GAS_WARM_ACCESS) |
472 | else: |
473 | evm.accessed_addresses.add(address) |
474 | charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) |
475 | |
476 | # OPERATION |
477 | account = get_account(evm.env.state, address) |
478 | |
479 | if account == EMPTY_ACCOUNT: |
480 | codehash = U256(0) |
481 | else: |
482 | codehash = U256.from_be_bytes(keccak256(account.code)) |
483 | |
484 | push(evm.stack, codehash) |
485 | |
486 | # PROGRAM COUNTER |
487 | 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:
491 | """ |
---|---|
492 | Pushes the balance of the current address to the stack. |
493 |
|
494 | Parameters |
495 | ---------- |
496 | evm : |
497 | The current EVM frame. |
498 |
|
499 | """ |
500 | # STACK |
501 | pass |
502 | |
503 | # GAS |
504 | charge_gas(evm, GAS_FAST_STEP) |
505 | |
506 | # OPERATION |
507 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
508 | balance = get_account(evm.env.state, evm.message.current_target).balance |
509 | |
510 | push(evm.stack, balance) |
511 | |
512 | # PROGRAM COUNTER |
513 | 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:
517 | """ |
---|---|
518 | Pushes the base fee of the current block on to the stack. |
519 |
|
520 | Parameters |
521 | ---------- |
522 | evm : |
523 | The current EVM frame. |
524 |
|
525 | """ |
526 | # STACK |
527 | pass |
528 | |
529 | # GAS |
530 | charge_gas(evm, GAS_BASE) |
531 | |
532 | # OPERATION |
533 | push(evm.stack, U256(evm.env.base_fee_per_gas)) |
534 | |
535 | # PROGRAM COUNTER |
536 | 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:
540 | """ |
---|---|
541 | Pushes the versioned hash at a particular index on to the stack. |
542 |
|
543 | Parameters |
544 | ---------- |
545 | evm : |
546 | The current EVM frame. |
547 |
|
548 | """ |
549 | # STACK |
550 | index = pop(evm.stack) |
551 | |
552 | # GAS |
553 | charge_gas(evm, GAS_BLOBHASH_OPCODE) |
554 | |
555 | # OPERATION |
556 | if int(index) < len(evm.env.blob_versioned_hashes): |
557 | blob_hash = evm.env.blob_versioned_hashes[index] |
558 | else: |
559 | blob_hash = Bytes32(b"\x00" * 32) |
560 | push(evm.stack, U256.from_be_bytes(blob_hash)) |
561 | |
562 | # PROGRAM COUNTER |
563 | 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:
567 | """ |
---|---|
568 | Pushes the blob base fee on to the stack. |
569 |
|
570 | Parameters |
571 | ---------- |
572 | evm : |
573 | The current EVM frame. |
574 |
|
575 | """ |
576 | # STACK |
577 | pass |
578 | |
579 | # GAS |
580 | charge_gas(evm, GAS_BASE) |
581 | |
582 | # OPERATION |
583 | blob_base_fee = calculate_blob_gas_price(evm.env.excess_blob_gas) |
584 | push(evm.stack, U256(blob_base_fee)) |
585 | |
586 | # PROGRAM COUNTER |
587 | evm.pc += Uint(1) |