Table of contents

Ethereum compatibility layer

This provides a description of the compatibility layer built on Substrate to run unmodified Ethereum dapps.

The goal of Ethereum compatibility layer is to be able to:

  • Run a normal web3 application via the compatibility layer, using local nodes, where an extra bridge binary is acceptable.

  • Be able to import state from Ethereum mainnet.


Types of dapps

We consider three different types of dapps:

  • Dapps without private keys: those dapps do not handle private keys. They relies on eth_sendTransaction and expect the RPC node to handle keys.

  • Dapps with private keys: those dapps handle private keys internally, and will instead use eth_sendRawTransaction.

  • Specialized dapps: dapps with special functionalities. Those include ones that relies heavily on internal Ethereum implementation details. An example would be a decentralized mining pool contract.

The goal of the Ethereum compatibility layer is to support dapps with or without private keys. We ignore the case for specialized dapps as it is expensive to emulate subtle details of Ethereum implementations. Any method that can support dapps with private keys will also support dapps without private keys, but not vice versa. In appendix, an alternative method is provided that only handles dapps without private keys, but is simpler.


EVM pallet

The module would handle the essence of EVM invocations, and is implemented as pallet-evm.

State import

This section describes something that has not yet been implemented.

The pallet should be able to directly import state, both in genesis config, and through sudo transactions.

Ethereum pallet

This section describes something that has not yet been implemented.

A separate pallet module pallet-ethereum is required to emulate the full block processing part. This pallet has two main functionalities:

  • Store invoked transactions and their receipts.

  • Delegate call the EVM pallet, so that separate transaction and receipt information can be generated.

The module will have at least the following extrinsics:

  • transact: take a full Ethereum transaction, decode the RLP object, and delegate the call to EVM pallet. It then gathers the logs and receipts, and store them. There can be a whitelist of secp256k1 keys to sr25519 keys, or it can be configured to skip secp256k1 signature verification at all.

RPC module

This section describes something that has not yet been implemented.

The RPC module talks with pallet-ethereum. The blocks are emulated as follows:

  • Take Substrate’s state root as the Ethereum’s state root.

  • Take each block’s transaction and receipt root from pallet-ethereum.

  • Value of difficulty, extraData, gasLimit, gasUsed, uncles and other PoW-specific values are either none, default, or can be configured to be a constant.

The bridge also directly talks with rust-evm for anything that does not need to write on-chain. For example, eth_estimateGas.


To port a dapp initially designed for Ethereum mainnet, the following steps are needed:

  • Pick a block on Ethereum mainnet, where the dapp is "frozen".

  • Use a tool that exports the select account states into an object file.

  • Import the state into Substrate, either in genesis or through sudo transactions.

  • Start the internal RPC module.

  • Now the dapp can be used as normal.