@pytest.mark.ported_from(
[
"https://github.com/ethereum/tests/blob/v13.3/src/GeneralStateTestsFiller/stExtCodeHash/extcodehashEmpty_ParisFiller.yml", # noqa: E501
],
pr=["https://github.com/ethereum/execution-specs/pull/2237"],
)
@pytest.mark.parametrize("opcode", [Op.CREATE, Op.CREATE2])
def test_extcodehash_empty_contract_creation(
state_test: StateTestFiller,
pre: Alloc,
opcode: Op,
) -> None:
"""
Test EXTCODEHASH/EXTCODESIZE for empty contracts created with
CREATE/CREATE2.
"""
storage = Storage()
initcode = Op.RETURN(0, 0)
expected_hash = keccak256(b"")
created_slot = storage.store_next(0)
hash_slot = storage.store_next(expected_hash)
size_slot = storage.store_next(0)
copy_slot = storage.store_next(0)
create_op = (
opcode(value=0, offset=0, size=len(initcode), salt=0)
if opcode == Op.CREATE2
else opcode(value=0, offset=0, size=len(initcode))
)
code = (
Op.MSTORE(0, Op.PUSH32(bytes(initcode).ljust(32, b"\0")))
+ Op.SSTORE(created_slot, create_op)
+ Op.SSTORE(
hash_slot,
Op.EXTCODEHASH(Op.SLOAD(created_slot)),
)
+ Op.SSTORE(
size_slot,
Op.EXTCODESIZE(Op.SLOAD(created_slot)),
)
+ Op.EXTCODECOPY(Op.SLOAD(created_slot), 0, 0, 32)
+ Op.SSTORE(copy_slot, Op.MLOAD(0))
+ Op.STOP
)
code_address = pre.deploy_contract(code, storage=storage.canary())
created_address = (
compute_create2_address(
address=code_address,
salt=0,
initcode=initcode,
)
if opcode == Op.CREATE2
else compute_create_address(address=code_address, nonce=1)
)
storage[created_slot] = created_address
tx = Transaction(sender=pre.fund_eoa(), to=code_address)
state_test(
pre=pre,
post={
code_address: Account(storage=storage),
created_address: Account(nonce=1, code=b""),
},
tx=tx,
)