Skip to content

test_exchange_stack_underflow()

Documentation for tests/amsterdam/eip8024_dupn_swapn_exchange/test_exchange.py::test_exchange_stack_underflow@b314d18e.

Generate fixtures for these test cases for Amsterdam with:

fill -v tests/amsterdam/eip8024_dupn_swapn_exchange/test_exchange.py::test_exchange_stack_underflow --fork Amsterdam

Test EXCHANGE causes transaction failure on stack underflow.

Source code in tests/amsterdam/eip8024_dupn_swapn_exchange/test_exchange.py
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
@pytest.mark.parametrize(
    "immediate",
    # Boundaries of both valid ranges (0x00, 0x51, 0x80, 0xFF)
    [0, 78, 79, 80, 81, 128, 129, 255],
    ids=lambda x: f"underflow_imm_{x}",
)
def test_exchange_stack_underflow(
    immediate: int,
    pre: Alloc,
    state_test: StateTestFiller,
) -> None:
    """Test EXCHANGE causes transaction failure on stack underflow."""
    sender = pre.fund_eoa()

    # EXCHANGE needs m+1 items. Push one less to trigger underflow.
    n, m = decode_pair(immediate)
    insufficient_depth = m  # m+1 required, push only m

    code = Bytecode()
    code += Op.SSTORE(0, 1)  # Marker

    for i in range(insufficient_depth):
        code += Op.PUSH1(i)

    code += Op.EXCHANGE[immediate.to_bytes(1, "big")]
    code += Op.SSTORE(0, 2)  # Should never execute
    code += Op.STOP

    contract_address = pre.deploy_contract(code=code)
    tx = Transaction(to=contract_address, sender=sender)

    # Transaction should fail, contract storage unchanged
    post = {contract_address: Account(storage={})}

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

Parametrized Test Cases

This test generates 8 parametrized test cases across 1 fork.