MIP-7: Extension Opcodes

This MIP proposes a generic scheme by which new opcodes can be added to the Monad VM, while minimising the risk of collisions with future Ethereum changes.

1 Like

Disclaimer: I’m currently analyzing the JUMPDEST situation, and might propose a different approach to it (that there are reasons for the extension opcode to be JUMPDEST-analysis neutral).

This is more of an editorial suggestion to current approach:

In the Jumpdest Analysis section, the rule is too weak. In current form 0xEE605B would cause the 0x5B to be an invalid jump destination. I think it should read:

As for PUSH1 opcode, an immediate data byte following a 0xEE byte is skipped over during JUMPDEST analysis.

In particular:

  1. In 0xEE5B the 0x5B is not a valid jump destination
  2. In 0xEE605B the 0x5B is a valid jump destination
  3. In 0xEE615B5Bboth 0x5B’s are valid jump destinations etc.

For completeness: we’re unfortunate EIP-8024 is considered for Amsterdam, complicating things. If it goes in, 0xE6EE5B, 0xEEE65B (and similar) must be dealt with.

I would recommend that an EIP-8024-like approach to JUMPDEST-analysis is taken.

Problem statement

Let’s call the current approach “JUMPDEST-analysis expanding”, because we’re expanding the rules of the analysis, to cover 0xEE immediate arguments.

The interaction of current JUMPDEST-analysis expanding MIP-7 and EIP-8024 is broken:

Consider the bytecode: 0xE6 0xEE 0x60 0x5B. Here we compare how its JUMPDEST analysis and execution unfold:

EVM Jumpdest Analysis Execution
Osaka 0x5B is an invalid jumpdest as it is a PUSH1 argument: JDâś— invalid, invalid, PUSH1 0x5B
EIP-8024 0x5B is an invalid jumpdest as it is a PUSH1 argument: JDâś— DUPN-0xEE (valid), PUSH1-0x5B
MIP-7 0xEE skips 0x60 making 0x5B a valid jump destination: JDâś“ invalid, EXTENSION-0x60, JUMPDEST
Both 0xEE skips 0x60 making 0x5B a valid jump destination: JDâś“ DUPN-0xEE (valid), PUSH1-0x5B

Osaka and MIP-7 rows are less of a concern, as they contain invalid operation in the bytecode. However, code which is correct under EIP-8024 and executes as a DUPN-0xEE and PUSH1-0x5B, with the argument of the push being an invalid jump destination, becomes something different when combined with MIP-7.

A more severe variant is 0xE6 0xEE 0x60 0x60 0x5B, where MIP-7 causes the jump destination to vanish. 0xE6 0xEE 0x7F ... 0x5B demonstrates that the effect can cascade across the entire remainder of the bytecode.

Proposed solution

In general, let’s declare that the extension opcode 0xEE (in MIP-7 but also in whatever EIP we’re going to put up) is not altering JUMPDEST analysis in any way, that is, the set of valid jump destinations remains the same with or without MIP-7, for all bytecodes.

One way to do this is to adopt the approach EIP-8024 is taking, discussed as 2.2.1 in here. The advantages of this are:

  1. Increases the chance of success of the MIP-7’s EIP counterpart, because it dodges the subject of backwards comptibility of JUMPDEST-analysis, just like EIP-8024 did
  2. Increases the cross-compatiblity of the bytecode between EVMs adopting MIP-7 and others. Imagine bytecode which is aware of the EVM it’s running in (think a bundler which runs a hypothetical 0xEE-0x60 combo on a chain which recognizes this extension and jumps over it otherwise). It would not work cross chain if 0xEE 0x60 0x5B combination was treated with expanded JUMPDEST-analysis
  3. Consistent with EIP-8024, which I assume Monad is going to adopt anyway, if it goes into Amsterdam
  4. Still bytecode-efficient compared to 2.2.3 in here, and cleaner than 2.2.2 therein

In case >1byte immediate arguments are needed (or variadic) for the extension, approach 2.2.3 in here still can be used. MIP-7’s EIP counterpart may not prescribe the concrete variant, but it should require that the extension opcode doesn’t alter JUMPDEST analysis generally.

Added a proposal to MIP-7 to update and align with EIP-8163: Reserve EXTENSION (0xae) opcode