ethereum.forks.amsterdam.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:
40
    """
41
    Loads to the stack, the value corresponding to a certain key from the
42
    storage of the current account.
43
44
    Parameters
45
    ----------
46
    evm :
47
        The current EVM frame.
48
49
    """
50
    # STACK
51
    key = pop(evm.stack).to_be_bytes32()
52
53
    # GAS
54
    if (evm.message.current_target, key) in evm.accessed_storage_keys:
55
        charge_gas(evm, GAS_WARM_ACCESS)
56
    else:
57
        evm.accessed_storage_keys.add((evm.message.current_target, key))
58
        charge_gas(evm, GAS_COLD_SLOAD)
59
60
    # OPERATION
61
    tx_state = evm.message.tx_env.state
62
    value = get_storage(tx_state, evm.message.current_target, key)
63
    track_storage_read(tx_state, evm.message.current_target, key)
64
65
    push(evm.stack, value)
66
67
    # PROGRAM COUNTER
68
    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:
72
    """
73
    Stores a value at a certain key in the current context's storage.
74
75
    Parameters
76
    ----------
77
    evm :
78
        The current EVM frame.
79
80
    """
81
    if evm.message.is_static:
82
        raise WriteInStaticContext
83
84
    # STACK
85
    key = pop(evm.stack).to_be_bytes32()
86
    new_value = pop(evm.stack)
87
88
    # check we have at least the stipend gas
89
    check_gas(evm, GAS_CALL_STIPEND + Uint(1))
90
91
    tx_state = evm.message.tx_env.state
92
    original_value = get_storage_original(
93
        tx_state, evm.message.current_target, key
94
    )
95
    current_value = get_storage(tx_state, evm.message.current_target, key)
96
97
    gas_cost = Uint(0)
98
99
    if (evm.message.current_target, key) not in evm.accessed_storage_keys:
100
        evm.accessed_storage_keys.add((evm.message.current_target, key))
101
        gas_cost += GAS_COLD_SLOAD
102
103
    track_storage_read(tx_state, evm.message.current_target, key)
104
105
    if original_value == current_value and current_value != new_value:
106
        if original_value == 0:
107
            gas_cost += GAS_STORAGE_SET
108
        else:
109
            gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD
110
    else:
111
        gas_cost += GAS_WARM_ACCESS
112
113
    # Refund Counter Calculation
114
    if current_value != new_value:
115
        if original_value != 0 and current_value != 0 and new_value == 0:
116
            # Storage is cleared for the first time in the transaction
117
            evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND)
118
119
        if original_value != 0 and current_value == 0:
120
            # Gas refund issued earlier to be reversed
121
            evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND)
122
123
        if original_value == new_value:
124
            # Storage slot being restored to its original value
125
            if original_value == 0:
126
                # Slot was originally empty and was SET earlier
127
                evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS)
128
            else:
129
                # Slot was originally non-empty and was UPDATED earlier
130
                evm.refund_counter += int(
131
                    GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS
132
                )
133
134
    charge_gas(evm, gas_cost)
135
    set_storage(tx_state, evm.message.current_target, key, new_value)
136
137
    # PROGRAM COUNTER
138
    evm.pc += Uint(1)

tload

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

Parameters

evm : The current EVM frame.

def tload(evm: Evm) -> None:
142
    """
143
    Loads to the stack, the value corresponding to a certain key from the
144
    transient storage of the current account.
145
146
    Parameters
147
    ----------
148
    evm :
149
        The current EVM frame.
150
151
    """
152
    # STACK
153
    key = pop(evm.stack).to_be_bytes32()
154
155
    # GAS
156
    charge_gas(evm, GAS_WARM_ACCESS)
157
158
    # OPERATION
159
    value = get_transient_storage(
160
        evm.message.tx_env.state, evm.message.current_target, key
161
    )
162
    push(evm.stack, value)
163
164
    # PROGRAM COUNTER
165
    evm.pc += Uint(1)

tstore

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

Parameters

evm : The current EVM frame.

def tstore(evm: Evm) -> None:
169
    """
170
    Stores a value at a certain key in the current context's transient storage.
171
172
    Parameters
173
    ----------
174
    evm :
175
        The current EVM frame.
176
177
    """
178
    if evm.message.is_static:
179
        raise WriteInStaticContext
180
181
    # STACK
182
    key = pop(evm.stack).to_be_bytes32()
183
    new_value = pop(evm.stack)
184
185
    # GAS
186
    charge_gas(evm, GAS_WARM_ACCESS)
187
    set_transient_storage(
188
        evm.message.tx_env.state,
189
        evm.message.current_target,
190
        key,
191
        new_value,
192
    )
193
194
    # PROGRAM COUNTER
195
    evm.pc += Uint(1)