Skip to content

test_create2_oversized_initcode_with_insufficient_balance()

Documentation for tests/shanghai/eip3860_initcode/test_initcode.py::test_create2_oversized_initcode_with_insufficient_balance@b47f0253.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/shanghai/eip3860_initcode/test_initcode.py::test_create2_oversized_initcode_with_insufficient_balance --fork Amsterdam

Test CREATE2 with oversized initcode and insufficient balance.

Regression test for #914

CREATE2 is called with an endowment of 1123123123 (exceeds the contract's zero balance). The initcode size check must take priority over the balance check:

  • Initcode too large: consumes all gas, exits scope, SSTORE(1, 1) is never reached, so storage slot 1 remains 0.
  • Initcode within limit: insufficient balance pushes 0, execution continues, SSTORE(1, 1) executes, so storage slot 1 becomes 1.
Source code in tests/shanghai/eip3860_initcode/test_initcode.py
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
@pytest.mark.ported_from(
    [
        "https://github.com/holiman/goevmlab/blob/master/examples/create2_bug/main.go",
    ],
)
@pytest.mark.parametrize(
    "initcode_oversize,expected_storage_1",
    [
        pytest.param(True, 0, id="initcode_oversize"),
        pytest.param(False, 1, id="initcode_within_limit"),
    ],
)
def test_create2_oversized_initcode_with_insufficient_balance(
    state_test: StateTestFiller,
    pre: Alloc,
    initcode_oversize: bool,
    expected_storage_1: int,
    fork: Fork,
) -> None:
    """
    Test CREATE2 with oversized initcode and insufficient balance.

    Regression test for
    https://github.com/ethereum/execution-specs/issues/914

    CREATE2 is called with an endowment of 1123123123 (exceeds the
    contract's zero balance). The initcode size check must take
    priority over the balance check:

    - Initcode too large: consumes all gas, exits scope, SSTORE(1, 1)
      is never reached, so storage slot 1 remains 0.
    - Initcode within limit: insufficient balance pushes 0, execution
      continues, SSTORE(1, 1) executes, so storage slot 1 becomes 1.
    """
    initcode_size = (
        fork.max_initcode_size() * 2 if initcode_oversize else 0x100
    )
    caller_code = (
        Op.CREATE2(1123123123, 0, initcode_size, 0) + Op.POP + Op.SSTORE(1, 1)
    )
    caller_address = pre.deploy_contract(caller_code)

    sender = pre.fund_eoa()
    tx = Transaction(
        sender=sender,
        to=caller_address,
        gas_limit=10_000_000,
    )

    post = {
        caller_address: Account(storage={1: expected_storage_1}),
    }

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

Parametrized Test Cases

This test generates 2 parametrized test cases across 5 forks.