Standalone

Self-Hosted EVM

close button

Part VII

Create & Create2

With the CALL family of instructions implemented, we are only left with the CREATE and CREATE2 instructions. We are almost finished!

Create

CREATE is used by a contract to deploy a new contract on-chain. The deployer might attach some value to the deploying call. This instruction will consume the following stack:

selfhosted_EVM_12.webp

The deployment bytecode is given by mem[ARGS OFFSET: ARGS OFFSET + ARGS LENGTH], which consists of the contract bytecode and any constructor parameters.

The new contract's construction might revert. In this case, opCreate should safely handle the reversion and push address(0) onto the stack. This can be handled by using ICrossTx and a try/catch block, similar to what we did with our call instructions.

function opCreate(Scope memory scope) internal { ... try ICrossTx(address(this)).create(...) { // SUCCESS ... } catch (bytes memory revertData) { // FAILURE ... } }
selfhosted_EVM_13.webp

CREATE also has several other nuances you have to consider to get the implementation right:

  1. Each new contract's address is determined by the deployer's address and the deployer's nonce. A pre-defined function, State.getNextDeploymentAddress(address), is provided to help you perform this computation.

  2. Upon each deployment, the deployer's nonce should be incremented by 1, while the new contract's nonce should be set to 1.

  3. Although unlikely, it is possible that the address to deploy to is already occupied. In this case, deployment should fail.

Error

Expected Message

INSUFFICIENT_BALANCE_ERROR

sEVM: insufficient balance

READ_ONLY_ERROR

sEVM: read only

DUPLICATE_ACCOUNT_ERROR

sEVM: account already exists

Create2

CREATE2 deploys a contract as well, except that the new address is deterministically computed, independent from the deployer's nonce. Instead, it is computed from the deployer's address, initialization bytecode, and a salt. This instruction consumes the following stack:

selfhosted_EVM_14.webp

Similar to how opCreate is implemented, opCreate2 will need to make an external call to the sEVM.create2 function.

selfhosted_EVM_15.webp

Unlike in CREATE, you will need to define the address computation logic yourself.|

Error

Expected Message

INSUFFICIENT_BALANCE_ERROR

sEVM: insufficient balance

READ_ONLY_ERROR

sEVM: read only

DUPLICATE_ACCOUNT_ERROR

sEVM: account already exists

Your Task

Implement CREATE by defining:

  • opCreate in contracts/libraries/Instructions.sol

  • create in contracts/sEVM.sol

Then, implement CREATE2 by defining:

  • opCreate2 in contracts/libraries/Instructions.sol

  • create2 in contracts/sEVM.sol

Run tests in Questplay

Submit work in Questplay

As more and more came to learn, the Order of the Node Guardians was founded, sworn to follow the Tenets and use Cryptomancy to strive for a better world for all...