|
| 1 | +--- |
| 2 | +rskip: 544 |
| 3 | +title: Reject new contract code starting with the `0xEF` byte |
| 4 | +description: Implements EIP-3541 |
| 5 | +status: Draft |
| 6 | +purpose: Usa |
| 7 | +author: PDG (@patogallaiovlabs), SM (@smishraiov) |
| 8 | +layer: Core |
| 9 | +complexity: 1 |
| 10 | +created: 2026-01-05 |
| 11 | +--- |
| 12 | + |
| 13 | +| RSKIP | 544 | |
| 14 | +| --- | --- | |
| 15 | +| **Title** | Reject new contract code starting with the `0xEF` byte| |
| 16 | +| **Created** | 05-JAN-2026 | |
| 17 | +| **Author** | Patricio Gallardo, Shreemoy Mishra | |
| 18 | +| **Purpose** | Usa | |
| 19 | +| **Layer** | Core | |
| 20 | +| **Complexity** | 1 | |
| 21 | +| **Status** | Draft | |
| 22 | + |
| 23 | +## Abstract |
| 24 | + |
| 25 | +Implement [EIP-3541](https://eips.ethereum.org/EIPS/eip-3541) to disallow deployment of new contract starting with the `0xEF` byte. Code already existing in the account trie starting with `0xEF` byte is not affected semantically by this change. |
| 26 | + |
| 27 | +## Motivation |
| 28 | + |
| 29 | +Our motivation deviates from the original intent of EIP-3541. In the original EIP-3541, `0xEF` was meant to represent the first byte of a “magic sequence” for later use in the development of the EVM Object Format (EOF). The authors of [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) (for Account Abstraction) repurposed the use of this sequence format to denote EOA’s that choose to *inject code* into their account space. This is why EIP-3541 was a pre-requisite for EIP-7702. Thus, our primary motivation in this proposal is to pre-emptively satisfy this pre-requisite for any future proposal to implement EIP-7702 on Rootstock. This RSKIP is intended to follow EIP-3541 very closely, and large sections of the text are replicated from that proposal. |
| 30 | + |
| 31 | +## Specification |
| 32 | + |
| 33 | +Once this RKSIP is adopted, new contract creation (via create transaction, or via `CREATE` or `CREATE2` instructions) results in an exceptional abort if the deployed *code*’s first byte is `0xEF`. |
| 34 | + |
| 35 | +The *initcode* is the code executed in the context of the *create* transaction, `CREATE`, or `CREATE2` instructions. The *initcode* returns *code* (via the `RETURN` instruction), which is inserted into the account. |
| 36 | + |
| 37 | +The opcode `0xEF` is currently an undefined instruction in RSKJ’s. It pops no stack items and pushes no stack items, and it causes an exceptional abort when executed. This means *initcode* or already deployed *code* starting with this instruction will continue to abort execution. |
| 38 | + |
| 39 | +The exceptional abort due to *code* starting with `0xEF` behaves exactly the same as any other exceptional abort that can occur during *initcode* execution, i.e. in case of abort all gas provided to a `CREATE*` or create transaction is consumed. |
| 40 | + |
| 41 | +### Activation |
| 42 | + |
| 43 | +Todo: Block height at which activated is TBD |
| 44 | + |
| 45 | +## Implementation |
| 46 | + |
| 47 | +Todo: There is no implementation of this proposal at present |
| 48 | + |
| 49 | +## Rationale |
| 50 | + |
| 51 | +Contracts using unassigned opcodes are generally understood to be at risk of changing semantics. Hence using the unassigned `0xEF` should have lesser effects, than choosing an assigned opcode, such as `0xFD` (`REVERT`), `0xFE` (`INVALID`), or `0xFF` (`SELFDESTRUCT`). Arguably while such contracts may not be very useful, they are still using valid opcodes. |
| 52 | + |
| 53 | +## Backward compatibility |
| 54 | + |
| 55 | +This change is a hard-fork and therefore all full nodes must be updated. SPV light-clients do not need to be updated. |
| 56 | + |
| 57 | +## **Test Cases** |
| 58 | + |
| 59 | +Each test case below may be executed in 3 different contexts: |
| 60 | + |
| 61 | +- create transaction (no account code) |
| 62 | +- `CREATE`, with account code: `0x6000356000523660006000f0151560165760006000fd5b` (Yul code: `mstore(0, calldataload(0)) if iszero(create(0, 0, calldatasize())) { revert(0, 0) }`), |
| 63 | +- `CREATE2`, with account code: `0x60003560005260003660006000f5151560185760006000fd5b` (Yul code: `mstore(0, calldataload(0)) if iszero(create2(0, 0, calldatasize(), 0)) { revert(0, 0) }`) |
| 64 | + |
| 65 | +| Case | Calldata | Expected result | |
| 66 | +| --- | --- | --- | |
| 67 | +| deploy one byte `ef` | `0x60ef60005360016000f3` | new contract not deployed, transaction fails | |
| 68 | +| deploy two bytes `ef00` | `0x60ef60005360026000f3` | new contract not deployed, transaction fails | |
| 69 | +| deploy three bytes `ef0000` | `0x60ef60005360036000f3` | new contract not deployed, transaction fails | |
| 70 | +| deploy 32 bytes `ef00...00` | `0x60ef60005360206000f3` | new contract not deployed, transaction fails | |
| 71 | +| deploy one byte `fe` | `0x60fe60005360016000f3` | new contract deployed, transaction succeeds | |
| 72 | + |
| 73 | +## References |
| 74 | + |
| 75 | +\[1] [EIP-3541](https://eips.ethereum.org/EIPS/eip-3541) |
| 76 | + |
| 77 | +\[2] [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) |
| 78 | + |
| 79 | +## Copyright |
| 80 | + |
| 81 | +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
0 commit comments