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