Skip to content

test_create_address_dynamic_nonce()

Documentation for tests/frontier/create/test_create_preimage_layout.py::test_create_address_dynamic_nonce@ffe48572.

Generate fixtures for these test cases for Bogota with:

fill -v tests/frontier/create/test_create_preimage_layout.py::test_create_address_dynamic_nonce --fork Bogota

Verify CreatePreimageLayout dynamic nonce encoding matches CREATE.

A contract calls CREATE(value=0, offset=0, size=0) in a loop, computes the expected address using the dynamic nonce RLP encoder, and reverts if any computed address differs from the actual one.

The loop runs from nonce 1 to 260, crossing the RLP encoding boundary at nonce 128 (1-byte to 2-byte encoding) and at 256 where it has to change the 0x80 prefix to 0x81.

Source code in tests/frontier/create/test_create_preimage_layout.py
@pytest.mark.valid_from("Osaka")
def test_create_address_dynamic_nonce(
    pre: Alloc,
    state_test: StateTestFiller,
) -> None:
    """
    Verify CreatePreimageLayout dynamic nonce encoding matches CREATE.

    A contract calls CREATE(value=0, offset=0, size=0) in a loop,
    computes the expected address using the dynamic nonce RLP encoder,
    and reverts if any computed address differs from the actual one.

    The loop runs from nonce 1 to 260, crossing the RLP encoding
    boundary at nonce 128 (1-byte to 2-byte encoding) and at
    256 where it has to change the 0x80 prefix to 0x81.
    """
    iterations = 260

    # Memory[0:32] is used as the loop counter.
    # Layout starts at offset 32 to avoid conflict.
    layout = CreatePreimageLayout(
        sender_address=Op.ADDRESS,
        nonce=Op.PUSH1(1),
        offset=32,
    )

    # Build the loop body: check address, revert on mismatch,
    # increment nonce, decrement counter.
    body = (
        Conditional(
            condition=Op.EQ(
                layout.address_op(),
                Op.CREATE(value=0, offset=0, size=0),
            ),
            if_false=Op.REVERT(0, 0),
        )
        + layout.increment_nonce_op()
        + Op.MSTORE(0, Op.SUB(Op.MLOAD(0), 1))
    )

    code: Bytecode = layout
    code += Op.MSTORE(0, iterations)
    code += While(body=body, condition=Op.MLOAD(0))
    code += Op.SSTORE(0, 1)
    code += Op.STOP

    contract = pre.deploy_contract(code=code)
    sender = pre.fund_eoa()

    tx = Transaction(
        to=contract,
        sender=sender,
    )

    post = {contract: Account(storage={0: 1})}
    for nonce in range(1, iterations + 1):
        created = compute_create_address(address=contract, nonce=nonce)
        post[created] = Account(nonce=1)

    state_test(pre=pre, tx=tx, post=post)

Parametrized Test Cases

This test generates 1 parametrized test case across 3 forks.