ethereum.forks.shanghai.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:
24
    """
25
    Loads to the stack, the value corresponding to a certain key from the
26
    storage of the current account.
27
28
    Parameters
29
    ----------
30
    evm :
31
        The current EVM frame.
32
33
    """
34
    # STACK
35
    key = pop(evm.stack).to_be_bytes32()
36
37
    # GAS
38
    if (evm.message.current_target, key) in evm.accessed_storage_keys:
39
        charge_gas(evm, GasCosts.WARM_ACCESS)
40
    else:
41
        evm.accessed_storage_keys.add((evm.message.current_target, key))
42
        charge_gas(evm, GasCosts.COLD_STORAGE_ACCESS)
43
44
    # OPERATION
45
    tx_state = evm.message.tx_env.state
46
    value = get_storage(tx_state, evm.message.current_target, key)
47
48
    push(evm.stack, value)
49
50
    # PROGRAM COUNTER
51
    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:
55
    """
56
    Stores a value at a certain key in the current context's storage.
57
58
    Parameters
59
    ----------
60
    evm :
61
        The current EVM frame.
62
63
    """
64
    # STACK
65
    key = pop(evm.stack).to_be_bytes32()
66
    new_value = pop(evm.stack)
67
    if evm.gas_left <= GasCosts.CALL_STIPEND:
68
        raise OutOfGasError
69
70
    tx_state = evm.message.tx_env.state
71
    original_value = get_storage_original(
72
        tx_state, evm.message.current_target, key
73
    )
74
    current_value = get_storage(tx_state, evm.message.current_target, key)
75
76
    gas_cost = Uint(0)
77
78
    if (evm.message.current_target, key) not in evm.accessed_storage_keys:
79
        evm.accessed_storage_keys.add((evm.message.current_target, key))
80
        gas_cost += GasCosts.COLD_STORAGE_ACCESS
81
82
    if original_value == current_value and current_value != new_value:
83
        if original_value == 0:
84
            gas_cost += GasCosts.STORAGE_SET
85
        else:
86
            gas_cost += (
87
                GasCosts.COLD_STORAGE_WRITE - GasCosts.COLD_STORAGE_ACCESS
88
            )
89
    else:
90
        gas_cost += GasCosts.WARM_ACCESS
91
92
    # Refund Counter Calculation
93
    if current_value != new_value:
94
        if original_value != 0 and current_value != 0 and new_value == 0:
95
            # Storage is cleared for the first time in the transaction
96
            evm.refund_counter += GasCosts.REFUND_STORAGE_CLEAR
97
98
        if original_value != 0 and current_value == 0:
99
            # Gas refund issued earlier to be reversed
100
            evm.refund_counter -= GasCosts.REFUND_STORAGE_CLEAR
101
102
        if original_value == new_value:
103
            # Storage slot being restored to its original value
104
            if original_value == 0:
105
                # Slot was originally empty and was SET earlier
106
                evm.refund_counter += int(
107
                    GasCosts.STORAGE_SET - GasCosts.WARM_ACCESS
108
                )
109
            else:
110
                # Slot was originally non-empty and was UPDATED earlier
111
                evm.refund_counter += int(
112
                    GasCosts.COLD_STORAGE_WRITE
113
                    - GasCosts.COLD_STORAGE_ACCESS
114
                    - GasCosts.WARM_ACCESS
115
                )
116
117
    charge_gas(evm, gas_cost)
118
    if evm.message.is_static:
119
        raise WriteInStaticContext
120
    set_storage(tx_state, evm.message.current_target, key, new_value)
121
122
    # PROGRAM COUNTER
123
    evm.pc += Uint(1)