Skip to content

test_extcodecopy_nonzero_composes_additively()

Documentation for tests/amsterdam/eip8038_state_access_gas_cost_increase/test_ext_code_opcodes_gas.py::test_extcodecopy_nonzero_composes_additively@2867859a.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8038_state_access_gas_cost_increase/test_ext_code_opcodes_gas.py::test_extcodecopy_nonzero_composes_additively --fork Amsterdam

Verify the EIP-8038 EXTCODECOPY surcharge composes additively.

With a non-zero copy size, EXTCODECOPY charges the account-access cost, the EIP-8038 code-read WARM_ACCESS surcharge, the EIP-150 per-word copy cost (OPCODE_COPY_PER_WORD per word, driven by the copied data size), and the memory-expansion cost. The surcharge is a flat add-on that does not interact with the copy or memory terms, so the measured gas must equal the sum of all four components.

Source code in tests/amsterdam/eip8038_state_access_gas_cost_increase/test_ext_code_opcodes_gas.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
@EIPChecklist.GasCostChanges.Test.GasUpdatesMeasurement()
@pytest.mark.parametrize("warm", [False, True], ids=["cold", "warm"])
@pytest.mark.parametrize(
    "copy_size", [32, 96], ids=["one_word", "three_words"]
)
def test_extcodecopy_nonzero_composes_additively(
    state_test: StateTestFiller,
    env: Environment,
    pre: Alloc,
    fork: Fork,
    warm: bool,
    copy_size: int,
) -> None:
    """
    Verify the EIP-8038 ``EXTCODECOPY`` surcharge composes additively.

    With a non-zero copy size, ``EXTCODECOPY`` charges the account-access
    cost, the EIP-8038 code-read ``WARM_ACCESS`` surcharge, the EIP-150
    per-word copy cost (``OPCODE_COPY_PER_WORD`` per word, driven by the
    copied data size), and the memory-expansion cost. The surcharge is a
    flat add-on that does not interact with the copy or memory terms, so
    the measured gas must equal the sum of all four components.
    """
    # Target carries enough code to satisfy the copy; STOP padding keeps
    # it a deployable contract with a non-empty code hash.
    target = pre.deploy_contract(Op.STOP * copy_size)

    # Runnable opcode copying ``copy_size`` bytes of the target's code into
    # memory at offset 0. The metadata mirrors the runtime effect (warmth,
    # copied byte count, and the 0 -> copy_size memory growth) so the
    # opcode model agrees with execution and the overhead reduces to the
    # operand pushes alone.
    measured_code = Op.EXTCODECOPY.with_metadata(
        address_warm=warm,
        data_size=copy_size,
        new_memory_size=copy_size,
        old_memory_size=0,
    )(target, 0, 0, copy_size)

    # Oracle: the same metadata-only opcode. Subtracting its cost from the
    # measured code's cost yields the CodeGasMeasure overhead (the operand
    # PUSHes only), so the stored value equals exactly this opcode cost.
    oracle = Op.EXTCODECOPY.with_metadata(
        address_warm=warm,
        data_size=copy_size,
        new_memory_size=copy_size,
        old_memory_size=0,
    )
    expected_gas = oracle.gas_cost(fork)

    code_gas_measure = CodeGasMeasure(
        code=measured_code,
        overhead_cost=measured_code.gas_cost(fork) - oracle.gas_cost(fork),
        extra_stack_items=0,
    )
    measure_address = pre.deploy_contract(code=code_gas_measure)

    tx = Transaction(
        to=measure_address,
        sender=pre.fund_eoa(),
        access_list=[AccessList(address=target, storage_keys=[])]
        if warm
        else None,
    )

    post = {measure_address: Account(storage={0: expected_gas})}
    state_test(env=env, pre=pre, post=post, tx=tx)

Parametrized Test Cases

This test generates 4 parametrized test cases across 1 fork.