ethereum.istanbul.vm.instructions.environmentethereum.muir_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:
42 | """ |
---|---|
43 | Pushes the address of the current executing account to the stack. |
44 |
|
45 | Parameters |
46 | ---------- |
47 | evm : |
48 | The current EVM frame. |
49 |
|
50 | """ |
51 | # STACK |
52 | pass |
53 | |
54 | # GAS |
55 | charge_gas(evm, GAS_BASE) |
56 | |
57 | # OPERATION |
58 | push(evm.stack, U256.from_be_bytes(evm.message.current_target)) |
59 | |
60 | # PROGRAM COUNTER |
61 | 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:
65 | """ |
---|---|
66 | Pushes the balance of the given account onto the stack. |
67 |
|
68 | Parameters |
69 | ---------- |
70 | evm : |
71 | The current EVM frame. |
72 |
|
73 | """ |
74 | # STACK |
75 | address = to_address(pop(evm.stack)) |
76 | |
77 | # GAS |
78 | charge_gas(evm, GAS_BALANCE) |
79 | |
80 | # OPERATION |
81 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
82 | balance = get_account(evm.message.block_env.state, address).balance |
83 | |
84 | push(evm.stack, balance) |
85 | |
86 | # PROGRAM COUNTER |
87 | 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:
91 | """ |
---|---|
92 | Pushes the address of the original transaction sender to the stack. |
93 | The origin address can only be an EOA. |
94 |
|
95 | Parameters |
96 | ---------- |
97 | evm : |
98 | The current EVM frame. |
99 |
|
100 | """ |
101 | # STACK |
102 | pass |
103 | |
104 | # GAS |
105 | charge_gas(evm, GAS_BASE) |
106 | |
107 | # OPERATION |
108 | push(evm.stack, U256.from_be_bytes(evm.message.tx_env.origin)) |
109 | |
110 | # PROGRAM COUNTER |
111 | 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:
115 | """ |
---|---|
116 | Pushes the address of the caller onto the stack. |
117 |
|
118 | Parameters |
119 | ---------- |
120 | evm : |
121 | The current EVM frame. |
122 |
|
123 | """ |
124 | # STACK |
125 | pass |
126 | |
127 | # GAS |
128 | charge_gas(evm, GAS_BASE) |
129 | |
130 | # OPERATION |
131 | push(evm.stack, U256.from_be_bytes(evm.message.caller)) |
132 | |
133 | # PROGRAM COUNTER |
134 | 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:
138 | """ |
---|---|
139 | Push the value (in wei) sent with the call onto the stack. |
140 |
|
141 | Parameters |
142 | ---------- |
143 | evm : |
144 | The current EVM frame. |
145 |
|
146 | """ |
147 | # STACK |
148 | pass |
149 | |
150 | # GAS |
151 | charge_gas(evm, GAS_BASE) |
152 | |
153 | # OPERATION |
154 | push(evm.stack, evm.message.value) |
155 | |
156 | # PROGRAM COUNTER |
157 | 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:
161 | """ |
---|---|
162 | Push a word (32 bytes) of the input data belonging to the current |
163 | environment onto the stack. |
164 |
|
165 | Parameters |
166 | ---------- |
167 | evm : |
168 | The current EVM frame. |
169 |
|
170 | """ |
171 | # STACK |
172 | start_index = pop(evm.stack) |
173 | |
174 | # GAS |
175 | charge_gas(evm, GAS_VERY_LOW) |
176 | |
177 | # OPERATION |
178 | value = buffer_read(evm.message.data, start_index, U256(32)) |
179 | |
180 | push(evm.stack, U256.from_be_bytes(value)) |
181 | |
182 | # PROGRAM COUNTER |
183 | 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:
187 | """ |
---|---|
188 | Push the size of input data in current environment onto the stack. |
189 |
|
190 | Parameters |
191 | ---------- |
192 | evm : |
193 | The current EVM frame. |
194 |
|
195 | """ |
196 | # STACK |
197 | pass |
198 | |
199 | # GAS |
200 | charge_gas(evm, GAS_BASE) |
201 | |
202 | # OPERATION |
203 | push(evm.stack, U256(len(evm.message.data))) |
204 | |
205 | # PROGRAM COUNTER |
206 | 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:
210 | """ |
---|---|
211 | Copy a portion of the input data in current environment to memory. |
212 |
|
213 | This will also expand the memory, in case that the memory is insufficient |
214 | to store the data. |
215 |
|
216 | Parameters |
217 | ---------- |
218 | evm : |
219 | The current EVM frame. |
220 |
|
221 | """ |
222 | # STACK |
223 | memory_start_index = pop(evm.stack) |
224 | data_start_index = pop(evm.stack) |
225 | size = pop(evm.stack) |
226 | |
227 | # GAS |
228 | words = ceil32(Uint(size)) // Uint(32) |
229 | copy_gas_cost = GAS_COPY * words |
230 | extend_memory = calculate_gas_extend_memory( |
231 | evm.memory, [(memory_start_index, size)] |
232 | ) |
233 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
234 | |
235 | # OPERATION |
236 | evm.memory += b"\x00" * extend_memory.expand_by |
237 | value = buffer_read(evm.message.data, data_start_index, size) |
238 | memory_write(evm.memory, memory_start_index, value) |
239 | |
240 | # PROGRAM COUNTER |
241 | 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:
245 | """ |
---|---|
246 | Push the size of code running in current environment onto the stack. |
247 |
|
248 | Parameters |
249 | ---------- |
250 | evm : |
251 | The current EVM frame. |
252 |
|
253 | """ |
254 | # STACK |
255 | pass |
256 | |
257 | # GAS |
258 | charge_gas(evm, GAS_BASE) |
259 | |
260 | # OPERATION |
261 | push(evm.stack, U256(len(evm.code))) |
262 | |
263 | # PROGRAM COUNTER |
264 | 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:
268 | """ |
---|---|
269 | Copy a portion of the code in current environment to memory. |
270 |
|
271 | This will also expand the memory, in case that the memory is insufficient |
272 | to store the data. |
273 |
|
274 | Parameters |
275 | ---------- |
276 | evm : |
277 | The current EVM frame. |
278 |
|
279 | """ |
280 | # STACK |
281 | memory_start_index = pop(evm.stack) |
282 | code_start_index = pop(evm.stack) |
283 | size = pop(evm.stack) |
284 | |
285 | # GAS |
286 | words = ceil32(Uint(size)) // Uint(32) |
287 | copy_gas_cost = GAS_COPY * words |
288 | extend_memory = calculate_gas_extend_memory( |
289 | evm.memory, [(memory_start_index, size)] |
290 | ) |
291 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
292 | |
293 | # OPERATION |
294 | evm.memory += b"\x00" * extend_memory.expand_by |
295 | value = buffer_read(evm.code, code_start_index, size) |
296 | memory_write(evm.memory, memory_start_index, value) |
297 | |
298 | # PROGRAM COUNTER |
299 | 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:
303 | """ |
---|---|
304 | Push the gas price used in current environment onto the stack. |
305 |
|
306 | Parameters |
307 | ---------- |
308 | evm : |
309 | The current EVM frame. |
310 |
|
311 | """ |
312 | # STACK |
313 | pass |
314 | |
315 | # GAS |
316 | charge_gas(evm, GAS_BASE) |
317 | |
318 | # OPERATION |
319 | push(evm.stack, U256(evm.message.tx_env.gas_price)) |
320 | |
321 | # PROGRAM COUNTER |
322 | 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:
326 | """ |
---|---|
327 | Push the code size of a given account onto the stack. |
328 |
|
329 | Parameters |
330 | ---------- |
331 | evm : |
332 | The current EVM frame. |
333 |
|
334 | """ |
335 | # STACK |
336 | address = to_address(pop(evm.stack)) |
337 | |
338 | # GAS |
339 | charge_gas(evm, GAS_EXTERNAL) |
340 | |
341 | # OPERATION |
342 | code = get_account(evm.message.block_env.state, address).code |
343 | |
344 | codesize = U256(len(code)) |
345 | push(evm.stack, codesize) |
346 | |
347 | # PROGRAM COUNTER |
348 | 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:
352 | """ |
---|---|
353 | Copy a portion of an account's code to memory. |
354 |
|
355 | Parameters |
356 | ---------- |
357 | evm : |
358 | The current EVM frame. |
359 |
|
360 | """ |
361 | # STACK |
362 | address = to_address(pop(evm.stack)) |
363 | memory_start_index = pop(evm.stack) |
364 | code_start_index = pop(evm.stack) |
365 | size = pop(evm.stack) |
366 | |
367 | # GAS |
368 | words = ceil32(Uint(size)) // Uint(32) |
369 | copy_gas_cost = GAS_COPY * words |
370 | extend_memory = calculate_gas_extend_memory( |
371 | evm.memory, [(memory_start_index, size)] |
372 | ) |
373 | charge_gas(evm, GAS_EXTERNAL + copy_gas_cost + extend_memory.cost) |
374 | |
375 | # OPERATION |
376 | evm.memory += b"\x00" * extend_memory.expand_by |
377 | code = get_account(evm.message.block_env.state, address).code |
378 | |
379 | value = buffer_read(code, code_start_index, size) |
380 | memory_write(evm.memory, memory_start_index, value) |
381 | |
382 | # PROGRAM COUNTER |
383 | 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:
387 | """ |
---|---|
388 | Pushes the size of the return data buffer onto the stack. |
389 |
|
390 | Parameters |
391 | ---------- |
392 | evm : |
393 | The current EVM frame. |
394 | """ |
395 | # STACK |
396 | pass |
397 | |
398 | # GAS |
399 | charge_gas(evm, GAS_BASE) |
400 | |
401 | # OPERATION |
402 | push(evm.stack, U256(len(evm.return_data))) |
403 | |
404 | # PROGRAM COUNTER |
405 | 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:
409 | """ |
---|---|
410 | Copies data from the return data buffer code to memory |
411 |
|
412 | Parameters |
413 | ---------- |
414 | evm : |
415 | The current EVM frame. |
416 | """ |
417 | # STACK |
418 | memory_start_index = pop(evm.stack) |
419 | return_data_start_position = pop(evm.stack) |
420 | size = pop(evm.stack) |
421 | |
422 | # GAS |
423 | words = ceil32(Uint(size)) // Uint(32) |
424 | copy_gas_cost = GAS_RETURN_DATA_COPY * words |
425 | extend_memory = calculate_gas_extend_memory( |
426 | evm.memory, [(memory_start_index, size)] |
427 | ) |
428 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
429 | if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): |
430 | raise OutOfBoundsRead |
431 | |
432 | evm.memory += b"\x00" * extend_memory.expand_by |
433 | value = evm.return_data[ |
434 | return_data_start_position : return_data_start_position + size |
435 | ] |
436 | memory_write(evm.memory, memory_start_index, value) |
437 | |
438 | # PROGRAM COUNTER |
439 | 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:
443 | """ |
---|---|
444 | Returns the keccak256 hash of a contract’s bytecode |
445 | Parameters |
446 | ---------- |
447 | evm : |
448 | The current EVM frame. |
449 | """ |
450 | # STACK |
451 | address = to_address(pop(evm.stack)) |
452 | |
453 | # GAS |
454 | charge_gas(evm, GAS_CODE_HASH) |
455 | |
456 | # OPERATION |
457 | account = get_account(evm.message.block_env.state, address) |
458 | |
459 | if account == EMPTY_ACCOUNT: |
460 | codehash = U256(0) |
461 | else: |
462 | code = account.code |
463 | codehash = U256.from_be_bytes(keccak256(code)) |
464 | |
465 | push(evm.stack, codehash) |
466 | |
467 | # PROGRAM COUNTER |
468 | 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:
472 | """ |
---|---|
473 | Pushes the balance of the current address to the stack. |
474 |
|
475 | Parameters |
476 | ---------- |
477 | evm : |
478 | The current EVM frame. |
479 |
|
480 | """ |
481 | # STACK |
482 | pass |
483 | |
484 | # GAS |
485 | charge_gas(evm, GAS_FAST_STEP) |
486 | |
487 | # OPERATION |
488 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
489 | balance = get_account( |
490 | evm.message.block_env.state, evm.message.current_target |
491 | ).balance |
492 | |
493 | push(evm.stack, balance) |
494 | |
495 | # PROGRAM COUNTER |
496 | evm.pc += Uint(1) |