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 RETURNCODE
instruction. New account address calculation is based on sender's address and nonce.
Creation transaction is one of 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.
Wherever not explicitly listed, the rules of EOF contract creation should be identical or analogous to those of legacy creation transaction. This includes but is not limited to:
accessed_addresses
and address collision (EIP-684 and EIP-2929)Constant | Value |
---|---|
EOF_MAGIC |
Defined as 0xEF00 in EIP-3540 |
MAX_CODE_SIZE |
Defined as 24576 in EIP-170 |
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:
data
of the transaction is used for these calculations.data
into initcontainer
and calldata
:intcontainer
size by reading all section sizes from the header and adding them up with the header size to get the full container size.initcontainer
and all its subcontainers recursively.initcontainer
is additionally required to have data_size
declared in the header equal to actual data_section
size.initcontainer
does not contain RETURN
or STOP
calldata
part of transaction data
that follows initcontainer
is treated as calldata to pass into the execution frame.new_address
as keccak256(sender || sender_nonce)[12:]
RETURNCODE{deploy_container_index}(aux_data_offset, aux_data_size)
instruction. After that:deploy_container_index
in the container from which RETURNCODE
is executed,(aux_data_offset, aux_data_offset + aux_data_size)
memory segment and update data size in the header,deployed_code_size
be updated deploy container size,deployed_code_size > MAX_CODE_SIZE
instruction exceptionally aborts,state[new_address].code
to the updated deploy container (rules of EIP-3541, prohibiting deployment of code
starting with EF
from creation transactions, do not apply in this case).200 * deployed_code_size
gas.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.
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:
InitcodeTransaction
), 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.Creation transactions deploying legacy code are not affected, because any such transaction starting with EF
byte previously would fail on executing invalid instruction.
TBA
Copyright and related rights waived via CC0.