---
eip: 7873
title: EOF - TXCREATE and InitcodeTransaction type
description: Adds a `TXCREATE` instruction to EOF and an accompanying transaction type allowing to create EOF contracts from transaction data
author: Piotr Dobaczewski (@pdobacz), Andrei Maiboroda (@gumb0), Paweł Bylica (@chfast), Alex Beregszaszi (@axic), Danno Ferrin (@shemnon)
discussions-to: https://ethereum-magicians.org/t/eip-7873-eof-txcreate-instruction-and-initcodetransaction-type/22765
status: Stagnant
type: Standards Track
category: Core
created: 2025-01-31
requires: 3540, 3670, 3860, 7620
---

## Abstract

EVM Object Format (EOF) removes the possibility to create contracts using creation transactions (with an empty `to` field), `CREATE` or `CREATE2` instructions. We introduce a new instruction: `TXCREATE`, as well as a new transaction type (`InitcodeTransaction`), to provide a way to create contracts using EOF containers in transaction data.

## Motivation

This EIP uses terminology from the [EIP-3540](./eip-3540.md) which introduces the EOF format.

Creation transaction and creation instructions `CREATE` and `CREATE2` are means provided by legacy EVM to deploy new code, but per requirement of removing code observability, they are not allowed to deploy EOF code. To allow Externally Owned Accounts (EOAs) to deploy EOF contracts, there must be a way to create EOF contracts using bytecode delivered in transaction data.

Additionally, the new instruction and transaction type introduced in this EIP enable contracts to create other contracts using initcode from the transaction data, which in legacy EVM is achieved via a combination of `CREATE` or `CREATE2` and loading the initcode from calldata. 

This mechanism complements `EOFCREATE` and `RETURNCODE` instructions from [EIP-7620](./eip-7620.md), and thus all use cases of contract creation that are available in legacy EVM are enabled for EOF.

Since `TXCREATE` is not restricted to EOF containers, it also serves the purpose of bootstrapping EOF contracts into the state.

## Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Parameters

| Constant                    | Value                                                                                                                                                                                            |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `INITCODE_TX_TYPE`          | `Bytes1(0x06)`                                                                                                                                                                                   |
| `MAX_INITCODE_COUNT`        | `256`                                                                                                                                                                                            |
| `TX_CREATE_COST`            | Defined as `32000` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/fork_types.py#L42)    |
| `STACK_DEPTH_LIMIT`         | Defined as `1024` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/vm/interpreter.py#L60) |
| `GAS_CODE_DEPOSIT`          | Defined as `200` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/vm/gas.py#L44)          |
| `TX_DATA_COST_PER_ZERO`     | Defined as `4` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/fork_types.py#L41)        |
| `TX_DATA_COST_PER_NON_ZERO` | Defined as `16` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/fork_types.py#L40)       |
| `MAX_CODE_SIZE`             | Defined as `24576` in [EIP-170](./eip-170.md)                                                                                                                                                    |
| `MAX_INITCODE_SIZE`         | Defined as `2 * MAX_CODE_SIZE` in [EIP-3860](./eip-3860.md)                                                                                                                                      |

### Transaction Types

Introduce new transaction `InitcodeTransaction` (type `INITCODE_TX_TYPE`) which extends [EIP-1559](./eip-1559.md) (type 2) transaction by adding a new field `initcodes: List[ByteList[MAX_INITCODE_SIZE], MAX_INITCODE_COUNT]`.

The `initcodes` can only be accessed via the `TXCREATE` instruction (see below), therefore `InitcodeTransactions` are intended to be sent to contracts including `TXCREATE` in their execution.

#### Gas schedule

`initcodes` items data costs the same as calldata: transaction gas of an `InitcodeTransaction` is extended to include tokens in `initcodes` alongside tokens in `calldata`. Using the conventions from [EIP-7623](./eip-7623.md), the transaction gas is calculated as:

```python
STANDARD_TOKEN_COST = 4
TOTAL_COST_FLOOR_PER_TOKEN = 10

tokens_in_calldata = zero_bytes_in_calldata + nonzero_bytes_in_calldata * 4
tokens_in_initcodes = 0
for initcode in initcodes:
    tokens_in_initcodes += zero_bytes_in_initcode + nonzero_bytes_in_initcode * 4
tx.gasUsed = (
    21000
    +
    max(
        STANDARD_TOKEN_COST * (tokens_in_calldata + tokens_in_initcodes)
        + execution_gas_used,
        TOTAL_COST_FLOOR_PER_TOKEN * (tokens_in_calldata + tokens_in_initcodes)
    )
)
```


