Skip to content

test_exchange_basic()

Documentation for tests/amsterdam/eip8024_dupn_swapn_exchange/test_exchange.py::test_exchange_basic@ffe48572.

Generate fixtures for these test cases for Bogota with:

fill -v tests/amsterdam/eip8024_dupn_swapn_exchange/test_exchange.py::test_exchange_basic --fork Bogota

Test EXCHANGE with various n and m values.

Source code in tests/amsterdam/eip8024_dupn_swapn_exchange/test_exchange.py
@EIPChecklist.Opcode.Test.StackComplexOperations.StackHeights.Odd()
@EIPChecklist.Opcode.Test.StackComplexOperations.StackHeights.Even()
@pytest.mark.parametrize(
    "n,m",
    [
        (1, 2),  # Swap positions 2 and 3
        (1, 16),  # Swap positions 2 and 17
        (1, 29),  # Swap positions 2 and 30 (n + m = 30)
        (5, 10),  # Swap positions 6 and 11
        (13, 17),  # Swap positions 14 and 18 (n + m = 30)
        (14, 16),  # Swap positions 15 and 17 (n + m = 30)
    ],
    ids=lambda x: f"{x}",
)
def test_exchange_basic(
    n: int,
    m: int,
    pre: Alloc,
    fork: Fork,
    state_test: StateTestFiller,
) -> None:
    """Test EXCHANGE with various n and m values."""
    sender = pre.fund_eoa()

    # EXCHANGE with decoded (n, m) swaps position (n+1) with position (m+1)
    stack_height = m + 1  # Need at least m+1 items
    value_at_n_plus_1 = 0xAAAA
    value_at_m_plus_1 = 0xBBBB

    # Build stack with known values at swap positions (n+1) and (m+1)
    code = Bytecode()
    for i in range(stack_height):
        # Stack position is 1-indexed from top, so i=0 is bottom
        stack_pos = stack_height - i  # Position from top (1-indexed)
        if stack_pos == n + 1:
            code += Op.PUSH2(value_at_n_plus_1)
        elif stack_pos == m + 1:
            code += Op.PUSH2(value_at_m_plus_1)
        else:
            code += Op.PUSH2(0x1000 + i)

    # Pass n and m directly - encoder will handle encoding
    code += Op.EXCHANGE[n, m]

    # Store all stack values to verify the swap
    for i in range(stack_height):
        code += Op.PUSH1(i) + Op.SSTORE

    code += Op.STOP

    contract_address = pre.deploy_contract(code=code)

    tx = Transaction(to=contract_address, sender=sender)

    # Build expected storage
    expected_storage = {}
    for i in range(stack_height):
        stack_pos = i + 1  # Position from top (1-indexed)
        if stack_pos == n + 1:
            expected_storage[i] = value_at_m_plus_1  # Now has value from m+1
        elif stack_pos == m + 1:
            expected_storage[i] = value_at_n_plus_1  # Now has value from n+1
        else:
            # Original value at this position
            original_i = stack_height - stack_pos
            expected_storage[i] = 0x1000 + original_i

    post = {contract_address: Account(storage=expected_storage)}

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

Parametrized Test Cases

This test generates 6 parametrized test cases across 2 forks.