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