EOF - Creation transaction
相关视频
正文
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 RETURNCODE instruction. New account address calculation is based on sender's address and nonce.
Motivation
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.
Specification
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:
- behavior on
accessed_addressesand address collision (EIP-684 and EIP-2929) - EVM execution frame created for the initcode - memory, account context etc.
- nonce bumping of the account of newly created contract EIP-161
- balance checking and transfer for the creation endowment
Parameters
| 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:
- Intrinsic gas cost rules and limits defined in EIP-3860 for creation transactions apply. The entire
dataof the transaction is used for these calculations. - Find the split of
dataintoinitcontainerandcalldata:- Parse EOF header
- Find
intcontainersize by reading all section sizes from the header and adding them up with the header size to get the full container size.
- Validate the
initcontainerand all its subcontainers recursively.- Unlike in general validation,
initcontaineris additionally required to havedata_sizedeclared in the header equal to actualdata_sectionsize. - Validation includes checking that the
initcontainerdoes not containRETURNorSTOP
- Unlike in general validation,
- 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.
calldatapart of transactiondatathat followsinitcontaineris treated as calldata to pass into the execution frame.- Execute the container and deduct gas for execution.
- Calculate
new_addressaskeccak256(sender || sender_nonce)[12:] - A successful execution ends with initcode executing
RETURNCODE{deploy_container_index}(aux_data_offset, aux_data_size)instruction. After that:- load deploy-contract from EOF subcontainer at
deploy_container_indexin the container from whichRETURNCODEis 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_sizebe updated deploy container size, - if
deployed_code_size > MAX_CODE_SIZEinstruction exceptionally aborts, - set
state[new_address].codeto the updated deploy container (rules of EIP-3541, prohibiting deployment ofcodestarting withEFfrom creation transactions, do not apply in this case).
- load deploy-contract from EOF subcontainer at
- Calculate
- Deduct
200 * deployed_code_sizegas.
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 the
InitcodeTransaction), it would have a dedicated field for initcontainer execution input (calldata), and it will be accessed withCALLDATA*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.