Skip to content

test_dupn_stack_overflow()

Documentation for tests/amsterdam/eip8024_dupn_swapn_exchange/test_dupn.py::test_dupn_stack_overflow@ffe48572.

Generate fixtures for these test cases for Bogota with:

fill -v tests/amsterdam/eip8024_dupn_swapn_exchange/test_dupn.py::test_dupn_stack_overflow --fork Bogota

Test that DUPN aborts when pushing past the stack limit.

The callee pushes max_stack_height + stack_delta items and executes DUPN: from one below the limit the duplicate fills the stack exactly and succeeds, while from a full stack the push overflows and aborts the frame. The caller stores the call's success flag over a nonzero canary.

Source code in tests/amsterdam/eip8024_dupn_swapn_exchange/test_dupn.py
@EIPChecklist.Opcode.Test.StackOverflow()
@pytest.mark.parametrize(
    "stack_delta,call_succeeds",
    [
        pytest.param(-1, True, id="dupn_fills_stack_to_limit"),
        pytest.param(0, False, id="dupn_stack_overflow"),
    ],
)
def test_dupn_stack_overflow(
    stack_delta: int,
    call_succeeds: bool,
    pre: Alloc,
    fork: Fork,
    state_test: StateTestFiller,
) -> None:
    """
    Test that DUPN aborts when pushing past the stack limit.

    The callee pushes `max_stack_height + stack_delta` items and
    executes DUPN: from one below the limit the duplicate fills the
    stack exactly and succeeds, while from a full stack the push
    overflows and aborts the frame. The caller stores the call's
    success flag over a nonzero canary.
    """
    stack_height = fork.max_stack_height() + stack_delta
    callee_code = (
        Op.PUSH0 * stack_height + Op.DUPN[Spec.MIN_STACK_INDEX] + Op.STOP
    )
    callee_address = pre.deploy_contract(callee_code)

    caller_code = Op.SSTORE(0, Op.CALL(gas=Op.GAS, address=callee_address))
    caller_address = pre.deploy_contract(caller_code, storage={0: 0xBA5E})

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

    post = {
        caller_address: Account(
            storage={0: 1 if call_succeeds else 0},
        ),
    }

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

Parametrized Test Cases

This test generates 2 parametrized test cases across 2 forks.