ethereum.arrow_glacier.vm.instructions.environmentethereum.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:
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
    if address in evm.accessed_addresses:
78
        charge_gas(evm, GAS_WARM_ACCESS)
79
    else:
80
        evm.accessed_addresses.add(address)
81
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
82
83
    # OPERATION
84
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
85
    balance = get_account(evm.env.state, address).balance
86
87
    push(evm.stack, balance)
88
89
    # PROGRAM COUNTER
90
    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:
94
    """
95
    Pushes the address of the original transaction sender to the stack.
96
    The origin address can only be an EOA.
97
98
    Parameters
99
    ----------
100
    evm :
101
        The current EVM frame.
102
103
    """
104
    # STACK
105
    pass
106
107
    # GAS
108
    charge_gas(evm, GAS_BASE)
109
110
    # OPERATION
111
    push(evm.stack, U256.from_be_bytes(evm.env.origin))
112
113
    # PROGRAM COUNTER
114
    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:
118
    """
119
    Pushes the address of the caller onto the stack.
120
121
    Parameters
122
    ----------
123
    evm :
124
        The current EVM frame.
125
126
    """
127
    # STACK
128
    pass
129
130
    # GAS
131
    charge_gas(evm, GAS_BASE)
132
133
    # OPERATION
134
    push(evm.stack, U256.from_be_bytes(evm.message.caller))
135
136
    # PROGRAM COUNTER
137
    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:
141
    """
142
    Push the value (in wei) sent with the call onto the stack.
143
144
    Parameters
145
    ----------
146
    evm :
147
        The current EVM frame.
148
149
    """
150
    # STACK
151
    pass
152
153
    # GAS
154
    charge_gas(evm, GAS_BASE)
155
156
    # OPERATION
157
    push(evm.stack, evm.message.value)
158
159
    # PROGRAM COUNTER
160
    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:
164
    """
165
    Push a word (32 bytes) of the input data belonging to the current
166
    environment onto the stack.
167
168
    Parameters
169
    ----------
170
    evm :
171
        The current EVM frame.
172
173
    """
174
    # STACK
175
    start_index = pop(evm.stack)
176
177
    # GAS
178
    charge_gas(evm, GAS_VERY_LOW)
179
180
    # OPERATION
181
    value = buffer_read(evm.message.data, start_index, U256(32))
182
183
    push(evm.stack, U256.from_be_bytes(value))
184
185
    # PROGRAM COUNTER
186
    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:
190
    """
191
    Push the size of input data in current environment onto the stack.
192
193
    Parameters
194
    ----------
195
    evm :
196
        The current EVM frame.
197
198
    """
199
    # STACK
200
    pass
201
202
    # GAS
203
    charge_gas(evm, GAS_BASE)
204
205
    # OPERATION
206
    push(evm.stack, U256(len(evm.message.data)))
207
208
    # PROGRAM COUNTER
209
    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:
213
    """
214
    Copy a portion of the input data in current environment to memory.
215
216
    This will also expand the memory, in case that the memory is insufficient
217
    to store the data.
218
219
    Parameters
220
    ----------
221
    evm :
222
        The current EVM frame.
223
224
    """
225
    # STACK
226
    memory_start_index = pop(evm.stack)
227
    data_start_index = pop(evm.stack)
228
    size = pop(evm.stack)
229
230
    # GAS
231
    words = ceil32(Uint(size)) // Uint(32)
232
    copy_gas_cost = GAS_COPY * words
233
    extend_memory = calculate_gas_extend_memory(
234
        evm.memory, [(memory_start_index, size)]
235
    )
236
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
237
238
    # OPERATION
239
    evm.memory += b"\x00" * extend_memory.expand_by
240
    value = buffer_read(evm.message.data, data_start_index, size)
241
    memory_write(evm.memory, memory_start_index, value)
242
243
    # PROGRAM COUNTER
244
    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:
248
    """
249
    Push the size of code running in current environment onto the stack.
250
251
    Parameters
252
    ----------
253
    evm :
254
        The current EVM frame.
255
256
    """
257
    # STACK
258
    pass
259
260
    # GAS
261
    charge_gas(evm, GAS_BASE)
262
263
    # OPERATION
264
    push(evm.stack, U256(len(evm.code)))
265
266
    # PROGRAM COUNTER
267
    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:
271
    """
272
    Copy a portion of the code in current environment to memory.
273
274
    This will also expand the memory, in case that the memory is insufficient
275
    to store the data.
276
277
    Parameters
278
    ----------
279
    evm :
280
        The current EVM frame.
281
282
    """
283
    # STACK
284
    memory_start_index = pop(evm.stack)
285
    code_start_index = pop(evm.stack)
286
    size = pop(evm.stack)
287
288
    # GAS
289
    words = ceil32(Uint(size)) // Uint(32)
290
    copy_gas_cost = GAS_COPY * words
291
    extend_memory = calculate_gas_extend_memory(
292
        evm.memory, [(memory_start_index, size)]
293
    )
294
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
295
296
    # OPERATION
297
    evm.memory += b"\x00" * extend_memory.expand_by
298
    value = buffer_read(evm.code, code_start_index, size)
299
    memory_write(evm.memory, memory_start_index, value)
300
301
    # PROGRAM COUNTER
302
    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:
306
    """
307
    Push the gas price used in current environment onto the stack.
308
309
    Parameters
310
    ----------
311
    evm :
312
        The current EVM frame.
313
314
    """
315
    # STACK
316
    pass
317
318
    # GAS
319
    charge_gas(evm, GAS_BASE)
320
321
    # OPERATION
322
    push(evm.stack, U256(evm.env.gas_price))
