Skip to content

test_extcodecopy_zero_code()

Documentation for tests/constantinople/eip1052_extcodehash/test_extcodehash.py::test_extcodecopy_zero_code@ffe48572.

Generate fixtures for these test cases for Bogota with:

fill -v tests/constantinople/eip1052_extcodehash/test_extcodehash.py::test_extcodecopy_zero_code --fork Bogota

Test EXTCODECOPY/EXTCODESIZE/EXTCODEHASH of accounts with no code.

Two account types: nonexistent (no state at all) and existing (EOA with balance, no code). EXTCODECOPY writes nothing to memory (stays zero). EXTCODEHASH is zero for nonexistent, keccak256("") for existing accounts.

TODO: The original test also intended to cover empty accounts (zero nonce, zero balance, no code), but such accounts cannot exist in post-Paris forks due to EIP-161 cleanup.

Source code in tests/constantinople/eip1052_extcodehash/test_extcodehash.py
@pytest.mark.ported_from(
    [
        "https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stExtCodeHash/codeCopyZero_ParisFiller.yml",  # noqa: E501
    ],
)
@pytest.mark.parametrize(
    "target_type",
    [
        "nonexistent",
        "existing",
    ],
)
def test_extcodecopy_zero_code(
    state_test: StateTestFiller,
    pre: Alloc,
    target_type: str,
) -> None:
    """
    Test EXTCODECOPY/EXTCODESIZE/EXTCODEHASH of accounts with no code.

    Two account types: nonexistent (no state at all) and existing
    (EOA with balance, no code). EXTCODECOPY writes nothing to memory
    (stays zero). EXTCODEHASH is zero for nonexistent, keccak256("")
    for existing accounts.

    TODO: The original test also intended to cover empty accounts
    (zero nonce, zero balance, no code), but such accounts cannot
    exist in post-Paris forks due to EIP-161 cleanup.
    """
    storage = Storage()

    if target_type == "nonexistent":
        target = pre.nonexistent_account()
        expected_hash: int | bytes = 0
    else:  # existing
        target = pre.fund_eoa(amount=1)
        expected_hash = keccak256(b"")

    code = (
        Op.EXTCODECOPY(target, 0, 0, 32)
        + Op.SSTORE(storage.store_next(0, "extcodecopy"), Op.MLOAD(0))
        + Op.SSTORE(
            storage.store_next(0, "extcodesize"),
            Op.EXTCODESIZE(target),
        )
        + Op.SSTORE(
            storage.store_next(expected_hash, "extcodehash"),
            Op.EXTCODEHASH(target),
        )
        + Op.SSTORE(
            storage.store_next(1, "callcode_result"),
            Op.CALLCODE(50_000, target, 0, 0, 0, 0, 0),
        )
    )

    code_address = pre.deploy_contract(code, storage=storage.canary())

    tx = Transaction(sender=pre.fund_eoa(), to=code_address)

    state_test(
        pre=pre,
        post={code_address: Account(storage=storage)},
        tx=tx,
    )

Parametrized Test Cases

This test generates 2 parametrized test cases across 11 forks.