Standalone

Self-Hosted EVM

close button

Part IV

Instructions

With storage, stack, and memory virtually re-implemented, we now have the basic building blocks to implement most instructions!

Execution Scope

In our EVM, each instruction takes in an execution Scope (see contracts/libraries/Context.sol) as a parameter. Scope encapsulates the state of the EVM during the execution of a transaction.

Scope { // EVM execution context Context context; // Contract being executed Contract _contract; // EVM API API api; // EVM execution state // STOP flag bool stop; // Program counter : position in the bytecode uint256 pc; // Stack Stack stack; // Memory Memory _memory; // Read-only flag bool readOnly; // Call states // REVERTED flag bool reverted; // Return data buffer bytes returndata; }

You will notice three new sub-structures.

  • Context maintains information about the incoming call.

  • Contract represents a virtual contract.

  • API exposes the functions of State.sol to the instruction library, so instructions can read and write onto the sEVM state.

Take a quick look at how these structures are defined in Context.sol!

selfhosted_EVM_06.webp

Basic Instructions

We want to implement the basic instructions in `contracts/libraries/Instructions.sol`. This means all unimplemented instructions except the following:

  • opCall

  • opStaticCall

  • opDelegateCall

  • opCallCode

  • opCreate

  • opCreate2

You will see some pre-implemented instructions. There is no need to implement nor modify them. For example:

/** * @dev BLOCKHASH instruction. * @notice THIS INSTRUCTION IS ALREADY IMPLEMENTED * @param scope The current execution scope. */ function opBlockHash(Scope memory scope) internal view { scope.stack.push(blockhash(block.number)); }

Considerations

Some opcodes should lead to an immediate revert if they are used in an inappropriate context. For instance, opSstore should revert if scope.readOnly is set to true.

As the sEVM runs inside the real EVM you can use the EVM primitives to implement most of the instructions. Also remember that at the assembly level, all arithmetic instructions should be unchecked (i.e., should overflow/underflow silently).

Error

Expected Message

READ_ONLY_ERROR

sEVM: read only

Your Task

Implement the basic instructions in contracts/libraries/Instructions.sol.

You do not have to implement instructions that have already been implemented for you, nor the `CALL` and `CREATE` family of instructions:

  • opCall

  • opStaticCall

  • opDelegateCall

  • opCallCode

  • opCreate

  • opCreate2

Make sure to research what each instruction should do. evm.codes should prove useful.

Run tests in Questplay

Despite the dangers of going against the Guilds, many disciples flocked to the Great Archmage, desperate to learn the secrets of Cryptomancy…