323
324
    # PROGRAM COUNTER
325
    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:
329
    """
330
    Push the code size of a given account onto the stack.
331
332
    Parameters
333
    ----------
334
    evm :
335
        The current EVM frame.
336
337
    """
338
    # STACK
339
    address = to_address(pop(evm.stack))
340
341
    # GAS
342
    if address in evm.accessed_addresses:
343
        charge_gas(evm, GAS_WARM_ACCESS)
344
    else:
345
        evm.accessed_addresses.add(address)
346
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
347
348
    # OPERATION
349
    # Non-existent accounts default to EMPTY_ACCOUNT, which has empty code.
350
    codesize = U256(len(get_account(evm.env.state, address).code))
351
352
    push(evm.stack, codesize)
353
354
    # PROGRAM COUNTER
355
    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:
359
    """
360
    Copy a portion of an account's code to memory.
361
362
    Parameters
363
    ----------
364
    evm :
365
        The current EVM frame.
366
367
    """
368
    # STACK
369
    address = to_address(pop(evm.stack))
370
    memory_start_index = pop(evm.stack)
371
    code_start_index = pop(evm.stack)
372
    size = pop(evm.stack)
373
374
    # GAS
375
    words = ceil32(Uint(size)) // Uint(32)
376
    copy_gas_cost = GAS_COPY * words
377
    extend_memory = calculate_gas_extend_memory(
378
        evm.memory, [(memory_start_index, size)]
379
    )
380
381
    if address in evm.accessed_addresses:
382
        charge_gas(evm, GAS_WARM_ACCESS + copy_gas_cost + extend_memory.cost)
383
    else:
384
        evm.accessed_addresses.add(address)
385
        charge_gas(
386
            evm, GAS_COLD_ACCOUNT_ACCESS + copy_gas_cost + extend_memory.cost
387
        )
388
389
    # OPERATION
390
    evm.memory += b"\x00" * extend_memory.expand_by
391
    code = get_account(evm.env.state, address).code
392
    value = buffer_read(code, code_start_index, size)
393
    memory_write(evm.memory, memory_start_index, value)
394
395
    # PROGRAM COUNTER
396
    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:
400
    """
401
    Pushes the size of the return data buffer onto the stack.
402
403
    Parameters
404
    ----------
405
    evm :
406
        The current EVM frame.
407
    """
408
    # STACK
409
    pass
410
411
    # GAS
412
    charge_gas(evm, GAS_BASE)
413
414
    # OPERATION
415
    push(evm.stack, U256(len(evm.return_data)))
416
417
    # PROGRAM COUNTER
418
    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:
422
    """
423
    Copies data from the return data buffer code to memory
424
425
    Parameters
426
    ----------
427
    evm :
428
        The current EVM frame.
429
    """
430
    # STACK
431
    memory_start_index = pop(evm.stack)
432
    return_data_start_position = pop(evm.stack)
433
    size = pop(evm.stack)
434
435
    # GAS
436
    words = ceil32(Uint(size)) // Uint(32)
437
    copy_gas_cost = GAS_RETURN_DATA_COPY * words
438
    extend_memory = calculate_gas_extend_memory(
439
        evm.memory, [(memory_start_index, size)]
440
    )
441
    charge_gas(evm, GAS_VERY_LOW + copy_gas_cost + extend_memory.cost)
442
    if Uint(return_data_start_position) + Uint(size) > ulen(evm.return_data):
443
        raise OutOfBoundsRead
444
445
    evm.memory += b"\x00" * extend_memory.expand_by
446
    value = evm.return_data[
447
        return_data_start_position : return_data_start_position + size
448
    ]
449
    memory_write(evm.memory, memory_start_index, value)
450
451
    # PROGRAM COUNTER
452
    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:
456
    """
457
    Returns the keccak256 hash of a contract’s bytecode
458
    Parameters
459
    ----------
460
    evm :
461
        The current EVM frame.
462
    """
463
    # STACK
464
    address = to_address(pop(evm.stack))
465
466
    # GAS
467
    if address in evm.accessed_addresses:
468
        charge_gas(evm, GAS_WARM_ACCESS)
469
    else:
470
        evm.accessed_addresses.add(address)
471
        charge_gas(evm, GAS_COLD_ACCOUNT_ACCESS)
472
473
    # OPERATION
474
    account = get_account(evm.env.state, address)
475
476
    if account == EMPTY_ACCOUNT:
477
        codehash = U256(0)
478
    else:
479
        codehash = U256.from_be_bytes(keccak256(account.code))
480
481
    push(evm.stack, codehash)
482
483
    # PROGRAM COUNTER
484
    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:
488
    """
489
    Pushes the balance of the current address to the stack.
490
491
    Parameters
492
    ----------
493
    evm :
494
        The current EVM frame.
495
496
    """
497
    # STACK
498
    pass
499
500
    # GAS
501
    charge_gas(evm, GAS_FAST_STEP)
502
503
    # OPERATION
504
    # Non-existent accounts default to EMPTY_ACCOUNT, which has balance 0.
505
    balance = get_account(evm.env.state, evm.message.current_target).balance
506
507
    push(evm.stack, balance)
508
509
    # PROGRAM COUNTER
510
    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:
514
    """
515
    Pushes the base fee of the current block on to the stack.
516
517
    Parameters
518
    ----------
519
    evm :
520
        The current EVM frame.
521
522
    """
523
    # STACK
524
    pass
525
526
    # GAS
527
    charge_gas(evm, GAS_BASE)
528
529
    # OPERATION
530
    push(evm.stack, U256(evm.env.base_fee_per_gas))
531
532
    # PROGRAM COUNTER
533
    evm.pc += Uint(1)