Skip to content

Commit

Permalink
EXCHANGE
Browse files Browse the repository at this point in the history
Exercise exchange operation

Signed-off-by: Danno Ferrin <danno@numisight.com>
  • Loading branch information
shemnon committed May 3, 2024
1 parent 1054283 commit bfbf248
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/ethereum_test_tools/vm/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -5014,6 +5014,36 @@ class Opcodes(Opcode, Enum):
"""

EXCHANGE = Opcode(0xE8, data_portion_length=1)
"""
!!! Note: This opcode is under development
EXCHANGE[mn]
----
Description
----
Exchanges two stack positions. Two nybbles, n is high 4 bits + 1, then m is 4 low bits + 1.
Exchanges tne n+1'th item with the n + m + 1 item.
Inputs
----
n + m + 1, or ((imm >> 4) + (imm &0x0F) + 3) from the raw immediate,
Outputs
----
n + m + 1, or ((imm >> 4) + (imm &0x0F) + 3) from the raw immediate,
Fork
----
EOF_FORK
Gas
----
3
"""

CREATE3 = Opcode(0xEC, popped_stack_items=4, pushed_stack_items=1, data_portion_length=1)
"""
!!! Note: This opcode is under development
Expand Down
67 changes: 67 additions & 0 deletions tests/prague/eip663_dupn_swapn_exchange/test_exchange.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
abstract: Tests [EIP-663: SWAPN, DUPN and EXCHANGE instructions](https://eips.ethereum.org/EIPS/eip-663)
Tests for the SWAPN instruction.
""" # noqa: E501

import pytest

from ethereum_test_tools import Account, Environment, StateTestFiller, TestAddress, Transaction
from ethereum_test_tools.eof.v1 import Container, Section
from ethereum_test_tools.eof.v1.constants import NON_RETURNING_SECTION
from ethereum_test_tools.vm.opcode import Opcodes as Op

from ..eip3540_eof_v1.spec import EOF_FORK_NAME
from . import REFERENCE_SPEC_GIT_PATH, REFERENCE_SPEC_VERSION

REFERENCE_SPEC_GIT_PATH = REFERENCE_SPEC_GIT_PATH
REFERENCE_SPEC_VERSION = REFERENCE_SPEC_VERSION


@pytest.mark.valid_from(EOF_FORK_NAME)
def test_exchange_all_valid_immediates(
tx: Transaction,
state_test: StateTestFiller,
):
"""
Test case for all valid SWAPN immediates.
"""
n = 256
s = 34
values = range(0x3E8, 0x3E8 + s)

eof_code = Container(
sections=[
Section.Code(
code=b"".join(Op.PUSH2(v) for v in values)
+ b"".join(Op.EXCHANGE(x) for x in range(0, n))
+ b"".join((Op.PUSH1(x) + Op.SSTORE) for x in range(0, s))
+ Op.STOP,
code_inputs=0,
code_outputs=NON_RETURNING_SECTION,
max_stack_height=s + 1,
)
],
)

pre = {
TestAddress: Account(balance=1_000_000_000),
tx.to: Account(code=eof_code),
}

# this does the same full-loop exchange
values_rotated = list(range(0x3E8, 0x3E8 + s))
for e in range(0, n):
a = (e >> 4) + 1
b = (e & 0x0F) + 1 + a
tmp = values_rotated[a]
values_rotated[a] = values_rotated[b]
values_rotated[b] = tmp

post = {tx.to: Account(storage=dict(zip(range(0, s), reversed(values_rotated))))}

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

0 comments on commit bfbf248

Please sign in to comment.