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:
36
    <snip>
46
    # STACK
47
    key = pop(evm.stack).to_be_bytes32()
48
49
    # GAS
50
    if (evm.message.current_target, key) in evm.accessed_storage_keys:
51
        charge_gas(evm, GasCosts.WARM_ACCESS)
52
    else:
53
        evm.accessed_storage_keys.add((evm.message.current_target, key))
54
        charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS)
55
56
    # OPERATION
57
    tx_state = evm.message.tx_env.state
58
    value = get_storage(tx_state, evm.message.current_target, key)
59
60
    push(evm.stack, value)
61
62
    # PROGRAM COUNTER
63
    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:
67
    <snip>
76
    if evm.message.is_static:
77
        raise WriteInStaticContext
78
79
    # STACK
80
    key = pop(evm.stack).to_be_bytes32()
81
    new_value = pop(evm.stack)
76
    if evm.gas_left <= GasCosts.CALL_STIPEND:
77
        raise OutOfGasError
82
83
    # check we have at least the stipend gas
84
    check_gas(evm, GasCosts.CALL_STIPEND + Uint(1))
85
86
    tx_state = evm.message.tx_env.state
87
    original_value = get_storage_original(
88
        tx_state, evm.message.current_target, key
89
    )
90
    current_value = get_storage(tx_state, evm.message.current_target, key)
91
92
    gas_cost = Uint(0)
93
    state_gas = Uint(0)
94
95
    if (evm.message.current_target, key) not in evm.accessed_storage_keys:
96
        evm.accessed_storage_keys.add((evm.message.current_target, key))
97
        gas_cost += GasCosts.COLD_STORAGE_ACCESS
98
99
    if original_value == current_value and current_value != new_value:
92
        if original_value == 0:
93
            gas_cost += GasCosts.STORAGE_SET
94
        else:
95
            gas_cost += (
96
                GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS
97
            )
100
        # charge regular cost for the operation, even when we
101
        # already charge state gas for state creation
102
        gas_cost += GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS
103
    else:
104
        gas_cost += GasCosts.WARM_ACCESS
105
106
    # Refund Counter Calculation
107
    if current_value != new_value:
108
        if original_value != 0 and current_value != 0 and new_value == 0:
109
            # Storage is cleared for the first time in the transaction
110
            evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR
111
112
        if original_value != 0 and current_value == 0:
113
            # Gas refund issued earlier to be reversed
114
            evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR
115
116
        if original_value == new_value:
112
            # Storage slot being restored to its original value
113
            if original_value == 0:
114
                # Slot was originally empty and was SET earlier
115
                evm.refund_counter += int(
116
                    GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS
117
                )
118
            else:
119
                # Slot was originally non-empty and was UPDATED earlier
120
                evm.refund_counter += int(
121
                    GasCosts.COLD_STORAGE_WRITE
122
                    - GasCosts.COLD_STORAGE_ACCESS
123
                    - GasCosts.WARM_ACCESS
124
                )
117
            # Storage slot being restored to its original value
118
            evm.refund_counter += int(
119
                GasCosts.COLD_STORAGE_WRITE
120
                - GasCosts.COLD_STORAGE_ACCESS
121
                - GasCosts.WARM_ACCESS
122
            )
123
126
    charge_gas(evm, gas_cost)
127
    if evm.message.is_static:
128
        raise WriteInStaticContext
124
    if original_value == current_value and current_value != new_value:
125
        if original_value == 0:
126
            state_gas = StateGasCosts.STORAGE_SET
127
128
    if current_value != new_value and original_value == new_value:
129
        if original_value == 0:
130
            # Slot set then cleared: refund the state gas charge.
131
            credit_state_gas_refund(evm, StateGasCosts.STORAGE_SET)
132
133
    # Charge regular gas before state gas so that a regular-gas OOG
134
    # does not consume state gas that would inflate the parent's
135
    # reservoir on frame failure.
136
    charge_gas(evm, gas_cost)
137
    charge_state_gas(evm, state_gas)
138
    set_storage(tx_state, evm.message.current_target, key, new_value)
139
140
    # PROGRAM COUNTER
141
    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:
145
    <snip>
155
    # STACK
156
    key = pop(evm.stack).to_be_bytes32()
157
158
    # GAS
159
    charge_gas(evm, GasCosts.WARM_ACCESS)
160
161
    # OPERATION
162
    value = get_transient_storage(
163
        evm.message.tx_env.state, evm.message.current_target, key
164
    )
165
    push(evm.stack, value)
166
167
    # PROGRAM COUNTER
168
    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:
172
    <snip>
181
    if evm.message.is_static:
182
        raise WriteInStaticContext
183
184
    # STACK
185
    key = pop(evm.stack).to_be_bytes32()
186
    new_value = pop(evm.stack)
187
188
    # GAS
189
    charge_gas(evm, GasCosts.WARM_ACCESS)
178
    if evm.message.is_static:
179
        raise WriteInStaticContext
190
    set_transient_storage(
191
        evm.message.tx_env.state,
192
        evm.message.current_target,
193
        key,
194
        new_value,
195
    )
196
197
    # PROGRAM COUNTER
198
    evm.pc += Uint(1)