ethereum.istanbul.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.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.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.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 | # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code. |
343 | codesize = U256(len(get_account(evm.env.state, address).code)) |
344 | |
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.env.state, address).code |
378 | value = buffer_read(code, code_start_index, size) |
379 | memory_write(evm.memory, memory_start_index, value) |
380 | |
381 | # PROGRAM COUNTER |
382 | 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:
386 | """ |
---|---|
387 | Pushes the size of the return data buffer onto the stack. |
388 |
|
389 | Parameters |
390 | ---------- |
391 | evm : |
392 | The current EVM frame. |
393 | """ |
394 | # STACK |
395 | pass |
396 | |
397 | # GAS |
398 | charge_gas(evm, GAS_BASE) |
399 | |
400 | # OPERATION |
401 | push(evm.stack, U256(len(evm.return_data))) |
402 | |
403 | # PROGRAM COUNTER |
404 | 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:
408 | """ |
---|---|
409 | Copies data from the return data buffer code to memory |
410 |
|
411 | Parameters |
412 | ---------- |
413 | evm : |
414 | The current EVM frame. |
415 | """ |
416 | # STACK |
417 | memory_start_index = pop(evm.stack) |
418 | return_data_start_position = pop(evm.stack) |
419 | size = pop(evm.stack) |
420 | |
421 | # GAS |
422 | words = ceil32(Uint(size)) // Uint(32) |
423 | copy_gas_cost = GAS_RETURN_DATA_COPY * words |
424 | extend_memory = calculate_gas_extend_memory( |
425 | evm.memory, [(memory_start_index, size)] |
426 | ) |
427 | charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost) |
428 | if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data): |
429 | raise OutOfBoundsRead |
430 | |
431 | evm.memory += b"\x00" * extend_memory.expand_by |
432 | value = evm.return_data[ |
433 | return_data_start_position : return_data_start_position + size |
434 | ] |
435 | memory_write(evm.memory, memory_start_index, value) |
436 | |
437 | # PROGRAM COUNTER |
438 | 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:
442 | """ |
---|---|
443 | Returns the keccak256 hash of a contract’s bytecode |
444 | Parameters |
445 | ---------- |
446 | evm : |
447 | The current EVM frame. |
448 | """ |
449 | # STACK |
450 | address = to_address(pop(evm.stack)) |
451 | |
452 | # GAS |
453 | charge_gas(evm, GAS_CODE_HASH) |
454 | |
455 | # OPERATION |
456 | account = get_account(evm.env.state, address) |
457 | |
458 | if account == EMPTY_ACCOUNT: |
459 | codehash = U256(0) |
460 | else: |
461 | codehash = U256.from_be_bytes(keccak256(account.code)) |
462 | |
463 | push(evm.stack, codehash) |
464 | |
465 | # PROGRAM COUNTER |
466 | 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:
470 | """ |
---|---|
471 | Pushes the balance of the current address to the stack. |
472 |
|
473 | Parameters |
474 | ---------- |
475 | evm : |
476 | The current EVM frame. |
477 |
|
478 | """ |
479 | # STACK |
480 | pass |
481 | |
482 | # GAS |
483 | charge_gas(evm, GAS_FAST_STEP) |
484 | |
485 | # OPERATION |
486 | # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0. |
487 | balance = get_account(evm.env.state, evm.message.current_target).balance |
488 | |
489 | push(evm.stack, balance) |
490 | |
491 | # PROGRAM COUNTER |
492 | evm.pc += Uint(1) |