@pytest.mark.parametrize(
"starting_nonce",
[
pytest.param(1, id="nonce_1_initial_value"),
pytest.param(127, id="nonce_127_max_single_byte"),
pytest.param(255, id="nonce_max_1_byte_value"),
pytest.param(256**2 - 1, id="nonce_max_2_byte_value"),
pytest.param(256**3 - 1, id="nonce_max_3_byte_value"),
pytest.param(256**4 - 1, id="nonce_max_4_byte_value"),
pytest.param(256**5 - 1, id="nonce_max_5_byte_value"),
pytest.param(256**6 - 1, id="nonce_max_6_byte_value"),
pytest.param(256**7 - 1, id="nonce_max_7_byte_value"),
],
)
@pytest.mark.pre_alloc_mutable
@pytest.mark.valid_from("Osaka")
def test_create_address_nonce_boundary(
pre: Alloc,
state_test: StateTestFiller,
starting_nonce: int,
) -> None:
"""
Verify CreatePreimageLayout at RLP encoding size boundaries.
Deploy a contract at an address whose first and last bytes are
zero, with a prestate nonce set to ``starting_nonce``. Run
CREATE in a loop for a small number of iterations, verifying
each computed address matches the actual one.
Each boundary value is the last nonce before the RLP encoding
grows by one byte.
"""
# EVM does not allow nonces higher than 8 bytes, so a PUSH8 will always fit
nonce_push = Op.PUSH8(starting_nonce)
layout = CreatePreimageLayout(
sender_address=Op.ADDRESS,
nonce=nonce_push,
offset=32,
)
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, BOUNDARY_ITERATIONS)
code += While(body=body, condition=Op.MLOAD(0))
code += Op.SSTORE(0, 1)
code += Op.STOP
pre.deploy_contract(
code=code,
address=DEPLOYER_ADDRESS,
nonce=starting_nonce,
)
sender = pre.fund_eoa()
tx = Transaction(to=DEPLOYER_ADDRESS, sender=sender)
post = {DEPLOYER_ADDRESS: Account(storage={0: 1})}
for nonce in range(starting_nonce, starting_nonce + BOUNDARY_ITERATIONS):
created = compute_create_address(address=DEPLOYER_ADDRESS, nonce=nonce)
post[created] = Account(nonce=1)
state_test(pre=pre, tx=tx, post=post)