ethereum.forks.bpo5.vm.instructions.storageethereum.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:
44
    """
45
    Loads to the stack, the value corresponding to a certain key from the
46
    storage of the current account.
47
48
    Parameters
49
    ----------
50
    evm :
51
        The current EVM frame.
52
53
    """
54
    # STACK
55
    key = pop(evm.stack).to_be_bytes32()
56
57
    # GAS
58
    if (evm.message.current_target, key) in evm.accessed_storage_keys:
59
        charge_gas(evm, GAS_WARM_ACCESS)
60
    else:
61
        evm.accessed_storage_keys.add((evm.message.current_target, key))
62
        charge_gas(evm, GAS_COLD_SLOAD)
63
64
    # OPERATION
65
    value = get_storage(
66
        evm.message.block_env.state, evm.message.current_target, key
67
    )
68
    track_storage_read(
69
        evm.state_changes,
70
        evm.message.current_target,
71
        key,
72
    )
73
74
    push(evm.stack, value)
75
76
    # PROGRAM COUNTER
77
    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:
81
    """
82
    Stores a value at a certain key in the current context's storage.
83
84
    Parameters
85
    ----------
86
    evm :
87
        The current EVM frame.
88
89
    """
90
    if evm.message.is_static:
91
        raise WriteInStaticContext
92
93
    # STACK
94
    key = pop(evm.stack).to_be_bytes32()
95
    new_value = pop(evm.stack)
82
    if evm.gas_left <= GAS_CALL_STIPEND:
83
        raise OutOfGasError
96
97
    # check we have at least the stipend gas
98
    check_gas(evm, GAS_CALL_STIPEND + Uint(1))
99
100
    state = evm.message.block_env.state
101
    original_value = get_storage_original(
102
        state, evm.message.current_target, key
103
    )
104
    current_value = get_storage(state, evm.message.current_target, key)
105
106
    gas_cost = Uint(0)
107
108
    if (evm.message.current_target, key) not in evm.accessed_storage_keys:
109
        evm.accessed_storage_keys.add((evm.message.current_target, key))
110
        gas_cost += GAS_COLD_SLOAD
111
112
    capture_pre_storage(
113
        evm.message.tx_env.state_changes,
114
        evm.message.current_target,
115
        key,
116
        current_value,
117
    )
118
    track_storage_read(
119
        evm.state_changes,
120
        evm.message.current_target,
121
        key,
122
    )
123
124
    if original_value == current_value and current_value != new_value:
125
        if original_value == 0:
126
            gas_cost += GAS_STORAGE_SET
127
        else:
128
            gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD
129
    else:
130
        gas_cost += GAS_WARM_ACCESS
131
132
    # Refund Counter Calculation
133
    if current_value != new_value:
134
        if original_value != 0 and current_value != 0 and new_value == 0:
135
            # Storage is cleared for the first time in the transaction
136
            evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND)
137
138
        if original_value != 0 and current_value == 0:
139
            # Gas refund issued earlier to be reversed
140
            evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND)
141
142
        if original_value == new_value:
143
            # Storage slot being restored to its original value
144
            if original_value == 0:
145
                # Slot was originally empty and was SET earlier
146
                evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS)
147
            else:
148
                # Slot was originally non-empty and was UPDATED earlier
149
                evm.refund_counter += int(
150
                    GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS
151
                )
152
153
    charge_gas(evm, gas_cost)
127
    if evm.message.is_static:
128
        raise WriteInStaticContext
154
    set_storage(state, evm.message.current_target, key, new_value)
155
    track_storage_write(
156
        evm.state_changes,
157
        evm.message.current_target,
158
        key,
159
        new_value,
160
    )
161
162
    # PROGRAM COUNTER
163
    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:
167
    """
168
    Loads to the stack, the value corresponding to a certain key from the
169
    transient storage of the current account.
170
171
    Parameters
172
    ----------
173
    evm :
174
        The current EVM frame.
175
176
    """
177
    # STACK
178
    key = pop(evm.stack).to_be_bytes32()
179
180
    # GAS
181
    charge_gas(evm, GAS_WARM_ACCESS)
182
183
    # OPERATION
184
    value = get_transient_storage(
185
        evm.message.tx_env.transient_storage, evm.message.current_target, key
186
    )
187
    push(evm.stack, value)
188
189
    # PROGRAM COUNTER
190
    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:
194
    """
195
    Stores a value at a certain key in the current context's transient storage.
196
197
    Parameters
198
    ----------
199
    evm :
200
        The current EVM frame.
201
202
    """
203
    if evm.message.is_static:
204
        raise WriteInStaticContext
205
206
    # STACK
207
    key = pop(evm.stack).to_be_bytes32()
208
    new_value = pop(evm.stack)
209
210
    # GAS
211
    charge_gas(evm, GAS_WARM_ACCESS)
178
    if evm.message.is_static:
179
        raise WriteInStaticContext
212
    set_transient_storage(
213
        evm.message.tx_env.transient_storage,
214
        evm.message.current_target,
215
        key,
216
        new_value,
217
    )
218
219
    # PROGRAM COUNTER
220
    evm.pc += Uint(1)