ethereum.forks.paris.vm.instructions.storageethereum.forks.shanghai.vm.instructions.storage

Ethereum Virtual Machine (EVM) Storage Instructions.

.. contents:: Table of Contents :backlinks: none :local:

Introduction

Implementations of the EVM storage related instructions.

sload

Loads to the stack, the value corresponding to a certain key from the storage of the current account.

Parameters

evm : The current EVM frame.

def sload(evm: Evm) -> None:
24
    """
25
    Loads to the stack, the value corresponding to a certain key from the
26
    storage of the current account.
27
28
    Parameters
29
    ----------
30
    evm :
31
        The current EVM frame.
32
33
    """
34
    # STACK
35
    key = pop(evm.stack).to_be_bytes32()
36
37
    # GAS
38
    if (evm.message.current_target, key) in evm.accessed_storage_keys:
39
        charge_gas(evm, GasCosts.WARM_ACCESS)
40
    else:
41
        evm.accessed_storage_keys.add((evm.message.current_target, key))
42
        charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS)
43
44
    # OPERATION
45
    value = get_storage(
46
        evm.message.block_env.state, evm.message.current_target, key
47
    )
48
49
    push(evm.stack, value)
50
51
    # PROGRAM COUNTER
52
    evm.pc += Uint(1)

sstore

Stores a value at a certain key in the current context's storage.

Parameters

evm : The current EVM frame.

def sstore(evm: Evm) -> None:
56
    """
57
    Stores a value at a certain key in the current context's storage.
58
59
    Parameters
60
    ----------
61
    evm :
62
        The current EVM frame.
63
64
    """
65
    # STACK
66
    key = pop(evm.stack).to_be_bytes32()
67
    new_value = pop(evm.stack)
68
    if evm.gas_left <= GasCosts.CALL_STIPEND:
69
        raise OutOfGasError
70
71
    state = evm.message.block_env.state
72
    original_value = get_storage_original(
73
        state, evm.message.current_target, key
74
    )
75
    current_value = get_storage(state, evm.message.current_target, key)
76
77
    gas_cost = Uint(0)
78
79
    if (evm.message.current_target, key) not in evm.accessed_storage_keys:
80
        evm.accessed_storage_keys.add((evm.message.current_target, key))
81
        gas_cost += GasCosts.COLD_STORAGE_ACCESS
82
83
    if original_value == current_value and current_value != new_value:
84
        if original_value == 0:
85
            gas_cost += GasCosts.STORAGE_SET
86
        else:
87
            gas_cost += (
88
                GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS
89
            )
90
    else:
91
        gas_cost += GasCosts.WARM_ACCESS
92
93
    # Refund Counter Calculation
94
    if current_value != new_value:
95
        if original_value != 0 and current_value != 0 and new_value == 0:
96
            # Storage is cleared for the first time in the transaction
97
            evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR
98
99
        if original_value != 0 and current_value == 0:
100
            # Gas refund issued earlier to be reversed
101
            evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR
102
103
        if original_value == new_value:
104
            # Storage slot being restored to its original value
105
            if original_value == 0:
106
                # Slot was originally empty and was SET earlier
107
                evm.refund_counter += int(
108
                    GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS
109
                )
110
            else:
111
                # Slot was originally non-empty and was UPDATED earlier
112
                evm.refund_counter += int(
113
                    GasCosts.COLD_STORAGE_WRITE
114
                    - GasCosts.COLD_STORAGE_ACCESS
115
                    - GasCosts.WARM_ACCESS
116
                )
117
118
    charge_gas(evm, gas_cost)
119
    if evm.message.is_static:
120
        raise WriteInStaticContext
121
    set_storage(state, evm.message.current_target, key, new_value)
122
123
    # PROGRAM COUNTER
124
    evm.pc += Uint(1)