#### Transaction validation

- `InitcodeTransaction` is invalid if there are zero entries in `initcodes`, or if there are more than `MAX_INITCODE_COUNT` entries.
- `InitcodeTransaction` is invalid if any entry in `initcodes` is zero length, or if any entry exceeds `MAX_INITCODE_SIZE`.
- `InitcodeTransaction` is invalid if the `to` is `nil`.

Under transaction validation rules `initcodes` are not validated for conforming to the EOF specification. They are only validated when accessed via `TXCREATE`. This avoids potential DoS attacks of the mempool. If during the execution of an `InitcodeTransaction` no `TXCREATE` instruction is called, such transaction is still valid.

Other creation transactions that support contract creation (specifically type 0 "Frontier," type 1 "AccessList," type 2 "FeeMarket" transactions with an empty `to` field) will not attempt to parse EOF containers in their `input` field and will execute the code as non-EOF code. This will result in immediately executing the undefined `0xEF` instruction and halting.


#### RLP and signature

Given the definitions from [EIP-2718](./eip-2718.md) the `TransactionPayload` for an `InitcodeTransaction` is the RLP serialization of:

```
[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, initcodes, y_parity, r, s]
```

`TransactionType` is `INITCODE_TX_TYPE` and the signature values `y_parity`, `r`, and `s` are calculated by constructing a secp256k1 signature over the following digest:

```
keccak256(INITCODE_TX_TYPE || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, initcodes]))
```

The [EIP-2718](./eip-2718.md) `ReceiptPayload` for this transaction is `rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])`.

### Execution Semantics

Wherever not explicitly listed, the rules of EOF contract creation, as well as the `TXCREATE` instruction, should be identical or analogous to those of `CREATE2` instruction. This includes but is not limited to:

- behavior on `accessed_addresses` and address collision ([EIP-684](./eip-684.md) and [EIP-2929](./eip-2929.md))
- EVM execution frame created for the `TXCREATE` initcode - memory, account context etc.
- nonce bumping of the account of newly created contract [EIP-161](./eip-161.md)
- balance checking and transfer for the creation endowment (`value` argument)
    
Introduce a new instruction on the same block number [EIP-3540](./eip-3540.md) is activated on: `TXCREATE` (`0xed`).
    
#### `TXCREATE`
    
- deduct `TX_CREATE_COST` gas
- halt with exceptional failure if the current frame is in `static-mode`.
- pop `tx_initcode_hash`, `salt`, `input_offset`, `input_size`, `value` from the operand stack
- perform (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.
    - let `initcontainer` be that EOF container, and `initcontainer_size` its length in bytes
- 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.
- **validate the initcode container 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.
    - validation includes checking that the `initcontainer` does not contain `RETURN` or `STOP`
- fails (returns 0 on the stack) if container was invalid
    - caller’s nonce is not updated and gas for initcode execution is not consumed.
- caller's memory slice `[input_offset:input_size]` is used as calldata
- execute the container 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 || sender32 || salt)[12:]`, where `sender32` is the sender address left-padded to 32 bytes with zeros
- an unsuccessful execution of initcode results in pushing `0` onto the stack
    - can populate returndata if execution `REVERT`ed
    - `sender`'s nonce stays updated
- a successful execution ends with initcode executing `RETURNCODE{deploy_container_index}(aux_data_offset, aux_data_size)` instruction (see [EIP-7620](./eip-7620.md)). After that:
    - load deploy EOF subcontainer at `deploy_container_index` in the container from which `RETURNCODE` is executed
    - concatenate data section with `(aux_data_offset, aux_data_offset + aux_data_size)` memory segment and update data size in the header
    - if updated deploy container size exceeds `MAX_CODE_SIZE`, instruction exceptionally aborts
    - set `state[new_address].code` to the updated deploy container
    - push `new_address` onto the stack
- deduct `GAS_CODE_DEPOSIT * deployed_code_size` gas

Note that the implementations are expected to cache the result of container validation for the time of current transaction execution, and therefore the cost of each container's validation is sufficiently covered by `InitcodeTransaction` intrinsic cost (initcodes charge).

## Rationale

### `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.

