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