ethereum.arrow_glacier.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.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.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.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 | charge_gas(evm, GAS_WARM_ACCESS) |
344 | else: |
345 | evm.accessed_addresses.add(address) |
346 | charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) |
347 | |
348 | # OPERATION |
349 | # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. |
350 | codesize = U256(len(get_account(evm.env.state, address).code)) |
351 | |
352 | push(evm.stack, codesize) |
353 | |
354 | # PROGRAM COUNTER |
355 | 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:
359 | """ |
---|---|
360 | Copy a portion of an account's code to memory. |
361 |
|
362 | Parameters |
363 | ---------- |
364 | evm : |
365 | The current EVM frame. |
366 |
|
367 | """ |
368 | # STACK |
369 | address = to_address(pop(evm.stack)) |
370 | memory_start_index = pop(evm.stack) |
371 | code_start_index = pop(evm.stack) |
372 | size = pop(evm.stack) |
373 | |
374 | # GAS |
375 | words = ceil32(Uint(size)) // Uint(32) |
376 | copy_gas_cost = GAS_COPY * words |
377 | extend_memory = calculate_gas_extend_memory( |
378 | evm.memory, [(memory_start_index, size)] |
379 | ) |
380 | |
381 | if address in evm.accessed_addresses: |
382 | charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost) |
383 | else: |
384 | evm.accessed_addresses.add(address) |
385 | charge_gas( |
386 | evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost |
387 | ) |
388 | |
389 | # OPERATION |
390 | evm.memory += b"\x00" * extend_memory.expand_by |
391 | code = get_account(evm.env.state, address).code |
392 | value = buffer_read(code, code_start_index, size) |
393 | memory_write(evm.memory, memory_start_index, value) |
394 | |
395 | # PROGRAM COUNTER |
396 | 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:
400 | """ |
---|---|
401 | Pushes the size of the return data buffer onto the stack. |
402 |
|
403 | Parameters |
404 | ---------- |
405 | evm : |
406 | The current EVM frame. |
407 | """ |
408 | # STACK |
409 | pass |
410 | |
411 | # GAS |
412 | charge_gas(evm, GAS_BASE) |
413 | |
414 | # OPERATION |
415 | push(evm.stack, U256(len(evm.return_data))) |
416 | |
417 | # PROGRAM COUNTER |
418 | 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:
422 | """ |
---|---|
423 | Copies data from the return data buffer code to memory |
424 |
|
425 | Parameters |
426 | ---------- |
427 | evm : |
428 | The current EVM frame. |
429 | """ |
430 | # STACK |
431 | memory_start_index = pop(evm.stack) |
432 | return_data_start_position = pop(evm.stack) |
433 | size = pop(evm.stack) |
434 | |
435 | # GAS |
436 | words = ceil32(Uint(size)) // Uint(32) |
437 | copy_gas_cost = GAS_RETURN_DATA_COPY * words |
438 | extend_memory = calculate_gas_extend_memory( |
439 | evm.memory, [(memory_start_index, size)] |
440 | ) |
441 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
442 | if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): |
443 | raise OutOfBoundsRead |
444 | |
445 | evm.memory += b"\x00" * extend_memory.expand_by |
446 | value = evm.return_data[ |
447 | return_data_start_position : return_data_start_position + size |
448 | ] |
449 | memory_write(evm.memory, memory_start_index, value) |
450 | |
451 | # PROGRAM COUNTER |
452 | 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:
456 | """ |
---|---|
457 | Returns the keccak256 hash of a contract’s bytecode |
458 | Parameters |
459 | ---------- |
460 | evm : |
461 | The current EVM frame. |
462 | """ |
463 | # STACK |
464 | address = to_address(pop(evm.stack)) |
465 | |
466 | # GAS |
467 | if address in evm.accessed_addresses: |
468 | charge_gas(evm, GAS_WARM_ACCESS) |
469 | else: |
470 | evm.accessed_addresses.add(address) |
471 | charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS) |
472 | |
473 | # OPERATION |
474 | account = get_account(evm.env.state, address) |
475 | |
476 | if account == EMPTY_ACCOUNT: |
477 | codehash = U256(0) |
478 | else: |
479 | codehash = U256.from_be_bytes(keccak256(account.code)) |
480 | |
481 | push(evm.stack, codehash) |
482 | |
483 | # PROGRAM COUNTER |
484 | 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:
488 | """ |
---|---|
489 | Pushes the balance of the current address to the stack. |
490 |
|
491 | Parameters |
492 | ---------- |
493 | evm : |
494 | The current EVM frame. |
495 |
|
496 | """ |
497 | # STACK |
498 | pass |
499 | |
500 | # GAS |
501 | charge_gas(evm, GAS_FAST_STEP) |
502 | |
503 | # OPERATION |
504 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
505 | balance = get_account(evm.env.state, evm.message.current_target).balance |
506 | |
507 | push(evm.stack, balance) |
508 | |
509 | # PROGRAM COUNTER |
510 | 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:
514 | """ |
---|---|
515 | Pushes the base fee of the current block on to the stack. |
516 |
|
517 | Parameters |
518 | ---------- |
519 | evm : |
520 | The current EVM frame. |
521 |
|
522 | """ |
523 | # STACK |
524 | pass |
525 | |
526 | # GAS |
527 | charge_gas(evm, GAS_BASE) |
528 | |
529 | # OPERATION |
530 | push(evm.stack, U256(evm.env.base_fee_per_gas)) |
531 | |
532 | # PROGRAM COUNTER |
533 | evm.pc += Uint(1) |