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:
34
    """
35
    Loads to the stack, the value corresponding to a certain key from the
36
    storage of the current account.
37
38
    Parameters
39
    ----------
40
    evm :
41
        The current EVM frame.
42
43
    """
44
    # STACK
45
    key = pop(evm.stack).to_be_bytes32()
46
47
    # GAS
48
    if (evm.message.current_target, key) in evm.accessed_storage_keys:
49
        charge_gas(evm, GasCosts.WARM_ACCESS)
50
    else:
51
        evm.accessed_storage_keys.add((evm.message.current_target, key))
52
        charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS)
53
54
    # OPERATION
55
    tx_state = evm.message.tx_env.state
56
    value = get_storage(tx_state, evm.message.current_target, key)
57
58
    push(evm.stack, value)
59
60
    # PROGRAM COUNTER
61
    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:
65
    """
66
    Stores a value at a certain key in the current context's storage.
67
68
    Parameters
69
    ----------
70
    evm :
71
        The current EVM frame.
72
73
    """
74
    if evm.message.is_static:
75
        raise WriteInStaticContext
76
77
    # STACK
78
    key = pop(evm.stack).to_be_bytes32()
79
    new_value = pop(evm.stack)
80
81
    # check we have at least the stipend gas
82
    check_gas(evm, GasCosts.CALL_STIPEND + Uint(1))
83
84
    tx_state = evm.message.tx_env.state
85
    original_value = get_storage_original(
86
        tx_state, evm.message.current_target, key
87
    )
88
    current_value = get_storage(tx_state, evm.message.current_target, key)
89
90
    gas_cost = Uint(0)
91
92
    if (evm.message.current_target, key) not in evm.accessed_storage_keys:
93
        evm.accessed_storage_keys.add((evm.message.current_target, key))
94
        gas_cost += GasCosts.COLD_STORAGE_ACCESS
95
96
    if original_value == current_value and current_value != new_value:
97
        if original_value == 0:
98
            gas_cost += GasCosts.STORAGE_SET
99
        else:
100
            gas_cost += (
101
                GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS
102
            )
103
    else:
104
        gas_cost += GasCosts.WARM_ACCESS
105
106
    # Refund Counter Calculation
107
    if current_value != new_value:
108
        if original_value != 0 and current_value != 0 and new_value == 0:
109
            # Storage is cleared for the first time in the transaction
110
            evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR
111
112
        if original_value != 0 and current_value == 0:
113
            # Gas refund issued earlier to be reversed
114
            evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR
115
116
        if original_value == new_value:
117
            # Storage slot being restored to its original value
118
            if original_value == 0:
119
                # Slot was originally empty and was SET earlier
120
                evm.refund_counter += int(
121
                    GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS
122
                )
123
            else:
124
                # Slot was originally non-empty and was UPDATED earlier
125
                evm.refund_counter += int(
126
                    GasCosts.COLD_STORAGE_WRITE
127
                    - GasCosts.COLD_STORAGE_ACCESS
128
                    - GasCosts.WARM_ACCESS
129
                )
130
131
    charge_gas(evm, gas_cost)
132
    set_storage(tx_state, evm.message.current_target, key, new_value)
133
134
    # PROGRAM COUNTER
135
    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:
139
    """
140
    Loads to the stack, the value corresponding to a certain key from the
141
    transient storage of the current account.
142
143
    Parameters
144
    ----------
145
    evm :
146
        The current EVM frame.
147
148
    """
149
    # STACK
150
    key = pop(evm.stack).to_be_bytes32()
151
152
    # GAS
153
    charge_gas(evm, GasCosts.WARM_ACCESS)
154
155
    # OPERATION
156
    value = get_transient_storage(
157
        evm.message.tx_env.state, evm.message.current_target, key
158
    )
159
    push(evm.stack, value)
160
161
    # PROGRAM COUNTER
162
    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:
166
    """
167
    Stores a value at a certain key in the current context's transient storage.
168
169
    Parameters
170
    ----------
171
    evm :
172
        The current EVM frame.
173
174
    """
175
    if evm.message.is_static:
176
        raise WriteInStaticContext
177
178
    # STACK
179
    key = pop(evm.stack).to_be_bytes32()
180
    new_value = pop(evm.stack)
181
182
    # GAS
183
    charge_gas(evm, GasCosts.WARM_ACCESS)
184
    set_transient_storage(
185
        evm.message.tx_env.state,
186
        evm.message.current_target,
187
        key,
188
        new_value,
189
    )
190
191
    # PROGRAM COUNTER
192
    evm.pc += Uint(1)