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