Skip to content

Commit

Permalink
Update EIP-7620: Expand the Rationale section & clarifications
Browse files Browse the repository at this point in the history
Merged by EIP-Bot.
  • Loading branch information
pdobacz authored Apr 18, 2024
1 parent e6ef267 commit e13a1a5
Showing 1 changed file with 32 additions and 3 deletions.
35 changes: 32 additions & 3 deletions EIPS/eip-7620.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,10 @@ Details on each instruction follow in the next sections.

- deduct `TX_CREATE_COST` gas
- read immediate operand `initcontainer_index`, encoded as 8-bit unsigned value
- pop `value`, `salt`, `data_offset`, `data_size` from the operand stack
- pop `value`, `salt`, `input_offset`, `input_size` from the operand stack
- peform (and charge for) memory expansion using `[input_offset, input_size]`
- load initcode EOF subcontainer at `initcontainer_index` in the container from which `EOFCREATE` is executed
- let `initcontainer_size` be the declared size of that EOF subcontainer in its parent container header
- deduct `GAS_KECCAK256_WORD * ((initcontainer_size + 31) // 32)` gas (hashing charge)
- check that current call depth is below `STACK_DEPTH_LIMIT` and that caller balance is enough to transfer `value`
- in case of failure return 0 on the stack, caller's nonce is not updated and gas for initcode execution is not consumed.
Expand All @@ -128,10 +130,12 @@ Details on each instruction follow in the next sections.
#### `TXCREATE`

- deduct `TX_CREATE_COST` gas
- pop `tx_initcode_hash`, `value`, `salt`, `data_offset`, `data_size` from the operand stack
- pop `tx_initcode_hash`, `value`, `salt`, `input_offset`, `input_size` from the operand stack
- peform (and charge for) memory expansion using `[input_offset, input_size]`
- load initcode EOF container from the transaction `initcodes` array which hashes to `tx_initcode_hash`
- fails (returns 0 on the stack) if such initcode does not exist in the transaction, or if called from a transaction of `TransactionType` other than `INITCODE_TX_TYPE`
- caller's nonce is not updated and gas for initcode execution is not consumed. Only `TXCREATE` constant gas was consumed
- let `initcontainer_size` be the length of that EOF container in bytes
- deduct `INITCODE_WORD_COST * ((initcontainer_size + 31) // 32)` gas
- deduct `GAS_KECCAK256_WORD * ((initcontainer_size + 31) // 32)` gas (hashing charge)
- check that current call depth is below `STACK_DEPTH_LIMIT` and that caller balance is enough to transfer `value`
Expand All @@ -146,7 +150,9 @@ Details on each instruction follow in the next sections.

These steps are common for `EOFCREATE` and `TXCREATE`:

- execute the container in "initcode-mode" and deduct gas for execution
- caller's memory slice [`input_offset`:`input_size`] is used as calldata
- execute the container in "initcode-mode" and deduct gas for execution. The 63/64th rule from [EIP-150](./eip-150.md) applies.
- increment `sender` account's nonce
- calculate `new_address` as `keccak256(0xff || sender || salt || keccak256(initcontainer))[12:]`
- an unsuccesful execution of initcode results in pushing `0` onto the stack
- can populate returndata if execution `REVERT`ed
Expand All @@ -157,6 +163,7 @@ These steps are common for `EOFCREATE` and `TXCREATE`:
- set `state[new_address].code` to the updated deploy container
- push `new_address` onto the stack
- `RETURN` and `STOP` are not allowed in "initcode-mode" (abort execution)
- "initcode-mode" *is not transitive* - it is only active for the frame executing the initcontainer. If another (non-create) call is made from this frame, it *is not* executed in "initcode-mode".

#### `RETURNCONTRACT`

Expand Down Expand Up @@ -244,18 +251,40 @@ function txcreate(a, b, c, d, e) -> f {

## Rationale

### Data section appending

The data section is appended to during contract creation and also its size needs to be updated in the header. Alternative designs were considered, where:

- additional section kinds for the data were introduced
- additional fields describing a subcontainer were introduced
- data section would be written over as opposed to being appended to, requiring it to be filled with 0 bytes prior to deployment

All of these alternatives either complicated the otherwise simple data structures or took away useful features (like the dynamically sized portion of the data section).

### `TXCREATE`

An alternative design was discussed, where instead of `TXCREATE`, `InitcodeTransaction` and the Creator Contract, the legacy-like creation transactions (with empty `to`) continue to be available to send EOF initcontainers in transactions and perform deployment of EOF contracts.

This makes it impossible for smart contract wallets to deploy arbitrary contracts (only EOAs can), which is a desired feature of current legacy creation rules. A workaround where those arbitrary contracts are first "uploaded" to a factory contract, and then deployed using `EOFCREATE`, is not satisfactory.

### `TXCREATE` failure modes

`TXCREATE` has two "light" failure modes in case the initcontainer is not present and in case the EOF validation is unsuccessful. An alternative design where both cases led to a "hard" failure (consuming the entire gas available) was considered. We decided to have the more granular and forgiving failure modes in order to align the gas costs incurred to the actual work the EVM performs.

### Creator Contract

EOF contract creation requires the Creator Contract be introduced via a state change, because neither legacy contracts nor create transactions can deploy EOF code. The alternative approach which was to continue using legacy creation would still rely on fetching the *initcode* from memory and not satisfy the requirement of code non-observability.

### EOF validation checking initcode-mode

Extra EOF validation rules were considered:

- Each EOF subcontainer must either be referenced by an `EOFCREATE` or a `RETURNCONTRACT` instruction, but never both
- Each EOF subcontainer may either contain `RETURNCONTRACT` or `RETURN` / `STOP` instructions, but never a mix of these two kinds
- A subcontainer referenced by an `EOFCREATE` must never contain a `RETURN` / `STOP` instruction, whereas a subcontainer referenced by a `RETURNCONTRACT` must never contain a `RETURNCONTRACT`

These rules were not adopted to avoid the extra logic and complexity (esp. the last rule causes EOF validation of subcontainers to not be self-contained).

## 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), and the contract creation options do not change for legacy bytecode.
Expand Down

0 comments on commit e13a1a5

Please sign in to comment.