EEVM.SystemContracts (eevm v0.1.0)

Copy Markdown View Source

Genesis setup for the system contracts that blocks call from Cancun on.

EIPFromAddressCalled
EIP-4788 beacon rootsCancun0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02block start
EIP-2935 block hashesPrague0x0000F90827F1C53a10cb7A02335B175320002935block start
EIP-7002 withdrawal requestsPrague0x00000961Ef480Eb55e80D19ad83579A64c007002block end
EIP-7251 consolidation requestsPrague0x0000BBdDc7CE488642fb579F8B00f3a590007251block end

On mainnet each contract was deployed by an ordinary transaction before its fork activated. A chain started from scratch, such as a devnet or a test, has no such history, so genesis_accounts/1 returns the contracts a fork calls as genesis accounts, and install/2 writes them into a database.

Block execution never installs them itself: a Prague block whose state lacks the EIP-7002 or EIP-7251 contract fails with :system_contract_empty, as those EIPs require. A missing EIP-4788 or EIP-2935 contract makes its block-start call a no-op. EEVM.SystemContracts.BeaconRoots and EEVM.SystemContracts.BlockHashes drive and read those two contracts.

Summary

Functions

Returns the system contracts that blocks of fork call, as genesis accounts in the shape EEVM.Database.InMemory.new/1 takes: %{address => %{balance: 0, nonce: 1, code: code}}.

Writes the accounts genesis_accounts/1 returns for fork into db, replacing any accounts at those addresses but keeping their storage.

Functions

genesis_accounts(fork)

@spec genesis_accounts(EEVM.Config.t() | EEVM.HardforkConfig.spec_id()) :: %{
  required(non_neg_integer()) => %{balance: 0, nonce: 1, code: binary()}
}

Returns the system contracts that blocks of fork call, as genesis accounts in the shape EEVM.Database.InMemory.new/1 takes: %{address => %{balance: 0, nonce: 1, code: code}}.

fork is an EEVM.Config or a hardfork name. Each contract is included from the fork that activates its EIP, with its canonical deployed code and the nonce of 1 that its deployment left on mainnet, so state roots match other clients'. Forks before Cancun need none.

Examples

iex> EEVM.SystemContracts.genesis_accounts(:prague) |> Map.keys() |> Enum.sort()
[
  0x00000961EF480EB55E80D19AD83579A64C007002,
  0x0000BBDDC7CE488642FB579F8B00F3A590007251,
  0x0000F90827F1C53A10CB7A02335B175320002935,
  0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02
]
iex> EEVM.SystemContracts.genesis_accounts(EEVM.Config.new(:cancun))
%{0x000F3DF6D732807EF1319FB7B8BB8522D0BEAC02 => %{balance: 0, nonce: 1,
  code: EEVM.SystemContracts.BeaconRoots.deployed_bytecode()}}
iex> EEVM.SystemContracts.genesis_accounts(:shanghai)
%{}

install(db, fork)

Writes the accounts genesis_accounts/1 returns for fork into db, replacing any accounts at those addresses but keeping their storage.

Example

iex> db = EEVM.SystemContracts.install(EEVM.Database.InMemory.new(), :prague)
iex> EEVM.Database.get_nonce(db, 0x00000961EF480EB55E80D19AD83579A64C007002)
1