SWAP Chain Analysis: Opportunities for the EXCHANGE Instruction
Methodology
We instrumented Zilkworm to track consecutive sequences of SWAP instructions during execution of Ethereum mainnet blocks. A βSWAP chainβ is a run of two or more SWAP instructions with no other opcodes in between.
Dataset: ~2,720 mainnet blocks (block range 24398374β24621109), representing typical recent Ethereum transaction workloads.
Collection: Runtime instrumentation β we count how many times each unique consecutive SWAP pattern is executed, not just how many exist in bytecode. This reflects actual gas expenditure.
Key Results
Each replacement of 3 SWAPs (3 bytes, 9 gas) with 1 EXCHANGE (2 bytes, 3 gas) eliminates 2 instructions, saves 1 byte and 6 gas.
| Metric |
Value |
| Total SWAP chain occurrences |
67,359,504 |
| Total SWAP instructions in chains |
160,252,881 |
| Unique chain patterns |
4,599 |
| Gas spent in chains (at 3 gas/SWAP) |
480,758,643 |
| Instructions eliminated by EXCHANGE |
25,947,384 (16.2%) |
| Bytes saved |
12,973,692 |
| Gas saved |
77,842,152 (16.2%) |
| Per-block average instructions eliminated |
~9,539 |
| Per-block average bytes saved |
~4,769 |
| Per-block average gas saved |
~28,618 |
EXCHANGE Instruction Background (EIP-8024)
The EXCHANGE instruction (0xe8) is proposed in EIP-8024 for legacy EVM (not EOF-only). It swaps two stack items that are not the top of stack:
- Encoding:
0xe8 imm where imm is a single byte
- The immediate is decoded via
decode_pair(x) yielding (n, m): k = x ^ 143; q, r = divmod(k, 16); if q < r: (n, m) = (q+1, r+1), else (n, m) = (r+1, 29-q)
- Constraints:
1 <= n < m, n + m <= 30
- Effect: swap the
(n+1)th stack item with the (m+1)th stack item (i.e., stack[n] with stack[m], 0-indexed from top)
- Valid
n range: 1β14, valid m range: 2β29
- Gas cost: 3 (same as SWAP)
- Certain immediate values (
0x5b, 0x60β0x7f) are disallowed to preserve JUMPDEST and PUSH semantics in legacy bytecode
Unlike SWAP (which always involves stack[0]), EXCHANGE operates on deeper stack positions. This is exactly what many SWAP chains achieve: swapping two non-top elements by temporarily routing through stack[0].
Pattern Categories
1. Exact EXCHANGE Replacements (3 SWAPs β 1 EXCHANGE)
The pattern SWAP_a SWAP_b SWAP_a (where a != b) has the net effect of swapping stack[min(a,b)] with stack[max(a,b)] while leaving stack[0] unchanged. This is exactly one EXCHANGE instruction. Each replacement eliminates 2 instructions, saves 1 byte and 6 gas.
130 unique patterns, 12,046,816 occurrences. 24,093,632 instructions eliminated, 12,046,816 bytes saved, 72,280,896 gas saved.
Top patterns:
| Count |
Pattern |
Replacement |
Effect |
| 4,100,981 |
SWAP2 SWAP1 SWAP2 |
EXCHANGE(1,1) |
stack[1] β stack[2] |
| 3,553,495 |
SWAP1 SWAP2 SWAP1 |
EXCHANGE(1,1) |
stack[1] β stack[2] |
| 1,186,570 |
SWAP4 SWAP1 SWAP4 |
EXCHANGE(1,3) |
stack[1] β stack[4] |
| 1,169,171 |
SWAP3 SWAP1 SWAP3 |
EXCHANGE(1,2) |
stack[1] β stack[3] |
| 619,504 |
SWAP6 SWAP1 SWAP6 |
EXCHANGE(1,5) |
stack[1] β stack[6] |
| 382,698 |
SWAP5 SWAP1 SWAP5 |
EXCHANGE(1,4) |
stack[1] β stack[5] |
| 147,086 |
SWAP3 SWAP2 SWAP3 |
EXCHANGE(2,1) |
stack[2] β stack[3] |
| 112,397 |
SWAP2 SWAP3 SWAP2 |
EXCHANGE(2,1) |
stack[2] β stack[3] |
| 101,031 |
SWAP9 SWAP1 SWAP9 |
EXCHANGE(1,8) |
stack[1] β stack[9] |
| 95,989 |
SWAP7 SWAP1 SWAP7 |
EXCHANGE(1,6) |
stack[1] β stack[7] |
| 85,593 |
SWAP8 SWAP1 SWAP8 |
EXCHANGE(1,7) |
stack[1] β stack[8] |
| 63,039 |
SWAP10 SWAP1 SWAP10 |
EXCHANGE(1,9) |
stack[1] β stack[10] |
| 62,252 |
SWAP13 SWAP1 SWAP13 |
EXCHANGE(1,12) |
stack[1] β stack[13] |
| 61,830 |
SWAP12 SWAP1 SWAP12 |
EXCHANGE(1,11) |
stack[1] β stack[12] |
| 60,708 |
SWAP11 SWAP1 SWAP11 |
EXCHANGE(1,10) |
stack[1] β stack[11] |
The dominant sub-pattern is SWAP_x SWAP1 SWAP_x β swapping stack[1] with a deeper element. This accounts for the vast majority of exact replacements.
2. Partial EXCHANGE Replacements (within longer chains)
Longer chains often contain SWAP_a SWAP_b SWAP_a sub-patterns that can be extracted and replaced, reducing the chain length.
1,047 unique patterns, 926,876 sub-pattern replacements. 1,853,752 instructions eliminated, 926,876 bytes saved, 5,561,256 gas saved.
Top examples:
| Count |
Original |
After EXCHANGE |
| 101,181 |
SWAP3 SWAP6 SWAP3 SWAP5 [4 ops] |
EXCHANGE(3,3) SWAP5 [2 ops] |
| 77,153 |
SWAP3 SWAP1 SWAP2 SWAP1 [4 ops] |
SWAP3 EXCHANGE(1,1) [2 ops] |
| 52,174 |
SWAP1 SWAP3 SWAP2 SWAP3 [4 ops] |
SWAP1 EXCHANGE(2,1) [2 ops] |
| 44,443 |
SWAP1 SWAP3 SWAP1 SWAP2 [4 ops] |
EXCHANGE(1,2) SWAP2 [2 ops] |
| 39,550 |
SWAP3 SWAP2 SWAP1 SWAP2 [4 ops] |
SWAP3 EXCHANGE(1,1) [2 ops] |
3. Staircase Patterns (not directly replaceable)
Descending staircases (SWAPn SWAPn-1 ... SWAP1) perform a left rotation, bringing a deep element to the top. Ascending staircases (SWAP1 SWAP2 ... SWAPn) push the top element down to depth n.
These cannot be replaced by a single EXCHANGE since they fundamentally change stack[0]. However, they could benefit from a hypothetical ROTATE n instruction.
Descending staircases: 59 patterns, 1,424,636 occurrences
| Count |
Pattern |
Effect |
| 528,154 |
SWAP3 SWAP2 SWAP1 |
Rotate top 4 left |
| 478,047 |
SWAP4 SWAP3 SWAP2 SWAP1 |
Rotate top 5 left |
| 175,318 |
SWAP4 SWAP3 SWAP2 |
Rotate top 3 of [1..4] left |
| 61,955 |
SWAP6 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 |
Rotate top 7 left |
| 59,247 |
SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 |
Rotate top 6 left |
Ascending staircases: ~186,870 occurrences
| Count |
Pattern |
| 78,674 |
SWAP1 SWAP2 SWAP3 SWAP4 SWAP5 |
| 56,268 |
SWAP1 SWAP2 SWAP3 |
| 30,609 |
SWAP1 SWAP2 SWAP3 SWAP4 |
| 14,192 |
SWAP1 SWAP2 SWAP3 SWAP4 SWAP5 SWAP6 |
4. Two-Element Pairs (dominant by volume)
Pairs account for 60.7% of all SWAP chain instructions (97.3M instructions). These cannot be reduced by EXCHANGE since they are only 2 instructions and EXCHANGE requires 3 SWAPs to justify a replacement.
The most common pairs are adjacent descending pairs forming rotations:
| Count |
Pattern |
Semantic |
| 14,926,659 |
SWAP2 SWAP1 |
Rotate top 3 left |
| 13,086,432 |
SWAP3 SWAP2 |
Rotate top 4 left (partial) |
| 5,359,213 |
SWAP4 SWAP3 |
Rotate top 5 left (partial) |
| 4,810,215 |
SWAP1 SWAP2 |
Rotate top 3 right |
| 2,129,201 |
SWAP1 SWAP3 |
Move stack[3] toward top |
Chain Length Distribution
| Length |
Patterns |
Occurrences |
Instructions |
% of Total |
| 2 |
224 |
48,659,466 |
97,318,932 |
60.7% |
| 3 |
807 |
14,933,556 |
44,800,668 |
28.0% |
| 4 |
1,101 |
2,457,743 |
9,830,972 |
6.1% |
| 5 |
793 |
591,118 |
2,955,590 |
1.8% |
| 6 |
593 |
275,495 |
1,652,970 |
1.0% |
| 7+ |
1,081 |
442,126 |
3,694,749 |
2.3% |
EXCHANGE Usage Distribution
The following table shows which EXCHANGE(n, m) pairs would be used and how often, combining both exact and partial replacements. 104 unique pairs out of 210 possible are utilized.
The distribution is heavily skewed toward n=1 (swapping stack[1] with a deeper element), which accounts for 91.0% of all replacements. EXCHANGE(1,2) alone covers 60.6%.
Top 20 pairs:
| EXCHANGE(n,m) |
Effect |
Count |
% |
|
| EXCHANGE(1,2) |
stack[1] β stack[2] |
7,859,407 |
60.58% |
ββββββββββββββββββββββββββββββββββββββββ |
| EXCHANGE(1,3) |
stack[1] β stack[3] |
1,271,267 |
9.80% |
ββββββ |
| EXCHANGE(1,4) |
stack[1] β stack[4] |
1,222,069 |
9.42% |
ββββββ |
| EXCHANGE(1,6) |
stack[1] β stack[6] |
643,284 |
4.96% |
βββ |
| EXCHANGE(1,5) |
stack[1] β stack[5] |
408,369 |
3.15% |
ββ |
| EXCHANGE(2,3) |
stack[2] β stack[3] |
344,159 |
2.65% |
β |
| EXCHANGE(1,7) |
stack[1] β stack[7] |
118,183 |
0.91% |
β |
| EXCHANGE(3,6) |
stack[3] β stack[6] |
113,528 |
0.88% |
β |
| EXCHANGE(2,5) |
stack[2] β stack[5] |
110,596 |
0.85% |
β |
| EXCHANGE(1,9) |
stack[1] β stack[9] |
105,314 |
0.81% |
β |
| EXCHANGE(1,8) |
stack[1] β stack[8] |
104,035 |
0.80% |
β |
| EXCHANGE(1,10) |
stack[1] β stack[10] |
73,893 |
0.57% |
|
| EXCHANGE(3,5) |
stack[3] β stack[5] |
66,863 |
0.52% |
|
| EXCHANGE(1,11) |
stack[1] β stack[11] |
66,763 |
0.51% |
|
| EXCHANGE(3,4) |
stack[3] β stack[4] |
66,499 |
0.51% |
|
| EXCHANGE(1,13) |
stack[1] β stack[13] |
66,419 |
0.51% |
|
| EXCHANGE(1,12) |
stack[1] β stack[12] |
66,381 |
0.51% |
|
| EXCHANGE(5,6) |
stack[5] β stack[6] |
39,275 |
0.30% |
|
| EXCHANGE(4,5) |
stack[4] β stack[5] |
39,084 |
0.30% |
|
| EXCHANGE(2,4) |
stack[2] β stack[4] |
35,085 |
0.27% |
|
Heatmap of EXCHANGE usage across the full EIP-8024 encoding space (values are log10 of count, . = valid but unused):
n\m 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
1 6.9 6.1 6.1 5.6 5.8 5.1 5.0 5.0 4.9 4.8 4.8 4.8 3.2 2.4 0.7 . . . . . . . . . . . . .
2 5.5 4.5 5.0 3.7 3.4 3.5 3.2 2.2 2.4 1.9 2.9 1.6 2.7 1.1 . . . . . . . . . . . .
3 4.8 4.8 5.1 3.8 3.8 3.5 2.7 2.5 2.1 3.0 1.3 . 1.0 . . . . . . . . . . .
4 4.6 4.2 3.9 3.3 3.2 0.8 3.0 2.3 0.3 2.5 1.1 . . . . . . . . . . .
5 4.6 3.7 4.1 3.5 3.3 1.8 0.0 3.0 2.7 0.0 . . . . . . . . . .
6 3.8 3.5 2.6 2.0 2.6 2.1 1.6 . 1.6 0.0 . . . . . . . .
7 4.5 3.5 2.8 0.3 1.0 1.6 3.3 1.2 . . . . . . . .
8 3.4 3.2 2.2 0.5 2.6 1.7 . . . . . . . .
9 3.8 1.9 0.8 . 1.3 . . . . . . .
10 3.3 1.3 3.5 0.0 1.6 2.7 . . . .
11 2.7 1.7 1.6 . . . . .
12 2.3 0.7 0.3 . . .
13 2.5 1.4 . .
14 2.7 .
All usage is concentrated in the left portion (m <= 16) since SWAP instructions only reach stack position 16. The top-left corner (low n, low m) is the hottest region. The first row (n=1) dominates, confirming that the most common use case is swapping stack[1] with deeper positions. The diagonal (m = n+1, adjacent swaps) also shows elevated usage. The right half of the encoding space (m > 16) is entirely unused β these positions are unreachable from SWAP chain patterns.
EXCHANGE Immediate Range Coverage
All 130 exact replacement patterns (mapping to 90 unique (n, m) pairs) fit within the EIP-8024 EXCHANGE constraints (1 <= n < m, n + m <= 30):
- Maximum
n used: 14
- Maximum
m used: 15
- Maximum
n + m: 29
Since SWAP only addresses positions 1β16 and EXCHANGE can reach up to n + m = 30, the EIP-8024 encoding covers 100% of cases arising from SWAP chain optimization.
Conclusions
-
16.2% of SWAP chain instructions (25.9M) can be eliminated by replacing SWAP_a SWAP_b SWAP_a patterns with a single EXCHANGE, saving 77.8M gas and 13.0M bytes across the dataset. This is a mechanical pattern substitution requiring no algorithmic changes.
-
The EIP-8024 EXCHANGE encoding is sufficient. All observed patterns fit within 1 <= n < m, n + m <= 30. No patterns exceed the encoding limits.
-
The dominant exact pattern is SWAP_x SWAP1 SWAP_x β swapping stack[1] with a deeper element. This accounts for the overwhelming majority of replaceable occurrences.
-
60.7% of chain instructions are in 2-element pairs that cannot be reduced by EXCHANGE. These are fundamentally rotations that move elements through stack[0]. A dedicated rotation instruction would be needed to optimize these.
-
Staircase patterns (descending/ascending) represent another significant class (~1.6M occurrences) that EXCHANGE alone cannot address. These perform full rotations of the top N stack elements. A ROTATE n instruction could replace an entire staircase with a single opcode.