Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 18 additions & 24 deletions EIPS/eip-8024.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
eip: 8024
title: Backward compatible SWAPN, DUPN, EXCHANGE
description: Introduce additional instructions for manipulating the stack which allow accessing the stack at higher depths
author: Francisco Giordano (@frangio), Charles Cooper (@charles-cooper), Alex Beregszaszi (@axic)
author: Francisco Giordano (@frangio), Charles Cooper (@charles-cooper), Alex Beregszaszi (@axic), Paweł Bylica (@chfast)
discussions-to: https://ethereum-magicians.org/t/eip-8024-backward-compatible-swapn-dupn-exchange/25486
status: Review
type: Standards Track
Expand Down Expand Up @@ -78,14 +78,11 @@ The auxiliary functions `decode_single` and `decode_pair` are defined by the fol
```python
def decode_single(x: int) -> int:
assert 0 <= x <= 90 or 128 <= x <= 255
if x <= 90:
return x + 17
else:
return x - 20
return (x + 145) & 0xff

def decode_pair(x: int) -> tuple[int, int]:
assert 0 <= x <= 79 or 128 <= x <= 255

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the range of valid byte values is different here?

@frangio frangio Feb 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use the same domain as decode_single, we either have a discontinuity in the pairs that can be represented1, or there would be two ways to encode the same pair. So the range is reduced to keep this a bijection. We could try to map the extra available domain to some other continuous section but I figured the complexity wasn't worth it.

Footnotes

  1. You'd be able to swap 11,16 and 11,18 but not 11,17.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a way to extend EXCHANGE with two more pairs, making 14,15 and 14,16 swappable.

d4f4578

k = x if x <= 79 else x - 48
k = (x + 128) & 0xff
q, r = divmod(k, 16)
if q < r:
return q + 1, r + 1
Expand All @@ -98,10 +95,7 @@ Assemblers and compilers must emit a 1-byte immediate after each of these opcode
```python
def encode_single(n: int) -> int:
assert 17 <= n <= 235
if n <= 107:
return n - 17
else:
return n + 20
return (n + 111) & 0xff

def encode_pair(n: int, m: int) -> int:
assert 1 <= n <= 13 and n < m <= 29 and n + m <= 30
Expand All @@ -110,7 +104,7 @@ def encode_pair(n: int, m: int) -> int:
else:
q, r = 29 - m, n - 1
k = 16 * q + r
return k if k <= 79 else k + 48
return (k + 128) & 0xff
```

## Rationale
Expand Down Expand Up @@ -166,29 +160,29 @@ This has no effect on contracts that would never attempt to execute the opcodes

### Assembly/Disassembly

- `e600` is `[DUPN 17]`
- `e780` is `[SWAPN 108]`
- `e6005b` is `[DUPN 17, JUMPDEST]`
- `e680` is `[DUPN 17]`
- `e7db` is `[SWAPN 108]`
- `e6805b` is `[DUPN 17, JUMPDEST]`
- `e75b` is `[INVALID_SWAPN, JUMPDEST]`
- `e6605b` is `[INVALID_DUPN, PUSH1 0x5b]`
- `e7610000` is `[INVALID_SWAPN, PUSH2 0x0000]`
- `e65f` is `[INVALID_DUPN, PUSH0]`
- `e812` is `[EXCHANGE 2 3]`
- `e8d0` is `[EXCHANGE 1 19]`
- `e892` is `[EXCHANGE 2 3]`
- `e820` is `[EXCHANGE 1 19]`
- `e850` is `[INVALID_EXCHANGE, POP]`

### Execution

- `60016000808080808080808080808080808080e600` results in 18 stack items, the top of the stack valued 1, the bottom of the stack valued 1, the rest valued 0
- `60016000808080808080808080808080808080e6` at the end of the code is equivalent to above
- `600160008080808080808080808080808080806002e700` results in 18 stack items, the top of the stack valued 1, the bottom of the stack valued 2, the rest valued 0
- `600160008080808080808080808080808080806002e7` at the end of the code is equivalent to above
- `600060016002e801` results in 3 stack items, from top to bottom: [2, 0, 1]
- `600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060016002e8` results in 30 stack items, the top of the stack valued 2, the bottom of the stack valued 1, the rest valued 0
- `60016000808080808080808080808080808080e680` results in 18 stack items, the top of the stack valued 1, the bottom of the stack valued 1, the rest valued 0
- `60016000808080808080808080808080808080e6` at the end of the code results in exceptional halt (`code[pc + 1] = 0`, so `DUPN 145`)
Comment thread
frangio marked this conversation as resolved.
Outdated
- `600160008080808080808080808080808080806002e780` results in 18 stack items, the top of the stack valued 1, the bottom of the stack valued 2, the rest valued 0
- `600160008080808080808080808080808080806002e7` at the end of the code results in exceptional halt (`code[pc + 1] = 0`, so `SWAPN 145`)
- `600060016002e881` results in 3 stack items, from top to bottom: [2, 0, 1]
- `600080808080808080808080808080808080808080808080808080808060016002e880` results in 30 stack items, the top of the stack valued 2, the bottom of the stack valued 1, the rest valued 0
- `e75b` reverts
- `600456e65b` executes successfully (`PUSH 04 JUMP INVALID_DUPN JUMPDEST`)
- `600060006000e80115` results in 3 stack items, the top of the stack valued 1, the rest valued 0
- `6000808080808080808080808080808080e600` results in exceptional halt
- `60008080e88115` results in 3 stack items, the top of the stack valued 1, the rest valued 0
- `6000808080808080808080808080808080e680` results in exceptional halt

## Security Considerations

Expand Down
Loading