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