diff --git a/EIPS/eip-4200.md b/EIPS/eip-4200.md index 30d75c2df141ed..7ca92bd8c0ba1a 100644 --- a/EIPS/eip-4200.md +++ b/EIPS/eip-4200.md @@ -1,7 +1,7 @@ --- eip: 4200 title: EOF - Static relative jumps -description: RJUMP and RJUMPI instructions with a signed immediate encoding the jump destination +description: RJUMP, RJUMPI and RJUMPV instructions with a signed immediate encoding the jump destination author: Alex Beregszaszi (@axic), Andrei Maiboroda (@gumb0), Paweł Bylica (@chfast) discussions-to: https://ethereum-magicians.org/t/eip-3920-static-relative-jumps/7108 status: Review @@ -39,17 +39,21 @@ We introduce two new instructions on the same block number [EIP-3540](./eip-3540 1. `RJUMP` (0x5c) 2. `RJUMPI` (0x5d) +3. `RJUMPV` (0x5e) -If the code is legacy bytecode, both of these instructions result in an *exceptional halt*. (*Note: This means no change to behaviour.*) +If the code is legacy bytecode, all of these instructions result in an *exceptional halt*. (*Note: This means no change to behaviour.*) If the code is valid EOF1: -1. `RJUMP relative_offset` (0x5c), sets the `PC` to `PC_post_instruction + relative_offset`. -2. `RJUMPI relative_offset` (0x5d), pops a value (`condition`) from the stack, and sets the `PC` to `PC_post_instruction + ((condition == 0) ? 0 : relative_offset)`. +1. `RJUMP relative_offset` sets the `PC` to `PC_post_instruction + relative_offset`. +2. `RJUMPI relative_offset` pops a value (`condition`) from the stack, and sets the `PC` to `PC_post_instruction + ((condition == 0) ? 0 : relative_offset)`. +3. `RJUMPV count relative_offset+` pops a value (`case`) from the stack, and sets the `PC` to `PC_post_instruction + ((case >= count) ? 0 : relative_offset[case])`. The immediate argument `relative_offset` is encoded as a 16-bit **signed** (two's-complement) big-endian value. Under `PC_post_instruction` we mean the `PC` position after the entire immediate value. -We also extend the validation algorithm of [EIP-3670](./eip-3670.md) to verify that each `RJUMP`/`RJUMPI` has a `relative_offset` pointing to an instruction. This means it cannot point to an immediate data of `PUSHn`/`RJUMP`/`RJUMPI`. It cannot point outside of code bounds. It is allowed to point to a `JUMPDEST`, but is not required to. +The immediate encoding of `RJUMPV` is more special: the 8-bit `count` value incremented by 1 determines the number of `relative_offset` values following. Based on this it can be seen that the encoding of `RJUMPV` must have at least one `relative_offset` and thus it will take at minimum 4 bytes. Furthermore, the `case >= count` condition falling through means that in many use cases one would place the *default* path following the `RJUMPV` instruction. + +We also extend the validation algorithm of [EIP-3670](./eip-3670.md) to verify that each `RJUMP`/`RJUMPI`/`RJUMPV` has a `relative_offset` pointing to an instruction. This means it cannot point to an immediate data of `PUSHn`/`RJUMP`/`RJUMPI`. It cannot point outside of code bounds. It is allowed to point to a `JUMPDEST`, but is not required to. Because the destinations are validated upfront, the cost of these instructions are less than their dynamic counterparts: `RJUMP` should cost 5, and `RJUMPI` should cost 7. This is a reduction of 2 gas, compared to `JUMP` and `JUMPI`. @@ -106,6 +110,10 @@ There are two benefits here: 1. Not wasting a byte for a `JUMPDEST` also means a saving of 200 gas during deployment, for each jump destination. 2. Saving an extra 1 gas per jump during execution, given `JUMPDEST` itself cost 1 gas and is "executed" during jumping. +### `RJUMPV` fallback case + +If no match is found (i.e. the *default* case) in the `RJUMPV` instruction execution will continue without branching. This allows for gaps in the arguments to be filled with `0`s, and a choice of implementation by the programmer. Alternate options would include exceptional aborts in case of no match. + ## Backwards Compatibility This change poses no risk to backwards compatibility, as it is introduced at the same time EIP-3540 is. The new instructions are not introduced for legacy bytecode (code which is not EOF formatted).