ethereum.forks.muir_glacier.vm.instructions.environmentethereum.forks.berlin.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:
40 | """ |
---|---|
41 | Pushes the address of the current executing account to the stack. |
42 |
|
43 | Parameters |
44 | ---------- |
45 | evm : |
46 | The current EVM frame. |
47 |
|
48 | """ |
49 | # STACK |
50 | pass |
51 | |
52 | # GAS |
53 | charge_gas(evm, GAS_BASE) |
54 | |
55 | # OPERATION |
56 | push(evm.stack, U256.from_be_bytes(evm.message.current_target)) |
57 | |
58 | # PROGRAM COUNTER |
59 | 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:
63 | """ |
---|---|
64 | Pushes the balance of the given account onto the stack. |
65 |
|
66 | Parameters |
67 | ---------- |
68 | evm : |
69 | The current EVM frame. |
70 |
|
71 | """ |
72 | # STACK |
73 | address = to_address_masked(pop(evm.stack)) |
74 | |
75 | # GAS |
77 | charge_gas(evm, GAS_BALANCE) |
76 | if address in evm.accessed_addresses: |
77 | charge_gas(evm, GAS_WARM_ACCESS) |
78 | else: |
79 | evm.accessed_addresses.add(address) |
80 | charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) |
81 | |
82 | # OPERATION |
83 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
84 | balance = get_account(evm.message.block_env.state, address).balance |
85 | |
86 | push(evm.stack, balance) |
87 | |
88 | # PROGRAM COUNTER |
89 | 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:
93 | """ |
---|---|
94 | Pushes the address of the original transaction sender to the stack. |
95 | The origin address can only be an EOA. |
96 |
|
97 | Parameters |
98 | ---------- |
99 | evm : |
100 | The current EVM frame. |
101 |
|
102 | """ |
103 | # STACK |
104 | pass |
105 | |
106 | # GAS |
107 | charge_gas(evm, GAS_BASE) |
108 | |
109 | # OPERATION |
110 | push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) |
111 | |
112 | # PROGRAM COUNTER |
113 | 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:
117 | """ |
---|---|
118 | Pushes the address of the caller onto the stack. |
119 |
|
120 | Parameters |
121 | ---------- |
122 | evm : |
123 | The current EVM frame. |
124 |
|
125 | """ |
126 | # STACK |
127 | pass |
128 | |
129 | # GAS |
130 | charge_gas(evm, GAS_BASE) |
131 | |
132 | # OPERATION |
133 | push(evm.stack, U256.from_be_bytes(evm.message.caller)) |
134 | |
135 | # PROGRAM COUNTER |
136 | 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:
140 | """ |
---|---|
141 | Push the value (in wei) sent with the call onto the stack. |
142 |
|
143 | Parameters |
144 | ---------- |
145 | evm : |
146 | The current EVM frame. |
147 |
|
148 | """ |
149 | # STACK |
150 | pass |
151 | |
152 | # GAS |
153 | charge_gas(evm, GAS_BASE) |
154 | |
155 | # OPERATION |
156 | push(evm.stack, evm.message.value) |
157 | |
158 | # PROGRAM COUNTER |
159 | 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:
163 | """ |
---|---|
164 | Push a word (32 bytes) of the input data belonging to the current |
165 | environment onto the stack. |
166 |
|
167 | Parameters |
168 | ---------- |
169 | evm : |
170 | The current EVM frame. |
171 |
|
172 | """ |
173 | # STACK |
174 | start_index = pop(evm.stack) |
175 | |
176 | # GAS |
177 | charge_gas(evm, GAS_VERY_LOW) |
178 | |
179 | # OPERATION |
180 | value = buffer_read(evm.message.data, start_index, U256(32)) |
181 | |
182 | push(evm.stack, U256.from_be_bytes(value)) |
183 | |
184 | # PROGRAM COUNTER |
185 | 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:
189 | """ |
---|---|
190 | Push the size of input data in current environment onto the stack. |
191 |
|
192 | Parameters |
193 | ---------- |
194 | evm : |
195 | The current EVM frame. |
196 |
|
197 | """ |
198 | # STACK |
199 | pass |
200 | |
201 | # GAS |
202 | charge_gas(evm, GAS_BASE) |
203 | |
204 | # OPERATION |
205 | push(evm.stack, U256(len(evm.message.data))) |
206 | |
207 | # PROGRAM COUNTER |
208 | 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:
212 | """ |
---|---|
213 | Copy a portion of the input data in current environment to memory. |
214 |
|
215 | This will also expand the memory, in case that the memory is insufficient |
216 | to store the data. |
217 |
|
218 | Parameters |
219 | ---------- |
220 | evm : |
221 | The current EVM frame. |
222 |
|
223 | """ |
224 | # STACK |
225 | memory_start_index = pop(evm.stack) |
226 | data_start_index = pop(evm.stack) |
227 | size = pop(evm.stack) |
228 | |
229 | # GAS |
230 | words = ceil32(Uint(size)) // Uint(32) |
231 | copy_gas_cost = GAS_COPY * words |
232 | extend_memory = calculate_gas_extend_memory( |
233 | evm.memory, [(memory_start_index, size)] |
234 | ) |
235 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
236 | |
237 | # OPERATION |
238 | evm.memory += b"\x00" * extend_memory.expand_by |
239 | value = buffer_read(evm.message.data, data_start_index, size) |
240 | memory_write(evm.memory, memory_start_index, value) |
241 | |
242 | # PROGRAM COUNTER |
243 | 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:
247 | """ |
---|---|
248 | Push the size of code running in current environment onto the stack. |
249 |
|
250 | Parameters |
251 | ---------- |
252 | evm : |
253 | The current EVM frame. |
254 |
|
255 | """ |
256 | # STACK |
257 | pass |
258 | |
259 | # GAS |
260 | charge_gas(evm, GAS_BASE) |
261 | |
262 | # OPERATION |
263 | push(evm.stack, U256(len(evm.code))) |
264 | |
265 | # PROGRAM COUNTER |
266 | 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:
270 | """ |
---|---|
271 | Copy a portion of the code in current environment to memory. |
272 |
|
273 | This will also expand the memory, in case that the memory is insufficient |
274 | to store the data. |
275 |
|
276 | Parameters |
277 | ---------- |
278 | evm : |
279 | The current EVM frame. |
280 |
|
281 | """ |
282 | # STACK |
283 | memory_start_index = pop(evm.stack) |
284 | code_start_index = pop(evm.stack) |
285 | size = pop(evm.stack) |
286 | |
287 | # GAS |
288 | words = ceil32(Uint(size)) // Uint(32) |
289 | copy_gas_cost = GAS_COPY * words |
290 | extend_memory = calculate_gas_extend_memory( |
291 | evm.memory, [(memory_start_index, size)] |
292 | ) |
293 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
294 | |
295 | # OPERATION |
296 | evm.memory += b"\x00" * extend_memory.expand_by |
297 | value = buffer_read(evm.code, code_start_index, size) |
298 | memory_write(evm.memory, memory_start_index, value) |
299 | |
300 | # PROGRAM COUNTER |
301 | 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:
305 | """ |
---|---|
306 | Push the gas price used in current environment onto the stack. |
307 |
|
308 | Parameters |
309 | ---------- |
310 | evm : |
311 | The current EVM frame. |
312 |
|
313 | """ |
314 | # STACK |
315 | pass |
316 | |
317 | # GAS |
318 | charge_gas(evm, GAS_BASE) |
319 | |
320 | # OPERATION |
321 | push(evm.stack, U256(evm.message.tx_env.gas_price)) |
322 | |
323 | # PROGRAM COUNTER |
324 | 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:
328 | """ |
---|---|
329 | Push the code size of a given account onto the stack. |
330 |
|
331 | Parameters |
332 | ---------- |
333 | evm : |
334 | The current EVM frame. |
335 |
|
336 | """ |
337 | # STACK |
338 | address = to_address_masked(pop(evm.stack)) |
339 | |
340 | # GAS |
338 | charge_gas(evm, GAS_EXTERNAL) |
341 | if address in evm.accessed_addresses: |
342 | access_gas_cost = GAS_WARM_ACCESS |
343 | else: |
344 | evm.accessed_addresses.add(address) |
345 | access_gas_cost = GAS_COLD_ACCOUNT_ACCESS |
346 | |
347 | charge_gas(evm, access_gas_cost) |
348 | |
349 | # OPERATION |
350 | code = get_account(evm.message.block_env.state, address).code |
351 | |
352 | codesize = U256(len(code)) |
353 | push(evm.stack, codesize) |
354 | |
355 | # PROGRAM COUNTER |
356 | 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:
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_masked(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)) // Uint(32) |
377 | copy_gas_cost = GAS_COPY * words |
378 | extend_memory = calculate_gas_extend_memory( |
379 | evm.memory, [(memory_start_index, size)] |
380 | ) |
372 | charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) |
381 | |
382 | if address in evm.accessed_addresses: |
383 | access_gas_cost = GAS_WARM_ACCESS |
384 | else: |
385 | evm.accessed_addresses.add(address) |
386 | access_gas_cost = GAS_COLD_ACCOUNT_ACCESS |
387 | |
388 | charge_gas(evm, access_gas_cost + copy_gas_cost + extend_memory.cost) |
389 | |
390 | # OPERATION |
391 | evm.memory += b"\x00" * extend_memory.expand_by |
392 | code = get_account(evm.message.block_env.state, address).code |
393 | |
394 | value = buffer_read(code, code_start_index, size) |
395 | memory_write(evm.memory, memory_start_index, value) |
396 | |
397 | # PROGRAM COUNTER |
398 | 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:
402 | """ |
---|---|
403 | Pushes the size of the return data buffer onto the stack. |
404 |
|
405 | Parameters |
406 | ---------- |
407 | evm : |
408 | The current EVM frame. |
409 |
|
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 | """ |
434 | # STACK |
435 | memory_start_index = pop(evm.stack) |
436 | return_data_start_position = pop(evm.stack) |
437 | size = pop(evm.stack) |
438 | |
439 | # GAS |
440 | words = ceil32(Uint(size)) // Uint(32) |
441 | copy_gas_cost = GAS_RETURN_DATA_COPY * words |
442 | extend_memory = calculate_gas_extend_memory( |
443 | evm.memory, [(memory_start_index, size)] |
444 | ) |
445 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
446 | if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): |
447 | raise OutOfBoundsRead |
448 | |
449 | evm.memory += b"\x00" * extend_memory.expand_by |
450 | value = evm.return_data[ |
451 | return_data_start_position : return_data_start_position + size |
452 | ] |
453 | memory_write(evm.memory, memory_start_index, value) |
454 | |
455 | # PROGRAM COUNTER |
456 | 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:
460 | """ |
---|---|
461 | Returns the keccak256 hash of a contract’s bytecode. |
462 |
|
463 | Parameters |
464 | ---------- |
465 | evm : |
466 | The current EVM frame. |
467 |
|
468 | """ |
469 | # STACK |
470 | address = to_address_masked(pop(evm.stack)) |
471 | |
472 | # GAS |
457 | charge_gas(evm, GAS_CODE_HASH) |
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) |