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:
| Operation | Gas | Note |
|---|
| SWAP15 | 3 | Swap with 16th item |
| DUP1-16 | 3 | Same cost tier |
| POP | 2 | Cheaper |
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