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