ethereum.forks.bpo3.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
    tx_state = evm.message.tx_env.state
52
    value = get_storage(tx_state, evm.message.current_target, key)
53
54
    push(evm.stack, value)
55
56
    # PROGRAM COUNTER
57
    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:
61
    """
62
    Stores a value at a certain key in the current context's storage.
63
64
    Parameters
65
    ----------
66
    evm :
67
        The current EVM frame.
68
69
    """
70
    # STACK
71
    key = pop(evm.stack).to_be_bytes32()
72
    new_value = pop(evm.stack)
73
    if evm.gas_left <= GasCosts.CALL_STIPEND:
74
        raise OutOfGasError
75
76
    tx_state = evm.message.tx_env.state
77
    original_value = get_storage_original(
78
        tx_state, evm.message.current_target, key
79
    )
80
    current_value = get_storage(tx_state, evm.message.current_target, key)
81
82
    gas_cost = Uint(0)
83
84
    if (evm.message.current_target, key) not in evm.accessed_storage_keys:
85
        evm.accessed_storage_keys.add((evm.message.current_target, key))
86
        gas_cost += GasCosts.COLD_STORAGE_ACCESS
87
88
    if original_value == current_value and current_value != new_value:
89
        if original_value == 0:
90
            gas_cost += GasCosts.STORAGE_SET
91
        else:
92
            gas_cost += (
93
                GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS
94
            )
95
    else:
96
        gas_cost += GasCosts.WARM_ACCESS
97
98
    # Refund Counter Calculation
99
    if current_value != new_value:
100
        if original_value != 0 and current_value != 0 and new_value == 0:
101
            # Storage is cleared for the first time in the transaction
102
            evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR
103
104
        if original_value != 0 and current_value == 0:
105
            # Gas refund issued earlier to be reversed
106
            evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR
107
108
        if original_value == new_value:
109
            # Storage slot being restored to its original value
110
            if original_value == 0:
111
                # Slot was originally empty and was SET earlier
112
                evm.refund_counter += int(
113
                    GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS
114
                )
115
            else:
116
                # Slot was originally non-empty and was UPDATED earlier
117
                evm.refund_counter += int(
118
                    GasCosts.COLD_STORAGE_WRITE
119
                    - GasCosts.COLD_STORAGE_ACCESS
120
                    - GasCosts.WARM_ACCESS
121
                )
122
123
    charge_gas(evm, gas_cost)
124
    if evm.message.is_static:
125
        raise WriteInStaticContext
126
    set_storage(tx_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
137
    Parameters
138
    ----------
139
    evm :
140
        The current EVM frame.
141
142
    """
143
    # STACK
144
    key = pop(evm.stack).to_be_bytes32()
145
146
    # GAS
147
    charge_gas(evm, GasCosts.WARM_ACCESS)
148
149
    # OPERATION
150
    value = get_transient_storage(
151
        evm.message.tx_env.state, evm.message.current_target, key
152
    )
153
    push(evm.stack, value)
154
155
    # PROGRAM COUNTER
156
    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:
160
    """
161
    Stores a value at a certain key in the current context's transient storage.
162
163
    Parameters
164
    ----------
165
    evm :
166
        The current EVM frame.
167
168
    """
169
    # STACK
170
    key = pop(evm.stack).to_be_bytes32()
171
    new_value = pop(evm.stack)
172
173
    # GAS
174
    charge_gas(evm, GasCosts.WARM_ACCESS)
175
    if evm.message.is_static:
176
        raise WriteInStaticContext
177
    set_transient_storage(
178
        evm.message.tx_env.state,
179
        evm.message.current_target,
180
        key,
181
        new_value,
182
    )
183
184
    # PROGRAM COUNTER
185
    evm.pc += Uint(1)