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