ethereum.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:
38
    <snip>
48
    # STACK
49
    key = pop(evm.stack).to_be_bytes32()
50
51
    # GAS
52
    if (evm.current_target, key) in evm.accessed_storage_keys:
53
        charge_gas(evm, GasCosts.WARM_ACCESS)
54
    else:
55
        evm.accessed_storage_keys.add((evm.current_target, key))
56
        charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS)
57
58
    # OPERATION
59
    tx_state = evm.tx_env.state
60
    value = get_storage(tx_state, evm.current_target, key)
61
62
    push(evm.stack, value)
63
64
    # PROGRAM COUNTER
65
    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:
69
    <snip>
78
    if evm.is_static:
79
        raise WriteInStaticContext
80
81
    # STACK
82
    key = pop(evm.stack).to_be_bytes32()
83
    new_value = pop(evm.stack)
84
85
    # GAS (STATE-INDEPENDENT)
86
    # Price what is computable without touching state, and check it is
87
    # affordable before any state access is performed.
88
    gas_cost = GasCosts.ZERO
89
90
    # Access cost: cold or warm, always charged.
91
    is_cold_access = (
92
        evm.current_target,
93
        key,
94
    ) not in evm.accessed_storage_keys
95
    if is_cold_access:
96
        gas_cost += GasCosts.COLD_STORAGE_ACCESS
97
    else:
98
        gas_cost += GasCosts.WARM_ACCESS
99
100
    # EIP-2200 stipend sentry, checked before the state access below
101
    # records the slot read in the Block Access List. The `max` guards an
102
    # access cost repriced above the stipend; neither warmth is today.
103
    check_gas(
104
        evm, max(gas_cost, ExecutionGas(GasCosts.CALL_STIPEND + Uint(1)))
105
    )
106
107
    # STATE ACCESS (STATE-DEPENDENT GAS)
108
    # Perform the access and complete the state-dependent pricing from
109
    # the slot's original and current values, adjusting the
110
    # transaction's refunds.
111
    if is_cold_access:
112
        evm.accessed_storage_keys.add((evm.current_target, key))
113
114
    tx_state = evm.tx_env.state
115
    original_value = get_storage_original(tx_state, evm.current_target, key)
116
    current_value = get_storage(tx_state, evm.current_target, key)
117
118
    state_gas = StateGas(Uint(0))
119
120
    # Write cost: charged each time the slot moves away from its
121
    # transaction-start value; restoring it refunds the charge below.
122
    if original_value == current_value and current_value != new_value:
123
        gas_cost += GasCosts.STORAGE_WRITE
124
125
    # Refund Counter Calculation
126
    if current_value != new_value:
127
        if original_value != 0 and current_value != 0 and new_value == 0:
128
            # Slot non-zero at transaction start is cleared; granted on
129
            # each such clear.
130
            evm.gas_meter.refund_counter += GasCosts.REFUND_STORAGE_CLEAR
131
132
        if original_value != 0 and current_value == 0:
133
            # Gas refund issued earlier to be reversed
134
            evm.gas_meter.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR
135
136
        if original_value == new_value:
137
            # Slot restored to its original value: refund the
138
            # STORAGE_WRITE charged when it was moved away.
139
            evm.gas_meter.refund_counter += int(GasCosts.STORAGE_WRITE)
140
141
    # STATE GAS
142
    # A first-time set of a zero slot pays for the state it creates; a
143
    # slot set then cleared refills the earlier charge.
144
    if original_value == current_value and current_value != new_value:
145
        if original_value == 0:
146
            state_gas = StateGasCosts.STORAGE_SET
147
148
    if current_value != new_value and original_value == new_value:
149
        if original_value == 0:
150
            # Slot set then cleared: refund the state gas charge.
151
            credit_state_gas_refund(evm.gas_meter, StateGasCosts.STORAGE_SET)
152
153
    # Charge execution gas before state gas so that an execution-gas
154
    # OOG does not consume state gas that would inflate the parent's
155
    # reservoir on frame failure.
156
    charge_gas(evm, gas_cost)
157
    charge_state_gas(evm, state_gas)
158
    set_storage(tx_state, evm.current_target, key, new_value)
159
160
    # PROGRAM COUNTER
161
    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:
165
    <snip>
175
    # STACK
176
    key = pop(evm.stack).to_be_bytes32()
177
178
    # GAS
179
    charge_gas(evm, GasCosts.OPCODE_TLOAD)
180
181
    # OPERATION
182
    value = get_transient_storage(evm.tx_env.state, evm.current_target, key)
183
    push(evm.stack, value)
184
185
    # PROGRAM COUNTER
186
    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:
190
    <snip>
199
    if evm.is_static:
200
        raise WriteInStaticContext
201
202
    # STACK
203
    key = pop(evm.stack).to_be_bytes32()
204
    new_value = pop(evm.stack)
205
206
    # GAS
207
    charge_gas(evm, GasCosts.OPCODE_TSTORE)
208
    set_transient_storage(
209
        evm.tx_env.state,
210
        evm.current_target,
211
        key,
212
        new_value,
213
    )
214
215
    # PROGRAM COUNTER
216
    evm.pc += Uint(1)