CREATEF ======= In general, replace CREATE3/CREATE4 with CREATEF, where the same executing contract is used for initcode, but a different code section other than 0 is used. Problem ------- Using the factory pattern will require two levels of nesting if done in a EOF container. First there is the executing container, then there is the container that holds the exec code, then there will be the deployed contract itself. ``` +-----------------------------+ | Factory Contract | | +-------------------------+ | | | Child contract initcode | | | | +----------------+ | | | | | Child Contract | | | | | +----------------+ | | | +-------------------------+ | +-----------------------------+ ``` There will be three separate EOF headers to parse. Let's not forget, this also has to be deployed, so the master deployer will have _at least_ 3 layers of nested contracts. ``` +---------------------------------+ | Factory Contract Deployer | | +-----------------------------+ | | | Factory Contract | | | | +-------------------------+ | | | | | Child contract initcode | | | | | | +----------------+ | | | | | | | Child Contract | | | | | | | +----------------+ | | | | | +-------------------------+ | | | +-----------------------------+ | +---------------------------------+ ``` Solution -------- Instead of going to a separate EOF container that contains initcode, the current container will contain the initcode at a different code setcion than the main entry point. The CREATEF call, instead of pointing to a subcointainer, will point to a code section to perform the pre-deployment initialization. ``` +--------------------------------------+ | Factory Contract | | sections 0-n Normal factory code | | section m Child contract initcode | | +----------------+ | | | Child Contract | | | +----------------+ | +--------------------------------------+ ``` This also allows for multiple contract to re-use subroutines from other initcode and the main factory code. A single CREATEF operation replaces CREATE3/CREATE4 and two return operations replace RETURNCONTRAcT, one referencing a EOF subcontainer index and one referening a hash of a container in the transaction body of a new transaction type. * CREATEF Operation * deduct 32000 gas * read uint8 operand initcodesection_index * pops value, salt, data_offset, data_size from the stack * deduct 8 * ((initcontainer_size + 31) // 32) gas (EIP-3860 + hashing charge) * calculate new_address as keccak256(0xff |\| sender |\| salt |\| inicodesection_index |\| keccak256(container))[12:] * Creates a new stack frame executing under the new address, but with the existing container. Execution starts with the first byte of the referened code section * an unsuccesful execution of initcode results in pushing 0 onto the stack * set state[new_address].code to the updated container * push new_address onto the stack * RETURN and STOP are not allowed (abort execution) * RETF at the top of the return stack is similarly not allowed * deduct 200 * deployed_code_size gas * if initcode container or deployed container is invalid, instruction’s execution ends with the result 0 pushed on stack. The caller’s nonce remains increased and all creation gas is deducted. Instead of two create variants there are two contract return variants * RETURN_CONTRACT_INDEX instruction * loads uint8 immediate container_index * exceptional halt if the container does not have a subcontainer at that index * exceptional halt if subcontainer code is EOF invalid (unless we settle on deep validation for containers from an external source) * pops two values from the stack: aux_data_offset, aux_data_size * Appends the aux data to the subcontainer, and re-writes the header if needed to accomodate the added data * cost 0 gas + 1 byte per final contract size * instruction exceptionally aborts if invoked not in “initcode mode” * RETURN_CONTRACT_HASH instruction * pops three values from the stack: codehash, aux_data_offset, aux_data_size * Searches for code with the codehash in specified locations * For EOF1 this will be a new transaction type that has extra "data" fields that hold containers, like CREATE4 * Account Abstraction systems can combine multiple creat calls into one TX without concern about the transaction indexes. * L2s/L3s and ZK systems may want to create a "library" of know contracts by hash, that are pre-loaded and pre-compiled. * exceptional halt if subcontainer code is EOF invalid (validation is always performed) * Appends the aux data to the subcontainer, and re-writes the header if needed to accomodate the added data * cost 0 gas + 1 byte per final contract size * instruction exceptionally aborts if invoked not in “initcode mode” The two return operations could be combined if we added a magic rule that any return value with 30 or more leading zeros refers to a container index. Or if we also refered to the subcontainers by hash.