ethereum.berlin.vm.instructions.environmentethereum.london.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:
41 | """ |
---|---|
42 | Pushes the address of the current executing account to the stack. |
43 |
|
44 | Parameters |
45 | ---------- |
46 | evm : |
47 | The current EVM frame. |
48 |
|
49 | """ |
50 | # STACK |
51 | pass |
52 | |
53 | # GAS |
54 | charge_gas(evm, GAS_BASE) |
55 | |
56 | # OPERATION |
57 | push(evm.stack, U256.from_be_bytes(evm.message.current_target)) |
58 | |
59 | # PROGRAM COUNTER |
60 | 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:
64 | """ |
---|---|
65 | Pushes the balance of the given account onto the stack. |
66 |
|
67 | Parameters |
68 | ---------- |
69 | evm : |
70 | The current EVM frame. |
71 |
|
72 | """ |
73 | # STACK |
74 | address = to_address(pop(evm.stack)) |
75 | |
76 | # GAS |
77 | if address in evm.accessed_addresses: |
78 | charge_gas(evm, GAS_WARM_ACCESS) |
79 | else: |
80 | evm.accessed_addresses.add(address) |
81 | charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) |
82 | |
83 | # OPERATION |
84 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
85 | balance = get_account(evm.message.block_env.state, address).balance |
86 | |
87 | push(evm.stack, balance) |
88 | |
89 | # PROGRAM COUNTER |
90 | 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:
94 | """ |
---|---|
95 | Pushes the address of the original transaction sender to the stack. |
96 | The origin address can only be an EOA. |
97 |
|
98 | Parameters |
99 | ---------- |
100 | evm : |
101 | The current EVM frame. |
102 |
|
103 | """ |
104 | # STACK |
105 | pass |
106 | |
107 | # GAS |
108 | charge_gas(evm, GAS_BASE) |
109 | |
110 | # OPERATION |
111 | push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) |
112 | |
113 | # PROGRAM COUNTER |
114 | 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:
118 | """ |
---|---|
119 | Pushes the address of the caller onto the stack. |
120 |
|
121 | Parameters |
122 | ---------- |
123 | evm : |
124 | The current EVM frame. |
125 |
|
126 | """ |
127 | # STACK |
128 | pass |
129 | |
130 | # GAS |
131 | charge_gas(evm, GAS_BASE) |
132 | |
133 | # OPERATION |
134 | push(evm.stack, U256.from_be_bytes(evm.message.caller)) |
135 | |
136 | # PROGRAM COUNTER |
137 | 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:
141 | """ |
---|---|
142 | Push the value (in wei) sent with the call onto the stack. |
143 |
|
144 | Parameters |
145 | ---------- |
146 | evm : |
147 | The current EVM frame. |
148 |
|
149 | """ |
150 | # STACK |
151 | pass |
152 | |
153 | # GAS |
154 | charge_gas(evm, GAS_BASE) |
155 | |
156 | # OPERATION |
157 | push(evm.stack, evm.message.value) |
158 | |
159 | # PROGRAM COUNTER |
160 | 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:
164 | """ |
---|---|
165 | Push a word (32 bytes) of the input data belonging to the current |
166 | environment onto the stack. |
167 |
|
168 | Parameters |
169 | ---------- |
170 | evm : |
171 | The current EVM frame. |
172 |
|
173 | """ |
174 | # STACK |
175 | start_index = pop(evm.stack) |
176 | |
177 | # GAS |
178 | charge_gas(evm, GAS_VERY_LOW) |
179 | |
180 | # OPERATION |
181 | value = buffer_read(evm.message.data, start_index, U256(32)) |
182 | |
183 | push(evm.stack, U256.from_be_bytes(value)) |
184 | |
185 | # PROGRAM COUNTER |
186 | 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:
190 | """ |
---|---|
191 | Push the size of input data in current environment onto the stack. |
192 |
|
193 | Parameters |
194 | ---------- |
195 | evm : |
196 | The current EVM frame. |
197 |
|
198 | """ |
199 | # STACK |
200 | pass |
201 | |
202 | # GAS |
203 | charge_gas(evm, GAS_BASE) |
204 | |
205 | # OPERATION |
206 | push(evm.stack, U256(len(evm.message.data))) |
207 | |
208 | # PROGRAM COUNTER |
209 | 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:
213 | """ |
---|---|
214 | Copy a portion of the input data in current environment to memory. |
215 |
|
216 | This will also expand the memory, in case that the memory is insufficient |
217 | to store the data. |
218 |
|
219 | Parameters |
220 | ---------- |
221 | evm : |
222 | The current EVM frame. |
223 |
|
224 | """ |
225 | # STACK |
226 | memory_start_index = pop(evm.stack) |
227 | data_start_index = pop(evm.stack) |
228 | size = pop(evm.stack) |
229 | |
230 | # GAS |
231 | words = ceil32(Uint(size)) // Uint(32) |
232 | copy_gas_cost = GAS_COPY * words |
233 | extend_memory = calculate_gas_extend_memory( |
234 | evm.memory, [(memory_start_index, size)] |
235 | ) |
236 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
237 | |
238 | # OPERATION |
239 | evm.memory += b"\x00" * extend_memory.expand_by |
240 | value = buffer_read(evm.message.data, data_start_index, size) |
241 | memory_write(evm.memory, memory_start_index, value) |
242 | |
243 | # PROGRAM COUNTER |
244 | 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:
248 | """ |
---|---|
249 | Push the size of code running in current environment onto the stack. |
250 |
|
251 | Parameters |
252 | ---------- |
253 | evm : |
254 | The current EVM frame. |
255 |
|
256 | """ |
257 | # STACK |
258 | pass |
259 | |
260 | # GAS |
261 | charge_gas(evm, GAS_BASE) |
262 | |
263 | # OPERATION |
264 | push(evm.stack, U256(len(evm.code))) |
265 | |
266 | # PROGRAM COUNTER |
267 | 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:
271 | """ |
---|---|
272 | Copy a portion of the code in current environment to memory. |
273 |
|
274 | This will also expand the memory, in case that the memory is insufficient |
275 | to store the data. |
276 |
|
277 | Parameters |
278 | ---------- |
279 | evm : |
280 | The current EVM frame. |
281 |
|
282 | """ |
283 | # STACK |
284 | memory_start_index = pop(evm.stack) |
285 | code_start_index = pop(evm.stack) |
286 | size = pop(evm.stack) |
287 | |
288 | # GAS |
289 | words = ceil32(Uint(size)) // Uint(32) |
290 | copy_gas_cost = GAS_COPY * words |
291 | extend_memory = calculate_gas_extend_memory( |
292 | evm.memory, [(memory_start_index, size)] |
293 | ) |
294 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
295 | |
296 | # OPERATION |
297 | evm.memory += b"\x00" * extend_memory.expand_by |
298 | value = buffer_read(evm.code, code_start_index, size) |
299 | memory_write(evm.memory, memory_start_index, value) |
300 | |
301 | # PROGRAM COUNTER |
302 | 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:
306 | """ |
---|---|
307 | Push the gas price used in current environment onto the stack. |
308 |
|
309 | Parameters |
310 | ---------- |
311 | evm : |
312 | The current EVM frame. |
313 |
|
314 | """ |
315 | # STACK |
316 | pass |
317 | |
318 | # GAS |
319 | charge_gas(evm, GAS_BASE) |
320 | |
321 | # OPERATION |
322 | push(evm.stack, U256(evm.message.tx_env.gas_price)) |
323 | |
324 | # PROGRAM COUNTER |
325 | 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:
329 | """ |
---|---|
330 | Push the code size of a given account onto the stack. |
331 |
|
332 | Parameters |
333 | ---------- |
334 | evm : |
335 | The current EVM frame. |
336 |
|
337 | """ |
338 | # STACK |
339 | address = to_address(pop(evm.stack)) |
340 | |
341 | # GAS |
342 | if address in evm.accessed_addresses: |
343 | access_gas_cost = GAS_WARM_ACCESS |
344 | else: |
345 | evm.accessed_addresses.add(address) |
346 | access_gas_cost = GAS_COLD_ACCOUNT_ACCESS |
347 | |
348 | charge_gas(evm, access_gas_cost) |
349 | |
350 | # OPERATION |
351 | code = get_account(evm.message.block_env.state, address).code |
352 | |
353 | codesize = U256(len(code)) |
354 | push(evm.stack, codesize) |
355 | |
356 | # PROGRAM COUNTER |
357 | 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:
361 | """ |
---|---|
362 | Copy a portion of an account's code to memory. |
363 |
|
364 | Parameters |
365 | ---------- |
366 | evm : |
367 | The current EVM frame. |
368 |
|
369 | """ |
370 | # STACK |
371 | address = to_address(pop(evm.stack)) |
372 | memory_start_index = pop(evm.stack) |
373 | code_start_index = pop(evm.stack) |
374 | size = pop(evm.stack) |
375 | |
376 | # GAS |
377 | words = ceil32(Uint(size)) // Uint(32) |
378 | copy_gas_cost = GAS_COPY * words |
379 | extend_memory = calculate_gas_extend_memory( |
380 | evm.memory, [(memory_start_index, size)] |
381 | ) |
382 | |
383 | if address in evm.accessed_addresses: |
384 | access_gas_cost = GAS_WARM_ACCESS |
385 | else: |
386 | evm.accessed_addresses.add(address) |
387 | access_gas_cost = GAS_COLD_ACCOUNT_ACCESS |
388 | |
389 | charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) |
390 | |
391 | # OPERATION |
392 | evm.memory += b"\x00" * extend_memory.expand_by |
393 | code = get_account(evm.message.block_env.state, address).code |
394 | |
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 | access_gas_cost = GAS_WARM_ACCESS |
472 | else: |
473 | evm.accessed_addresses.add(address) |
474 | access_gas_cost = GAS_COLD_ACCOUNT_ACCESS |
475 | |
476 | charge_gas(evm, access_gas_cost) |
477 | |
478 | # OPERATION |
479 | account = get_account(evm.message.block_env.state, address) |
480 | |
481 | if account == EMPTY_ACCOUNT: |
482 | codehash = U256(0) |
483 | else: |
484 | code = account.code |
485 | codehash = U256.from_be_bytes(keccak256(code)) |
486 | |
487 | push(evm.stack, codehash) |
488 | |
489 | # PROGRAM COUNTER |
490 | 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:
494 | """ |
---|---|
495 | Pushes the balance of the current address to the stack. |
496 |
|
497 | Parameters |
498 | ---------- |
499 | evm : |
500 | The current EVM frame. |
501 |
|
502 | """ |
503 | # STACK |
504 | pass |
505 | |
506 | # GAS |
507 | charge_gas(evm, GAS_FAST_STEP) |
508 | |
509 | # OPERATION |
510 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
511 | balance = get_account( |
512 | evm.message.block_env.state, evm.message.current_target |
513 | ).balance |
514 | |
515 | push(evm.stack, balance) |
516 | |
517 | # PROGRAM COUNTER |
518 | 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:
522 | """ |
---|---|
523 | Pushes the base fee of the current block on to the stack. |
524 |
|
525 | Parameters |
526 | ---------- |
527 | evm : |
528 | The current EVM frame. |
529 |
|
530 | """ |
531 | # STACK |
532 | pass |
533 | |
534 | # GAS |
535 | charge_gas(evm, GAS_BASE) |
536 | |
537 | # OPERATION |
538 | push(evm.stack, U256(evm.message.block_env.base_fee_per_gas)) |
539 | |
540 | # PROGRAM COUNTER |
541 | evm.pc += Uint(1) |