Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EIP: EOF - Creation transaction #8498

Merged
merged 2 commits into from
May 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions EIPS/eip-7698.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
eip: 7698
title: EOF - Creation transaction
description: Deploy EOF contracts using creation transactions
author: Piotr Dobaczewski (@pdobacz), Andrei Maiboroda (@gumb0), Paweł Bylica (@chfast), Alex Beregszaszi (@axic)
discussions-to: https://ethereum-magicians.org/t/eip-7698-eof-creation-transaction/19784
status: Draft
type: Standards Track
category: Core
created: 2024-04-24
requires: 3540, 7620
---

## Abstract

Creation transactions (i.e. the ones with empty `to`) can be used to deploy EOF contracts by providing EOF initcontainer concatenated with `calldata` for initcontainer execution in transaction's `data`. Initcontainer execution is similar to its execution during `EOFCREATE` instruction, ending with `RETURNCONTRACT` instruction. New account address calculation is based on sender's address and nonce.

## Motivation

Creation transaction is one if the three ways alongside creation instructions provided by legacy EVM to deploy new code. Given that legacy creation instructions (`CREATE` and `CREATE2`) are not allowed to deploy EOF code, supporting EOF in creation transactions is the only way to get the first EOF on-chain.

The mechanism for providing constructor arguments to initcontainer is exactly the same as for deploying legacy code (just concatenating them with initcontainer), therefore existing deployment tooling can be used as is to deploy EOF.

## Specification

### Parameters

| Constant | Value |
| - | - |
| `EOF_MAGIC` | Defined as `0xEF00` in [EIP-3540](./eip-3540.md) |
| `MAX_CODE_SIZE` | Defined as `24576` in [EIP-170](./eip-170.md) |


In case a creation transaction (transaction with empty `to`) has `data` starting with `EOF_MAGIC`, `data` is interpreted as a concatenation of EOF `initcontainer` and `calldata`. More specifically:

1. Intrinsic gas cost rules and limits defined in [EIP-3860](./eip-3860.md) for creation transactions apply. The entire `data` of the transaction is used for these calculations.
2. Find the split of `data` into `initcontainer` and `calldata`:

- Parse EOF header
- Find `intcontainer` size by reading all section sizes from the header and adding them up with the header size to get the full container size.

3. Validate the `initcontainer` and all its subcontainers recursively.

- Unlike in general validation, `initcontainer` is additionally required to have `data_size` declared in the header equal to actual `data_section` size.

4. If EOF header parsing or full container validation fails, transaction is considered valid and failing. Gas for initcode execution is not consumed, only intrinsic creation transaction costs are charged.
5. `calldata` part of transaction `data` that follows `initcontainer` is treated as calldata to pass into the execution frame.
6. Execute the container in "initcode-mode" (see [EIP-7620](./eip-7620.md)) and deduct gas for execution.
1. Calculate `new_address` as `keccak256(sender || sender_nonce)[12:]`
2. A successful execution ends with initcode executing `RETURNCONTRACT{deploy_container_index}(aux_data_offset, aux_data_size)` instruction. After that:
- load deploy-contract from EOF subcontainer at `deploy_container_index` in the container from which `RETURNCONTRACT` is executed,
- concatenate data section with `(aux_data_offset, aux_data_offset + aux_data_size)` memory segment and update data size in the header,
- let `deployed_code_size` be updated deploy container size,
- if `deployed_code_size > MAX_CODE_SIZE` instruction exceptionally aborts,
- set `state[new_address].code` to the updated deploy container.
3. `RETURN` and `STOP` are not allowed in "initcode-mode" (abort execution)
7. Deduct `200 * deployed_code_size` gas.

## Rationale

### Irregular state change to deploy Creator Contract

Originally it was proposed to deploy the first EOF contract via irregular state change. This contract would execute `TXCREATE` instruction and could be used then as an entry point to deploy any other EOF code. This would also require an introduction of `InitcodeTransaction`, required by `TXCREATE`. It was decided against this variant for the benefit of reduced scope of changes.

### Constructor arguments outside of initcontainer vs in data section

Alternative mechanism for providing constructor arguments to initcontainer execution was considered, where they are concatenated with data section of the initcontainer and are accessed via `DATA*` instructions instead of `CALLDATA*`. This has a benefit of not requiring the step finding the split of `transaction.data` into `initcontainer` and `calldata`, as entire `transaction.data` is an EOF container. However it was rejected for the following reasons:

- Existing tooling could not be used for deploying EOF without modification. To construct EOF creation transaction, the tooling would need to append constructor arguments to the container, as well as update data section size in the EOF header. Compiler could predict the size of constructor arguments to put the anticipated data size in the header, but it would not be possible for variadic length constructor arguments.
- In case a specialized EOF creation transaction is introduced in a later upgrade (such as `InitcodeTransaction` defined in [EIP-7620](./eip-7620.md)), it would have a dedicated field for initcontainer execution input (`calldata`), and it will be accessed with `CALLDATA*` instructions in initcode. It is better to avoid the situation where compilers would need to generate initcontainer code differently depending on which context it will be used in.
- As a general argument, data section can be seen to contain the data that execution considers validated and being closely coupled with the code definition, whereas calldata is an input from the outside that may be arbitrary and not validated.

## Backwards Compatibility

Creation transactions deploying legacy code are not affected, because any such transaction starting with `EF` byte previously would fail on executing invalid instruction.

## Security Considerations

TBA

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).
Loading