diff --git a/EIPS/eip-3670.md b/EIPS/eip-3670.md index ed22ebfcd5bee..42c443f44e8af 100644 --- a/EIPS/eip-3670.md +++ b/EIPS/eip-3670.md @@ -12,17 +12,17 @@ requires: 3540 ## Abstract -Introduce code validation at contract creation time for EOF formatted ([EIP-3540](./eip-3540.md)) contracts. Reject contracts which contain truncated `PUSH`-data or unassigned instructions. Legacy bytecode is unaffected by this change. +Introduce code validation at contract creation time for EOF formatted ([EIP-3540](./eip-3540.md)) contracts. Reject contracts which contain truncated `PUSH`-data or undefined instructions. Legacy bytecode (code which is not EOF formatted) is unaffected by this change. ## Motivation -Currently existing contracts require no validation of correctness and EVM implementations can decide how they handle truncated bytecode or unassinged instructions. This change aims to bring code validity into consensus, so that it becomes easier to reason about bytecode. Moreover, EVM implementations may require less paths to decide which instruction is valid in the current execution context. +Currently existing contracts require no validation of correctness and EVM implementations can decide how they handle truncated bytecode or undefined instructions. This change aims to bring code validity into consensus, so that it becomes easier to reason about bytecode. Moreover, EVM implementations may require less paths to decide which instruction is valid in the current execution context. -If it will be desired to introduce new instructions without bumping EOF version, having unassigned instructions already deployed would mean such contracts potentially can be broken (since some of the instructions are changing their behaviour). Rejecting to deploy unassigned instructions allows introducing new instructions with or without bumping the EOF version. +If it will be desired to introduce new instructions without bumping EOF version, having undefined instructions already deployed would mean such contracts potentially can be broken (since some of the instructions are changing their behaviour). Rejecting to deploy undefined instructions allows introducing new instructions with or without bumping the EOF version. ## Specification -*Remark:* We rely on the notation of *initcode*, *code* and *creation* as defined by EIP-3540. +*Remark:* We rely on the notation of *initcode*, *code* and *creation* as defined by [EIP-3540](./eip-3540.md). This feature is introduced on the very same block EIP-3540 is enabled, therefore every EOF1-compatible bytecode MUST be validated according to these rules. @@ -67,7 +67,7 @@ def validate_code(code: bytes): pos += 1 assert(opcode in valid_opcodes) - # Skip pushdata -- over-reading will be checked on next iteration + # Skip pushdata if opcode >= 0x60 and opcode <= 0x7f: pos += opcode - 0x60 + 1 @@ -77,11 +77,31 @@ def validate_code(code: bytes): ## Test Cases -TBA +#### Contract creation + +Each case should be tested for creation transaction, `CREATE` and `CREATE2`. + +- Invalid initcode +- Valid initcode returning invalid code +- Valid initcode returning valid code + +#### Valid codes + +- EOF code containing `INVALID` +- EOF code with a code section ending with `PUSH` instruction followed by correct number of bytes of data +- EOF code with data section containing bytes that are undefined instructions +- Legacy code containing undefined instruction +- Legacy code ending with incomplete PUSH instruction + +#### Invalid codes + +- EOF code containing undefined instruction +- EOF code ending with incomplete `PUSH` instruction + - This can include `PUSH` instruction unreachable by execution, e.g. after `STOP` ## Backwards Compatibility -This change poses no risk to backwards compatibility, as it is introduced at the same time EIP-3540 is. The validation does not cover legacy bytecode. +This change poses no risk to backwards compatibility, as it is introduced at the same time EIP-3540 is. The validation does not cover legacy bytecode (code which is not EOF formatted). ## Security Considerations