From 0c301a2ac5d47e71f472f8593cc7ea92db35faa2 Mon Sep 17 00:00:00 2001 From: pdobacz <5735525+pdobacz@users.noreply.github.com> Date: Fri, 2 Oct 2026 08:46:40 +0000 Subject: [PATCH 1/4] Add EIP-8163 EXTENSION opcode test support EIP8163 mixin adopted by a Bogota fork, EXTENSION (0xae) in execution_testing, tests in tests/bogota/eip8163_extension. Co-Authored-By: Claude --- .../src/execution_testing/cli/evm_bytes.py | 1 + .../src/execution_testing/forks/__init__.py | 1 + .../forks/forks/eips/bogota/eip_8163.py | 29 +++ .../src/execution_testing/vm/opcodes.py | 29 +++ tests/bogota/__init__.py | 1 + tests/bogota/eip8163_extension/__init__.py | 1 + tests/bogota/eip8163_extension/spec.py | 17 ++ .../eip8163_extension/test_extension.py | 214 ++++++++++++++++++ 8 files changed, 293 insertions(+) create mode 100644 packages/testing/src/execution_testing/forks/forks/eips/bogota/eip_8163.py create mode 100644 tests/bogota/__init__.py create mode 100644 tests/bogota/eip8163_extension/__init__.py create mode 100644 tests/bogota/eip8163_extension/spec.py create mode 100644 tests/bogota/eip8163_extension/test_extension.py diff --git a/packages/testing/src/execution_testing/cli/evm_bytes.py b/packages/testing/src/execution_testing/cli/evm_bytes.py index 3929ad4dce8..5827037bdb4 100644 --- a/packages/testing/src/execution_testing/cli/evm_bytes.py +++ b/packages/testing/src/execution_testing/cli/evm_bytes.py @@ -12,6 +12,7 @@ Op.STOP, Op.REVERT, Op.INVALID, + Op.EXTENSION, Op.JUMP, Op.JUMPI, } diff --git a/packages/testing/src/execution_testing/forks/__init__.py b/packages/testing/src/execution_testing/forks/__init__.py index 88a7fe529fa..2b08ce44d04 100644 --- a/packages/testing/src/execution_testing/forks/__init__.py +++ b/packages/testing/src/execution_testing/forks/__init__.py @@ -126,6 +126,7 @@ "ArrowGlacier", "Berlin", "BerlinToLondonAt5", + "Bogota", "Byzantium", "Constantinople", "ConstantinopleFix", diff --git a/packages/testing/src/execution_testing/forks/forks/eips/bogota/eip_8163.py b/packages/testing/src/execution_testing/forks/forks/eips/bogota/eip_8163.py new file mode 100644 index 00000000000..f89f26c821f --- /dev/null +++ b/packages/testing/src/execution_testing/forks/forks/eips/bogota/eip_8163.py @@ -0,0 +1,29 @@ +""" +EIP-8163: Reserve EXTENSION (0xae) opcode. + +Reserve `EXTENSION` as an extension prefix for EVM chains other than +Ethereum L1, where it behaves exactly like `INVALID`. + +https://eips.ethereum.org/EIPS/eip-8163 +""" + +from typing import Callable, Dict + +from execution_testing.vm import OpcodeBase, Opcodes + +from ....base_fork import BaseFork + + +class EIP8163(BaseFork): + """EIP-8163 class.""" + + @classmethod + def opcode_gas_map( + cls, + ) -> Dict[OpcodeBase, int | Callable[[OpcodeBase], int]]: + """Add EXTENSION, which halts exceptionally like INVALID.""" + base_map = super(EIP8163, cls).opcode_gas_map() + return { + **base_map, + Opcodes.EXTENSION: 0, + } diff --git a/packages/testing/src/execution_testing/vm/opcodes.py b/packages/testing/src/execution_testing/vm/opcodes.py index f468bab77a6..56385afa7c5 100644 --- a/packages/testing/src/execution_testing/vm/opcodes.py +++ b/packages/testing/src/execution_testing/vm/opcodes.py @@ -5274,6 +5274,35 @@ class Opcodes(Opcode, Enum): Source: [evm.codes/#A4](https://www.evm.codes/#A4) """ + EXTENSION = Opcode(0xAE, terminating=True) + """ + EXTENSION() + ---- + + Description + ---- + Instruction reserved as an extension prefix for non-Ethereum-L1 EVM + chains; behaves exactly like INVALID on Ethereum L1 + + Inputs + ---- + None + + Outputs + ---- + None + + Fork + ---- + Bogota + + Gas + ---- + All the remaining gas in this context is consumed + + Source: [EIP-8163](https://eips.ethereum.org/EIPS/eip-8163) + """ + DUPN = Opcode( 0xE6, pushed_stack_items=1, diff --git a/tests/bogota/__init__.py b/tests/bogota/__init__.py new file mode 100644 index 00000000000..3fc98ba09f8 --- /dev/null +++ b/tests/bogota/__init__.py @@ -0,0 +1 @@ +"""Test cases for EVM functionality introduced in Bogota.""" diff --git a/tests/bogota/eip8163_extension/__init__.py b/tests/bogota/eip8163_extension/__init__.py new file mode 100644 index 00000000000..26602358264 --- /dev/null +++ b/tests/bogota/eip8163_extension/__init__.py @@ -0,0 +1 @@ +"""Tests for [EIP-8163: Reserve EXTENSION (0xae) opcode](https://eips.ethereum.org/EIPS/eip-8163).""" diff --git a/tests/bogota/eip8163_extension/spec.py b/tests/bogota/eip8163_extension/spec.py new file mode 100644 index 00000000000..2d26993b76b --- /dev/null +++ b/tests/bogota/eip8163_extension/spec.py @@ -0,0 +1,17 @@ +"""Reference spec for [EIP-8163: Reserve EXTENSION (0xae) opcode](https://eips.ethereum.org/EIPS/eip-8163).""" + +from dataclasses import dataclass + + +@dataclass(frozen=True) +class ReferenceSpec: + """Reference specification.""" + + git_path: str + version: str + + +ref_spec_8163 = ReferenceSpec( + git_path="EIPS/eip-8163.md", + version="aef32ae28e42ba3a391ed8d991ddf6a68d53c152", +) diff --git a/tests/bogota/eip8163_extension/test_extension.py b/tests/bogota/eip8163_extension/test_extension.py new file mode 100644 index 00000000000..c7046807916 --- /dev/null +++ b/tests/bogota/eip8163_extension/test_extension.py @@ -0,0 +1,214 @@ +""" +Tests for [EIP-8163: Reserve EXTENSION (0xae) opcode](https://eips.ethereum.org/EIPS/eip-8163). + +EXTENSION behaves exactly like INVALID on chains with no extensions +defined for it, Ethereum L1 included, and the byte is neutral to +JUMPDEST analysis everywhere. All assertions here hold on any +EIP-8163-conformant EVM, including chains that define extensions. + +These tests do not assert the non-existence of extensions that would +be conformant but are undefined today: there is no way to +forward-guess under what conditions such an extension would succeed, +and no point in testing it. +""" + +import pytest +from execution_testing import ( + Account, + Alloc, + Bytecode, + Op, + StateTestFiller, + Transaction, + TransactionReceipt, +) + +from .spec import ref_spec_8163 + +REFERENCE_SPEC_GIT_PATH = ref_spec_8163.git_path +REFERENCE_SPEC_VERSION = ref_spec_8163.version + +pytestmark = pytest.mark.valid_from("EIP8163") + +slot_code_worked = 1 +value_code_worked = 0x1234 + + +@pytest.mark.parametrize( + "opcode,success,all_gas_consumed", + [ + pytest.param(Op.EXTENSION, False, True), + pytest.param(Op.INVALID, False, True), + pytest.param(Op.REVERT(0, 0), False, False, id="REVERT"), + pytest.param(Op.JUMPDEST, True, False), + ], +) +def test_top_level_call( + state_test: StateTestFiller, + pre: Alloc, + opcode: Bytecode, + success: bool, + all_gas_consumed: bool, +) -> None: + """ + Call a contract whose whole code is the single tested byte. + + EXTENSION behaves as INVALID, JUMPDEST as sanity check. + """ + contract_address = pre.deploy_contract(code=opcode) + + # Kept under the EIP-7825 transaction gas limit cap: above it, EIP-8037 + # turns the excess into a state gas reservoir that a halt leaves intact. + gas_limit = 1_000_000 + tx = Transaction( + gas_limit=gas_limit, + to=contract_address, + sender=pre.fund_eoa(), + expected_receipt=TransactionReceipt( + status=int(success), + cumulative_gas_used=gas_limit if all_gas_consumed else None, + ), + ) + + state_test(pre=pre, post={}, tx=tx) + + +@pytest.mark.parametrize( + "opcode,success", + [ + pytest.param(Op.EXTENSION, False), + pytest.param(Op.INVALID, False), + pytest.param(Op.JUMPDEST, True), + ], +) +@pytest.mark.parametrize("stack_item", [0, 1]) +def test_execute_with_stack( + state_test: StateTestFiller, + pre: Alloc, + opcode: Op, + success: bool, + stack_item: int, +) -> None: + """ + Execute the tested byte with 256 items of value 0 or 1 on the + stack. + + EXTENSION behaves as INVALID, JUMPDEST as sanity check. + """ + push = Op.PUSH0 if stack_item == 0 else Op.PUSH1(stack_item) + code = Op.SSTORE(slot_code_worked, value_code_worked) + push * 256 + opcode + contract_address = pre.deploy_contract(code=code) + + tx = Transaction(to=contract_address, sender=pre.fund_eoa()) + + storage = {slot_code_worked: value_code_worked} if success else {} + state_test( + pre=pre, + post={contract_address: Account(storage=storage)}, + tx=tx, + ) + + +@pytest.mark.parametrize("valid_jump", [True, False]) +@pytest.mark.parametrize("following_byte", [None, *range(256)]) +def test_jumpdest_analysis_neutrality( + state_test: StateTestFiller, + pre: Alloc, + valid_jump: bool, + following_byte: int | None, +) -> None: + """ + Jump over an EXTENSION byte to a destination right behind it. + + JUMPDEST analysis ignores EXTENSION: a JUMPDEST behind EXTENSION + is a valid destination and a 0x5b held as PUSH1 data behind + EXTENSION is not. EXTENSION is never executed. The optional byte + between EXTENSION and the destination covers all values, PUSH + opcodes with non-truncated data, to show none of them acts as an + EXTENSION immediate during the analysis. + """ + following = b"" + if following_byte is not None: + following = bytes([following_byte]) + if 0x60 <= following_byte <= 0x7F: + push_data_size = following_byte - 0x5F + following += b"\x00" * push_data_size + + sentinel = Op.SSTORE(slot_code_worked, value_code_worked) + destination = len( + sentinel + Op.PUSH2(0) + Op.JUMP + Op.EXTENSION + following + ) + target: Bytecode + if valid_jump: + target = Op.JUMPDEST + else: + # point at the 0x5b held as PUSH1 data + destination += 1 + target = Op.PUSH1(0x5B) + code = ( + sentinel + + Op.PUSH2(destination) + + Op.JUMP + + Op.EXTENSION + + following + + target + ) + contract_address = pre.deploy_contract(code=code) + + tx = Transaction(to=contract_address, sender=pre.fund_eoa()) + + storage = {slot_code_worked: value_code_worked} if valid_jump else {} + state_test( + pre=pre, + post={contract_address: Account(storage=storage)}, + tx=tx, + ) + + +@pytest.mark.parametrize( + "opcode,success", + [ + pytest.param(Op.EXTENSION, False), + pytest.param(Op.INVALID, False), + pytest.param(Op.JUMPDEST, True), + ], +) +@pytest.mark.parametrize("stack_item", [0, 1]) +@pytest.mark.parametrize( + "following_byte", + [pytest.param(b, id=f"0x{b:02x}") for b in [0x5B, *range(0x60, 0x80)]] + + [None], +) +def test_solo_extension_bytes( + state_test: StateTestFiller, + pre: Alloc, + opcode: Op, + success: bool, + stack_item: int, + following_byte: int | None, +) -> None: + """ + Execute the tested byte followed by a solo 0x5b or 0x60..0x7f + byte (or nothing), expect it to halt exceptionally always. + + EIP-8163 rules these out as single-byte extension immediates. + + EXTENSION behaves as INVALID, JUMPDEST as sanity check. + """ + push = Op.PUSH0 if stack_item == 0 else Op.PUSH1(stack_item) + code = ( + Op.SSTORE(slot_code_worked, value_code_worked) + + push * 256 + + opcode + + bytes([following_byte] if following_byte is not None else []) + ) + contract_address = pre.deploy_contract(code=code) + + tx = Transaction(to=contract_address, sender=pre.fund_eoa()) + + storage = {slot_code_worked: value_code_worked} if success else {} + state_test( + pre=pre, + post={contract_address: Account(storage=storage)}, + tx=tx, + ) From d17daf8c20bad8eea5b14742f7f68fc3884ea38d Mon Sep 17 00:00:00 2001 From: pdobacz <5735525+pdobacz@users.noreply.github.com> Date: Fri, 2 Oct 2026 08:00:33 +0000 Subject: [PATCH 2/4] encode the opcode under test with bytes() in the evm_bytes round trip bytes(opcode) is the opcode's encoding whatever its length. Co-Authored-By: Claude --- .../testing/src/execution_testing/cli/tests/test_evm_bytes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/testing/src/execution_testing/cli/tests/test_evm_bytes.py b/packages/testing/src/execution_testing/cli/tests/test_evm_bytes.py index d5622cd7d86..6cc5ec78285 100644 --- a/packages/testing/src/execution_testing/cli/tests/test_evm_bytes.py +++ b/packages/testing/src/execution_testing/cli/tests/test_evm_bytes.py @@ -164,7 +164,7 @@ def test_individual_opcodes(opcode: Op) -> None: else: expected_output = f"Op.{opcode._name_}" - bytecode = opcode.int().to_bytes(1, byteorder="big") + data_portion + bytecode = bytes(opcode) + data_portion assert process_evm_bytes_string("0x" + bytecode.hex()) == expected_output From 2a651e5a08f7ccbd974d0f9e32451d1852ad917a Mon Sep 17 00:00:00 2001 From: pdobacz <5735525+pdobacz@users.noreply.github.com> Date: Tue, 6 Oct 2026 12:46:32 +0000 Subject: [PATCH 3/4] Address review comments Derive the top-level call gas limit from the fork, sweep the solo following byte with a filled stack only, cut the jumpdest analysis sweep to the bytes it can distinguish, and drop the test the solo sweep subsumes. Co-Authored-By: Louis Tsai <72684086+LouisTsai-Csie@users.noreply.github.com> --- .../eip8163_extension/test_extension.py | 137 ++++++++---------- 1 file changed, 59 insertions(+), 78 deletions(-) diff --git a/tests/bogota/eip8163_extension/test_extension.py b/tests/bogota/eip8163_extension/test_extension.py index c7046807916..eea76fd2d22 100644 --- a/tests/bogota/eip8163_extension/test_extension.py +++ b/tests/bogota/eip8163_extension/test_extension.py @@ -17,6 +17,7 @@ Account, Alloc, Bytecode, + Fork, Op, StateTestFiller, Transaction, @@ -32,6 +33,7 @@ slot_code_worked = 1 value_code_worked = 0x1234 +value_code_untouched = 0xBA5E @pytest.mark.parametrize( @@ -46,6 +48,7 @@ def test_top_level_call( state_test: StateTestFiller, pre: Alloc, + fork: Fork, opcode: Bytecode, success: bool, all_gas_consumed: bool, @@ -57,16 +60,21 @@ def test_top_level_call( """ contract_address = pre.deploy_contract(code=opcode) - # Kept under the EIP-7825 transaction gas limit cap: above it, EIP-8037 - # turns the excess into a state gas reservoir that a halt leaves intact. - gas_limit = 1_000_000 + # One gas more than the code needs, so a normal halt refunds exactly + # that gas while an exceptional halt consumes it with the rest. + execution_gas = ( + fork.transaction_intrinsic_cost_calculator()() + opcode.gas_cost(fork) + ) + gas_limit = execution_gas + 1 tx = Transaction( gas_limit=gas_limit, to=contract_address, sender=pre.fund_eoa(), expected_receipt=TransactionReceipt( status=int(success), - cumulative_gas_used=gas_limit if all_gas_consumed else None, + cumulative_gas_used=( + gas_limit if all_gas_consumed else execution_gas + ), ), ) @@ -74,93 +82,61 @@ def test_top_level_call( @pytest.mark.parametrize( - "opcode,success", + "target,valid_jump", [ - pytest.param(Op.EXTENSION, False), - pytest.param(Op.INVALID, False), pytest.param(Op.JUMPDEST, True), + pytest.param(Op.PUSH1(0x5B), False, id="push_data_0x5b"), + ], +) +@pytest.mark.parametrize( + "following", + [ + pytest.param(Bytecode(), id="nothing"), + Op.STOP, + Op.ADD, + Op.JUMPDEST, + pytest.param(Op.PUSH1(0), id="PUSH1"), + pytest.param(Op.PUSH32(0), id="PUSH32"), + Op.EXTENSION, + Op.SELFDESTRUCT, ], ) -@pytest.mark.parametrize("stack_item", [0, 1]) -def test_execute_with_stack( - state_test: StateTestFiller, - pre: Alloc, - opcode: Op, - success: bool, - stack_item: int, -) -> None: - """ - Execute the tested byte with 256 items of value 0 or 1 on the - stack. - - EXTENSION behaves as INVALID, JUMPDEST as sanity check. - """ - push = Op.PUSH0 if stack_item == 0 else Op.PUSH1(stack_item) - code = Op.SSTORE(slot_code_worked, value_code_worked) + push * 256 + opcode - contract_address = pre.deploy_contract(code=code) - - tx = Transaction(to=contract_address, sender=pre.fund_eoa()) - - storage = {slot_code_worked: value_code_worked} if success else {} - state_test( - pre=pre, - post={contract_address: Account(storage=storage)}, - tx=tx, - ) - - -@pytest.mark.parametrize("valid_jump", [True, False]) -@pytest.mark.parametrize("following_byte", [None, *range(256)]) def test_jumpdest_analysis_neutrality( state_test: StateTestFiller, pre: Alloc, + following: Bytecode, + target: Bytecode, valid_jump: bool, - following_byte: int | None, ) -> None: """ Jump over an EXTENSION byte to a destination right behind it. JUMPDEST analysis ignores EXTENSION: a JUMPDEST behind EXTENSION is a valid destination and a 0x5b held as PUSH1 data behind - EXTENSION is not. EXTENSION is never executed. The optional byte - between EXTENSION and the destination covers all values, PUSH - opcodes with non-truncated data, to show none of them acts as an - EXTENSION immediate during the analysis. + EXTENSION is not. EXTENSION is never executed. Only JUMPDEST, the + PUSH opcodes and EXTENSION itself matter to the analysis of the + byte behind EXTENSION; every other byte is data to it. """ - following = b"" - if following_byte is not None: - following = bytes([following_byte]) - if 0x60 <= following_byte <= 0x7F: - push_data_size = following_byte - 0x5F - following += b"\x00" * push_data_size - - sentinel = Op.SSTORE(slot_code_worked, value_code_worked) - destination = len( - sentinel + Op.PUSH2(0) + Op.JUMP + Op.EXTENSION + following - ) - target: Bytecode - if valid_jump: - target = Op.JUMPDEST - else: - # point at the 0x5b held as PUSH1 data - destination += 1 - target = Op.PUSH1(0x5B) code = ( - sentinel - + Op.PUSH2(destination) - + Op.JUMP + Op.SSTORE(slot_code_worked, value_code_worked) + + Op.JUMP(pc=Op.PUSH2(data_placeholder="destination")) + Op.EXTENSION + following + target ) - contract_address = pre.deploy_contract(code=code) + code.substitute(destination=len(code) - 1) + + contract_address = pre.deploy_contract( + code=code, + storage={slot_code_worked: value_code_untouched}, + ) tx = Transaction(to=contract_address, sender=pre.fund_eoa()) - storage = {slot_code_worked: value_code_worked} if valid_jump else {} + value = value_code_worked if valid_jump else value_code_untouched state_test( pre=pre, - post={contract_address: Account(storage=storage)}, + post={contract_address: Account(storage={slot_code_worked: value})}, tx=tx, ) @@ -173,42 +149,47 @@ def test_jumpdest_analysis_neutrality( pytest.param(Op.JUMPDEST, True), ], ) -@pytest.mark.parametrize("stack_item", [0, 1]) @pytest.mark.parametrize( - "following_byte", - [pytest.param(b, id=f"0x{b:02x}") for b in [0x5B, *range(0x60, 0x80)]] - + [None], + "following", + [ + pytest.param(bytes([b]), id=f"0x{b:02x}") + for b in [0x5B, *range(0x60, 0x80)] + ] + + [pytest.param(b"", id="nothing")], ) def test_solo_extension_bytes( state_test: StateTestFiller, pre: Alloc, opcode: Op, success: bool, - stack_item: int, - following_byte: int | None, + following: bytes, ) -> None: """ Execute the tested byte followed by a solo 0x5b or 0x60..0x7f byte (or nothing), expect it to halt exceptionally always. EIP-8163 rules these out as single-byte extension immediates. + The stack is filled first, so the halt is known not to require an + empty stack. EXTENSION behaves as INVALID, JUMPDEST as sanity check. """ - push = Op.PUSH0 if stack_item == 0 else Op.PUSH1(stack_item) code = ( Op.SSTORE(slot_code_worked, value_code_worked) - + push * 256 + + Op.PUSH1(1) * 256 + opcode - + bytes([following_byte] if following_byte is not None else []) + + following + ) + contract_address = pre.deploy_contract( + code=code, + storage={slot_code_worked: value_code_untouched}, ) - contract_address = pre.deploy_contract(code=code) tx = Transaction(to=contract_address, sender=pre.fund_eoa()) - storage = {slot_code_worked: value_code_worked} if success else {} + value = value_code_worked if success else value_code_untouched state_test( pre=pre, - post={contract_address: Account(storage=storage)}, + post={contract_address: Account(storage={slot_code_worked: value})}, tx=tx, ) From 2dab627a1a7cac14896c440bb2eb3d21754c13ae Mon Sep 17 00:00:00 2001 From: pdobacz <5735525+pdobacz@users.noreply.github.com> Date: Wed, 26 Aug 2026 08:12:51 +0000 Subject: [PATCH 4/4] chore(doc): add EIP-8163 EXTENSION opcode to the EVM lists Register 0xAE in the pending and proposed opcode lists. Co-Authored-By: Claude Opus 5 --- lists/evm/pending-opcodes.md | 3 ++- lists/evm/proposed-opcodes.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lists/evm/pending-opcodes.md b/lists/evm/pending-opcodes.md index 300630c0aa9..27224302291 100644 --- a/lists/evm/pending-opcodes.md +++ b/lists/evm/pending-opcodes.md @@ -11,6 +11,7 @@ next or subsequent hard fork. | 0x5C | TLOAD | Transient data load | [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) | | 0x5D | TSTORE | Transient data store | [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) | | 0x5E | MCOPY | Memory copy | [EIP-5656](https://eips.ethereum.org/EIPS/eip-5656) | +| 0xAE | EXTENSION | Extension prefix for non-Ethereum-L1 EVM chains | [EIP-8163](https://eips.ethereum.org/EIPS/eip-8163) | | 0xD0 | DATALOAD | Loads data from EOF data section, via stack | [EIP-7480](https://eips.ethereum.org/EIPS/eip-7480) | | 0xD1 | DATALOADN | Loads data from EOF data section, via immediate | [EIP-7480](https://eips.ethereum.org/EIPS/eip-7480) | | 0xD2 | DATASIZE | Size of the EOF data section | [EIP-7480](https://eips.ethereum.org/EIPS/eip-7480) | @@ -222,7 +223,7 @@ scheduled or accepted) are in *italics*. | 0xAB | | | | | | 0xAC | | | | | | 0xAD | | | | | -| 0xAE | | | | | +| *0xAE* | *EXTENSION* | *System* | *Bogota* | *[EIP-8163](https://eips.ethereum.org/EIPS/eip-8163)* | | 0xAF | | | | | | 0xB0 | | | | | | 0xB1 | | | | | diff --git a/lists/evm/proposed-opcodes.md b/lists/evm/proposed-opcodes.md index 5692aedc230..2f1dcd71ba5 100644 --- a/lists/evm/proposed-opcodes.md +++ b/lists/evm/proposed-opcodes.md @@ -79,3 +79,4 @@ unshipped EIPs, even withdrawn and non-viable proposals. | [EIP-7620](https://eips.ethereum.org/EIPS/eip-7620) | 0xEC | EOFCREATE | Create from EOF contained initcode | | [EIP-7620](https://eips.ethereum.org/EIPS/eip-7620) | 0xED | TXCREATE | Create from transaction contained initcode (removed from EIP-7620) | | [EIP-7620](https://eips.ethereum.org/EIPS/eip-7620) | 0xEE | RETURNCONTRACT | Contract to be created, references EOF data | +| [EIP-8163](https://eips.ethereum.org/EIPS/eip-8163) | 0xAE | EXTENSION | Extension prefix for non-Ethereum-L1 EVM chains |