Skip to content

test_jumpi_not_taken_invalid_destination()

Documentation for tests/frontier/opcodes/test_dynamic_jump.py::test_jumpi_not_taken_invalid_destination@ffe48572.

Generate fixtures for these test cases for Bogota with:

fill -v tests/frontier/opcodes/test_dynamic_jump.py::test_jumpi_not_taken_invalid_destination --fork Bogota

Verify that a false-condition JUMPI whose destination is invalid does not fail and falls through.

The condition comes from calldata, so implementations that eagerly validate a static JUMPI destination must still skip the validation when the branch is not taken. The code holds no JUMPDEST at all, so both an in-code destination inside PUSH immediate data and one past the maximum code size are invalid.

Source code in tests/frontier/opcodes/test_dynamic_jump.py
@pytest.mark.ported_from(
    [
        f"{LEGACY_VM_TESTS}/jumpi1Filler.json",
    ],
)
@pytest.mark.valid_from("Frontier")
@pytest.mark.parametrize(
    "dest",
    [pytest.param(1, id="push_data"), pytest.param(2**256 - 1, id="max_u256")],
)
def test_jumpi_not_taken_invalid_destination(
    state_test: StateTestFiller,
    pre: Alloc,
    fork: Fork,
    dest: int,
) -> None:
    """
    Verify that a false-condition JUMPI whose destination is invalid does
    not fail and falls through.

    The condition comes from calldata, so implementations that eagerly
    validate a static JUMPI destination must still skip the validation
    when the branch is not taken. The code holds no JUMPDEST at all, so
    both an in-code destination inside PUSH immediate data and one past
    the maximum code size are invalid.
    """
    storage = Storage()
    code = (
        Op.JUMPI(dest, Op.CALLDATALOAD(0))
        + Op.SSTORE(storage.store_next(1, "fell through"), 1)
        + Op.STOP
    )
    assert Op.JUMPDEST.int() not in bytes(code)

    contract = pre.deploy_contract(code)
    tx = Transaction(
        sender=pre.fund_eoa(),
        to=contract,
        data=Hash(0),
        protected=fork.supports_protected_txs(),
    )

    state_test(pre=pre, post={contract: Account(storage=storage)}, tx=tx)

Parametrized Test Cases

This test generates 2 parametrized test cases across 17 forks.