### Allowing `TXCREATE` in legacy EVM

EOF contract creation requires an exceptional possibility of calling an EOF opcode in legacy code - `TXCREATE`, because otherwise neither legacy contracts nor create transactions can deploy EOF code to bootstrap. The alternative approach was to continue using legacy creation mechanisms, by either still relying on fetching the *initcode* from memory and not satisfy the overarching requirement of code non-observability, or to abuse the legacy creation transactions mechanism, or to introduce a predeployed Creator Contract into the state.

This also makes [EIP-7698](./eip-7698.md) (EOF - Creation transaction) no longer an essential requirement for deploying EOF contracts onto the chain. The EIP could be removed from EOFv1 and withdrawn.

### New address hashing scheme

`TXCREATE` uses the scheme `new_address = keccak256(0xff || sender32 || salt)[12:]`, same as `EOFCREATE` instruction. The decision whether to include initcontainer hash into salt is left to the `TXCREATE` caller. See [EIP-7620](./eip-7620.md) for detailed rationale.

### EOF creation transactions vs deployment patterns

Relying on the EOF creation transactions as the alternative solution makes it impossible for smart contract wallets to deploy arbitrary EOF contracts (only EOAs can). At the same time, it is a use case current legacy creation rules allow, thanks to `CREATE` and `CREATE2` instructions. A workaround where those arbitrary EOF contracts are first "uploaded" to a factory contract, and then deployed using an `EXTDELEGATECALL`-`EOFCREATE` sequence, is very expensive, as it requires the deployed contract to be put on-chain twice. Because of this, the approach proposed in this EIP is more compatible with the Account Abstraction (AA) roadmap, where smart contract wallets should have feature parity with EOAs.

On top of this, relying on nonce-based hashing scheme to obtain addresses of newly created contracts, like in the case of the EOF creation transactions, would prevent EOF contracts from being deployed counterfactually to deterministic, cross-chain addresses. Introduction of the `TXCREATE` instruction, supports this out of the box. ERCs can be written to provide toehold contracts which will cater for the deployment patterns, such as salt-less deployment and hashing in the sender's address as part of the salt.

### Handling of `0xEF00` prefixed code in existing transaction types.

Three existing transaction types (type 0 "Frontier," type 1 "AccessList," type 2 "FeeMarket") accept code as part of their input data in certain configurations. This code can start with `EF` as it is initcode and not a deployed contract.

One possible way of handling potential EOF containers in these transactions is to make them invalid if they are attempting to execute an EOF container as initcode. Specifically the transactions is invalid if the input data begins with `0xef00` and if the `to` field is set to nil, signaling a contract creation transaction. This would make blocks containing these transactions invalid, whereas before the fork including this EIP they would have been valid.

One impact that would be seen by this would be block builders, as they would need to ensure that the transactions that are invalid are not included in a block. There is precedent for this, as [EIP-7623](./eip-7623.md) established a new floor for the gas limit in transactions, prior to its adoption the limit was lower.  However, block builders have an existing check on gas limits and transactions and that change was adjusting the formula and constants.

We should also consider the treatment [EIP-7702](./eip-7702) delegation designations receive if they show up as code in a contract creation transaction.  The transaction is valid, is executed as plain bytecode, ad the first operation executed is `0xEF`, which is an invalid opcode and would cause the whole transaction to abort.

Letting the inputdata of a type 0, 1, and 2 contract creation transaction execute as plain EVM code irrespective of the magic `0xEF00` bytes keeps a consistent behavior in client code and keeps block builders from having to update their logic in older transaction types.

## Backwards Compatibility

This change poses no risk to backwards compatibility, as it is introduced at the same time EIP-3540 is. Despite the new instruction being introduced for legacy bytecode (code which is not EOF formatted), there is little chance that a meaningful contract would unintentionally execute `0xed` instruction with formally valid operands and inadvertently cause it to run EOF initcode (which would also require an `InitcodeTransaction` to be used, otherwise the initcode lookup will fail).

`TXCREATE` instruction introduction into legacy EVM does not affect `JUMPDEST` analysis, because instruction has no immediate arguments.

The transactions of the new type are invalid until this change activates.

Contract creation options do not change for legacy bytecode, including how existing transactions with `to: nil` behave when encountering code in their calldata that may look like an EOF container.

## Security Considerations

Needs discussion.

## Copyright

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