Skip to content

test_worst_creates_collisions()

Documentation for tests/benchmark/test_worst_bytecode.py::test_worst_creates_collisions@v5.0.0.

Generate fixtures for these test cases for Osaka with:

fill -v tests/benchmark/test_worst_bytecode.py::test_worst_creates_collisions --fork Osaka

Test the CREATE and CREATE2 collisions performance.

Source code in tests/benchmark/test_worst_bytecode.py
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
@pytest.mark.valid_from("Cancun")
@pytest.mark.parametrize(
    "opcode",
    [
        Op.CREATE,
        Op.CREATE2,
    ],
)
def test_worst_creates_collisions(
    state_test: StateTestFiller,
    pre: Alloc,
    fork: Fork,
    opcode: Op,
    gas_benchmark_value: int,
):
    """Test the CREATE and CREATE2 collisions performance."""
    # We deploy a "proxy contract" which is the contract that will be called in a loop
    # using all the gas in the block. This "proxy contract" is the one executing CREATE2
    # failing with a collision.
    # The reason why we need a "proxy contract" is that CREATE(2) failing with a collision will
    # consume all the available gas. If we try to execute the CREATE(2) directly without being
    # wrapped **and capped in gas** in a previous CALL, we would run out of gas very fast!
    #
    # The proxy contract calls CREATE(2) with empty initcode. The current call frame gas will
    # be exhausted because of the collision. For this reason the caller will carefully give us
    # the minimal gas necessary to execute the CREATE(2) and not waste any extra gas in the
    # CREATE(2)-failure.
    #
    # Note that these CREATE(2) calls will fail because in (**) below we pre-alloc contracts
    # with the same address as the ones that CREATE(2) will try to create.
    proxy_contract = pre.deploy_contract(
        code=Op.CREATE2(value=Op.PUSH0, salt=Op.PUSH0, offset=Op.PUSH0, size=Op.PUSH0)
        if opcode == Op.CREATE2
        else Op.CREATE(value=Op.PUSH0, offset=Op.PUSH0, size=Op.PUSH0)
    )

    gas_costs = fork.gas_costs()
    # The CALL to the proxy contract needs at a minimum gas corresponding to the CREATE(2)
    # plus extra required PUSH0s for arguments.
    min_gas_required = gas_costs.G_CREATE + gas_costs.G_BASE * (3 if opcode == Op.CREATE else 4)
    code_prefix = Op.PUSH20(proxy_contract) + Op.PUSH3(min_gas_required)
    attack_block = Op.POP(
        # DUP7 refers to the PUSH3 above.
        # DUP7 refers to the proxy contract address.
        Op.CALL(gas=Op.DUP7, address=Op.DUP7)
    )
    code = code_loop_precompile_call(code_prefix, attack_block, fork)
    tx_target = pre.deploy_contract(code=code)

    # (**) We deploy the contract that CREATE(2) will attempt to create so any attempt will fail.
    if opcode == Op.CREATE2:
        addr = compute_create2_address(address=proxy_contract, salt=0, initcode=[])
        pre.deploy_contract(address=addr, code=Op.INVALID)
    else:
        # Heuristic to have an upper bound.
        max_contract_count = 2 * gas_benchmark_value // gas_costs.G_CREATE
        for nonce in range(max_contract_count):
            addr = compute_create_address(address=proxy_contract, nonce=nonce)
            pre.deploy_contract(address=addr, code=Op.INVALID)

    tx = Transaction(
        to=tx_target,
        gas_limit=gas_benchmark_value,
        sender=pre.fund_eoa(),
    )

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

Parametrized Test Cases

The interactive table below is also available as a standalone page.

Test ID (Abbreviated) opcode
...fork_Cancun-state_test-opcode_CREATE CREATE
...fork_Cancun-state_test-opcode_CREATE2 CREATE2
...fork_Cancun-blockchain_test_from_state_test-opcode_CREATE CREATE
...fork_Cancun-blockchain_test_from_state_test-opcode_CREATE2 CREATE2
...fork_Prague-state_test-opcode_CREATE CREATE
...fork_Prague-state_test-opcode_CREATE2 CREATE2
...fork_Prague-blockchain_test_from_state_test-opcode_CREATE CREATE
...fork_Prague-blockchain_test_from_state_test-opcode_CREATE2 CREATE2
...fork_Osaka-state_test-opcode_CREATE CREATE
...fork_Osaka-state_test-opcode_CREATE2 CREATE2
...fork_Osaka-blockchain_test_from_state_test-opcode_CREATE CREATE
...fork_Osaka-blockchain_test_from_state_test-opcode_CREATE2 CREATE2