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