Skip to main content
This page is a placeholder. All examples on this page are currently AI-generated and are not correct. This documentation will be completed in the future with accurate, tested examples.

Overview

Opcode: 0x9E Introduced: Frontier (EVM genesis) SWAP15 exchanges the top stack item with the 16th item from the top. Only these two positions change - all other items remain in place.

Specification

Stack Input:
[..., valueN, item14, ..., item1, top]
Stack Output:
[..., top, item14, ..., item1, valueN]
Gas Cost: 3 (GasFastestStep) Operation:
temp = stack[top]
stack[top] = stack[top - 16]
stack[top - 16] = temp

Behavior

SWAP15 exchanges positions of the top item and the item at position 16 from top. Requires stack depth ≥ 16. Key characteristics:
  • Requires stack depth ≥ 16
  • Only two items change positions
  • Middle items (items 1-15) unchanged
  • StackUnderflow if depth < 16
  • Stack depth unchanged

Examples

Basic Usage

import { handler_0x9E_SWAP15 } from '@tevm/voltaire/evm/stack/handlers';
import { createFrame } from '@tevm/voltaire/evm/Frame';

// Swap top with 16th item
const frame = createFrame({
  stack: [1600n, 1500n, 1400n, 1300n, 1200n, 1100n, 1000n, 900n, 800n, 700n, 600n, 500n, 400n, 300n, 200n, 100n],
  gasRemaining: 1000n
});

const err = handler_0x9E_SWAP15(frame);

console.log(frame.stack); // [100n, 1500n, 1400n, 1300n, 1200n, 1100n, 1000n, 900n, 800n, 700n, 600n, 500n, 400n, 300n, 200n, 1600n] - positions 0 and 15 swapped
console.log(frame.gasRemaining); // 997n (3 gas consumed)

Solidity Compilation

contract Example {
    function deepSwap() public pure {
        assembly {
            push1 0x01
            push1 0x02
            push1 0x03
            push1 0x04
            push1 0x05
            push1 0x06
            push1 0x07
            push1 0x08
            push1 0x09
            push1 0x0a
            push1 0x0b
            push1 0x0c
            push1 0x0d
            push1 0x0e
            push1 0x0f
            push1 0x10
            // Stack: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
            swap15
            // Stack: [16, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1]
        }
    }
}

Assembly Usage

assembly {
    push1 0xa
    push1 0xb
    push1 0xc
    push1 0xd
    push1 0xe
    push1 0xf
    push1 0xg
    push1 0xh
    push1 0xi
    push1 0xj
    push1 0xk
    push1 0xl
    push1 0xm
    push1 0xn
    push1 0xo
    push1 0xp
    // Stack: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']

    swap15
    // Stack: ['p', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'a'] - 'a' and 'p' swapped
}

Gas Cost

Cost: 3 gas (GasFastestStep) All SWAP1-16 operations cost the same despite different stack depths accessed. Comparison:
OperationGasNote
SWAP153Swap with 16th item
DUP1-163Same cost tier
POP2Cheaper

Common Usage

Deep Stack Manipulation

function complex() public pure {
    assembly {
        let v0 := 0
        let v1 := 1
        let v2 := 2
        let v3 := 3
        let v4 := 4
        let v5 := 5
        let v6 := 6
        let v7 := 7
        let v8 := 8
        let v9 := 9
        let v10 := 10
        let v11 := 11
        let v12 := 12
        let v13 := 13
        let v14 := 14
        let v15 := 15
        // Need v0 at top
        swap15
        // v0 now at top
    }
}```

### Efficient Reordering

```solidity
// Reorder for function call
assembly {
    // Have: [value, to, token]
    // Need: [token, to, value]
    swap2  // [token, to, value]

    // Call transfer(token, to, value)
    call(gas(), target, 0, 0, 100, 0, 0)
}

Storage Optimization

assembly {
    let slot := 0
    let value := 42
    // Stack: [slot, value]

    // SSTORE needs (slot, value) but we have them reversed
    // No swap needed in this case, but if we did:
    swap1
    // Stack: [value, slot]
    sstore
}

Stack Depth Requirements

Minimum Depth

// SWAP15 requires 16 items
assembly {
    push1 0x01
    push1 0x02
    push1 0x03
    push1 0x04
    push1 0x05
    push1 0x06
    push1 0x07
    push1 0x08
    push1 0x09
    push1 0x0a
    push1 0x0b
    push1 0x0c
    push1 0x0d
    push1 0x0e
    push1 0x0f
    // Only 15 items - SWAP15 will fail!
    swap15  // StackUnderflow
}

Safe Usage

assembly {
    push1 0x01
    push1 0x02
    push1 0x03
    push1 0x04
    push1 0x05
    push1 0x06
    push1 0x07
    push1 0x08
    push1 0x09
    push1 0x0a
    push1 0x0b
    push1 0x0c
    push1 0x0d
    push1 0x0e
    push1 0x0f
    push1 0x10
    // Exactly 16 items - safe
    swap15  // Success
}

Implementation

/**
 * SWAP15 opcode (0x9E) - Swap top with 16th item
 *
 * Stack: [..., valueN, ..., top] => [..., top, ..., valueN]
 * Gas: 3 (GasFastestStep)
 */
export function handler_0x9E_SWAP15(frame: FrameType): EvmError | null {
  const gasErr = consumeGas(frame, FastestStep);
  if (gasErr) return gasErr;

  if (frame.stack.length <= 15) {
    return { type: "StackUnderflow" };
  }

  const topIdx = frame.stack.length - 1;
  const swapIdx = frame.stack.length - 16;
  const temp = frame.stack[topIdx];
  frame.stack[topIdx] = frame.stack[swapIdx];
  frame.stack[swapIdx] = temp;

  frame.pc += 1;
  return null;
}

Edge Cases

Stack Underflow

// Insufficient stack depth
const frame = createFrame({
  stack: [100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n]  // Only 15 items, need 16
});

const err = handler_0x9E_SWAP15(frame);
console.log(err); // { type: "StackUnderflow" }

Out of Gas

// Insufficient gas
const frame = createFrame({
  stack: [100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n, 100n],
  gasRemaining: 2n  // Need 3
});

const err = handler_0x9E_SWAP15(frame);
console.log(err); // { type: "OutOfGas" }

Identity Swap

// Swap same values
const frame = createFrame({
  stack: new Array(16).fill(42n)
});

handler_0x9E_SWAP15(frame);
console.log(frame.stack); // All still 42n

Maximum Values

// Swap with max uint256
const MAX = (1n << 256n) - 1n;
const frame = createFrame({
  stack: [0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, MAX, 1n]
});

handler_0x9E_SWAP15(frame);
console.log(frame.stack[0]); // 1n (was at top)
console.log(frame.stack[15]); // MAX (was at bottom)

References