From 98311b4c873d6c996a2b67f9ca69bc328d88cdba Mon Sep 17 00:00:00 2001 From: evgeniy-scherbina Date: Mon, 6 May 2024 14:04:06 -0400 Subject: [PATCH] Initialize precompiles in InitGenesis --- x/evm/genesis.go | 24 ++++++++++++++++++++++++ x/evm/genesis_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/x/evm/genesis.go b/x/evm/genesis.go index 992d53c9fd..4eb9b1c3cf 100644 --- a/x/evm/genesis.go +++ b/x/evm/genesis.go @@ -27,9 +27,14 @@ import ( precompile_modules "github.com/ethereum/go-ethereum/precompile/modules" ethermint "github.com/evmos/ethermint/types" "github.com/evmos/ethermint/x/evm/keeper" + "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" ) +const PrecompileNonce uint64 = 1 + +var PrecompileCode = []byte{0x1} + // InitGenesis initializes genesis state based on exported genesis func InitGenesis( ctx sdk.Context, @@ -48,6 +53,25 @@ func InitGenesis( panic(err) } + txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())) + stateDB := statedb.New(ctx, k, txConfig) + + for _, hexAddr := range data.Params.EnabledPrecompiles { + addr := common.HexToAddress(hexAddr) + + // Set the nonce of the precompile's address (as is done when a contract is created) to ensure + // that it is marked as non-empty and will not be cleaned up when the statedb is finalized. + stateDB.SetNonce(addr, PrecompileNonce) + // Set the code of the precompile's address to a non-zero length byte slice to ensure that the precompile + // can be called from within Solidity contracts. Solidity adds a check before invoking a contract to ensure + // that it does not attempt to invoke a non-existent contract. + stateDB.SetCode(addr, PrecompileCode) + } + + if err := stateDB.Commit(); err != nil { + panic(err) + } + err = k.SetParams(ctx, data.Params) if err != nil { panic(fmt.Errorf("error setting params %s", err)) diff --git a/x/evm/genesis_test.go b/x/evm/genesis_test.go index 0359a29664..785d0fd8eb 100644 --- a/x/evm/genesis_test.go +++ b/x/evm/genesis_test.go @@ -231,3 +231,35 @@ func (suite *EvmTestSuite) TestInitGenesis() { }) } } + +func (suite *EvmTestSuite) TestInitPrecompiles() { + hexAddr1 := "0x1000000000000000000000000000000000000000" + hexAddr2 := "0x2000000000000000000000000000000000000000" + + genState := types.DefaultGenesisState() + genState.Params.EnabledPrecompiles = []string{hexAddr1, hexAddr2} + registeredModules := []precompile_modules.Module{ + {Address: common.HexToAddress(hexAddr1)}, + {Address: common.HexToAddress(hexAddr2)}, + } + + vmdb := suite.StateDB() + + // check that enabled precompiles are uninitialized + for _, hexAddr := range genState.Params.EnabledPrecompiles { + addr := common.HexToAddress(hexAddr) + + suite.Require().Equal(uint64(0), vmdb.GetNonce(addr)) + suite.Require().Equal([]byte(nil), vmdb.GetCode(addr)) + } + + evm.InitGenesis(suite.ctx, suite.app.EvmKeeper, suite.app.AccountKeeper, *genState, registeredModules) + + // check that enabled precompiles are initialized + for _, hexAddr := range genState.Params.EnabledPrecompiles { + addr := common.HexToAddress(hexAddr) + + suite.Require().Equal(evm.PrecompileNonce, vmdb.GetNonce(addr)) + suite.Require().Equal(evm.PrecompileCode, vmdb.GetCode(addr)) + } +}