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(evm.env.state, evm.message.current_target, key)
60
61
    push(evm.stack, value)
62
63
    # PROGRAM COUNTER
64
    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:
68
    """
69
    Stores a value at a certain key in the current context's storage.
70
71
    Parameters
72
    ----------
73
    evm :
74
        The current EVM frame.
75
76
    """
77
    # STACK
78
    key = pop(evm.stack).to_be_bytes32()
79
    new_value = pop(evm.stack)
80
    if evm.gas_left <= GAS_CALL_STIPEND:
81
        raise OutOfGasError
82
83
    original_value = get_storage_original(
84
        evm.env.state, evm.message.current_target, key
85
    )
86
    current_value = get_storage(evm.env.state, evm.message.current_target, key)
87
88
    gas_cost = Uint(0)
89
90
    if (evm.message.current_target, key) not in evm.accessed_storage_keys:
91
        evm.accessed_storage_keys.add((evm.message.current_target, key))
92
        gas_cost += GAS_COLD_SLOAD
93
94
    if original_value == current_value and current_value != new_value:
95
        if original_value == 0:
96
            gas_cost += GAS_STORAGE_SET
97
        else:
98
            gas_cost += GAS_STORAGE_UPDATE - GAS_COLD_SLOAD
99
    else:
100
        gas_cost += GAS_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 += int(GAS_STORAGE_CLEAR_REFUND)
107
108
        if original_value != 0 and current_value == 0:
109
            # Gas refund issued earlier to be reversed
110
            evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND)
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(GAS_STORAGE_SET - GAS_WARM_ACCESS)
117
            else:
118
                # Slot was originally non-empty and was UPDATED earlier
119
                evm.refund_counter += int(
120
                    GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS
121
                )
122
123
    charge_gas(evm, gas_cost)
124
    if evm.message.is_static:
125
        raise WriteInStaticContext
126
    set_storage(evm.env.state, evm.message.current_target, key, new_value)
127
128
    # PROGRAM COUNTER
129
    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:
133
    """
134
    Loads to the stack, the value corresponding to a certain key from the
135
    transient storage of the current account.
136
    Parameters
137
    ----------
138
    evm :
139
        The current EVM frame.
140
    """
141
    # STACK
142
    key = pop(evm.stack).to_be_bytes32()
143
144
    # GAS
145
    charge_gas(evm, GAS_WARM_ACCESS)
146
147
    # OPERATION
148
    value = get_transient_storage(
149
        evm.env.transient_storage, evm.message.current_target, key
150
    )
151
    push(evm.stack, value)
152
153
    # PROGRAM COUNTER
154
    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:
158
    """
159
    Stores a value at a certain key in the current context's transient storage.
160
    Parameters
161
    ----------
162
    evm :
163
        The current EVM frame.
164
    """
165
    # STACK
166
    key = pop(evm.stack).to_be_bytes32()
167
    new_value = pop(evm.stack)
168
169
    # GAS
170
    charge_gas(evm, GAS_WARM_ACCESS)
171
    if evm.message.is_static:
172
        raise WriteInStaticContext
173
    set_transient_storage(
174
        evm.env.transient_storage, evm.message.current_target, key, new_value
175
    )
176
177
    # PROGRAM COUNTER
178
    evm.pc += Uint(1)