From e2fb32fca92d0feece071794c4b9517299069b6b Mon Sep 17 00:00:00 2001 From: Gjermund Garaba Date: Sun, 28 Sep 2025 11:46:20 +0200 Subject: [PATCH 1/4] feat: static precompiles builder --- precompiles/types/defaults.go | 93 ++----------- precompiles/types/static_precompiles.go | 170 ++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 81 deletions(-) create mode 100644 precompiles/types/static_precompiles.go diff --git a/precompiles/types/defaults.go b/precompiles/types/defaults.go index 49cb44125..1df666da7 100644 --- a/precompiles/types/defaults.go +++ b/precompiles/types/defaults.go @@ -1,21 +1,10 @@ package types import ( - "fmt" - "maps" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - bankprecompile "github.com/cosmos/evm/precompiles/bank" - "github.com/cosmos/evm/precompiles/bech32" cmn "github.com/cosmos/evm/precompiles/common" - distprecompile "github.com/cosmos/evm/precompiles/distribution" - govprecompile "github.com/cosmos/evm/precompiles/gov" - ics20precompile "github.com/cosmos/evm/precompiles/ics20" - "github.com/cosmos/evm/precompiles/p256" - slashingprecompile "github.com/cosmos/evm/precompiles/slashing" - stakingprecompile "github.com/cosmos/evm/precompiles/staking" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" channelkeeper "github.com/cosmos/ibc-go/v10/modules/core/04-channel/keeper" @@ -85,74 +74,16 @@ func DefaultStaticPrecompiles( codec codec.Codec, opts ...Option, ) map[common.Address]vm.PrecompiledContract { - options := defaultOptionals() - for _, opt := range opts { - opt(&options) - } - // Clone the mapping from the latest EVM fork. - precompiles := maps.Clone(vm.PrecompiledContractsPrague) - - // secp256r1 precompile as per EIP-7212 - p256Precompile := &p256.Precompile{} - - bech32Precompile, err := bech32.NewPrecompile(bech32PrecompileBaseGas) - if err != nil { - panic(fmt.Errorf("failed to instantiate bech32 precompile: %w", err)) - } - - stakingPrecompile := stakingprecompile.NewPrecompile( - stakingKeeper, - stakingkeeper.NewMsgServerImpl(&stakingKeeper), - stakingkeeper.NewQuerier(&stakingKeeper), - bankKeeper, - options.AddressCodec, - ) - - distributionPrecompile := distprecompile.NewPrecompile( - distributionKeeper, - distributionkeeper.NewMsgServerImpl(distributionKeeper), - distributionkeeper.NewQuerier(distributionKeeper), - stakingKeeper, - bankKeeper, - options.AddressCodec, - ) - - ibcTransferPrecompile := ics20precompile.NewPrecompile( - bankKeeper, - stakingKeeper, - transferKeeper, - channelKeeper, - ) - - bankPrecompile := bankprecompile.NewPrecompile(bankKeeper, erc20Keeper) - - govPrecompile := govprecompile.NewPrecompile( - govkeeper.NewMsgServerImpl(&govKeeper), - govkeeper.NewQueryServer(&govKeeper), - bankKeeper, - codec, - options.AddressCodec, - ) - - slashingPrecompile := slashingprecompile.NewPrecompile( - slashingKeeper, - slashingkeeper.NewMsgServerImpl(slashingKeeper), - bankKeeper, - options.ValidatorAddrCodec, - options.ConsensusAddrCodec, - ) - - // Stateless precompiles - precompiles[bech32Precompile.Address()] = bech32Precompile - precompiles[p256Precompile.Address()] = p256Precompile - - // Stateful precompiles - precompiles[stakingPrecompile.Address()] = stakingPrecompile - precompiles[distributionPrecompile.Address()] = distributionPrecompile - precompiles[ibcTransferPrecompile.Address()] = ibcTransferPrecompile - precompiles[bankPrecompile.Address()] = bankPrecompile - precompiles[govPrecompile.Address()] = govPrecompile - precompiles[slashingPrecompile.Address()] = slashingPrecompile - - return precompiles + precompiles := NewStaticPrecompiles(). + WithPraguePrecompiles(). + WithP256Precompile(). + WithBech32Precompile(). + WithStakingPrecompile(stakingKeeper, bankKeeper, opts...). + WithDistributionPrecompile(distributionKeeper, stakingKeeper, bankKeeper, opts...). + WithICS20Precompile(bankKeeper, stakingKeeper, transferKeeper, channelKeeper). + WithBankPrecompile(bankKeeper, erc20Keeper). + WithGovPrecompile(govKeeper, bankKeeper, codec, opts...). + WithSlashingPrecompile(slashingKeeper, bankKeeper, opts...) + + return map[common.Address]vm.PrecompiledContract(precompiles) } diff --git a/precompiles/types/static_precompiles.go b/precompiles/types/static_precompiles.go new file mode 100644 index 000000000..1fcc4f59a --- /dev/null +++ b/precompiles/types/static_precompiles.go @@ -0,0 +1,170 @@ +package types + +import ( + "fmt" + "maps" + + bankprecompile "github.com/cosmos/evm/precompiles/bank" + "github.com/cosmos/evm/precompiles/bech32" + cmn "github.com/cosmos/evm/precompiles/common" + distprecompile "github.com/cosmos/evm/precompiles/distribution" + govprecompile "github.com/cosmos/evm/precompiles/gov" + ics20precompile "github.com/cosmos/evm/precompiles/ics20" + "github.com/cosmos/evm/precompiles/p256" + slashingprecompile "github.com/cosmos/evm/precompiles/slashing" + stakingprecompile "github.com/cosmos/evm/precompiles/staking" + erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" + transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper" + channelkeeper "github.com/cosmos/ibc-go/v10/modules/core/04-channel/keeper" + + "github.com/cosmos/cosmos-sdk/codec" + distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" + govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" + slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" +) + +type StaticPrecompiles map[common.Address]vm.PrecompiledContract + +func NewStaticPrecompiles() StaticPrecompiles { + return make(StaticPrecompiles) +} + +func (s StaticPrecompiles) WithPraguePrecompiles() StaticPrecompiles { + maps.Copy(s, vm.PrecompiledContractsPrague) + return s +} + +func (s StaticPrecompiles) WithP256Precompile() StaticPrecompiles { + p256Precompile := &p256.Precompile{} + s[p256Precompile.Address()] = p256Precompile + return s +} + +func (s StaticPrecompiles) WithBech32Precompile() StaticPrecompiles { + bech32Precompile, err := bech32.NewPrecompile(bech32PrecompileBaseGas) + if err != nil { + panic(fmt.Errorf("failed to instantiate bech32 precompile: %w", err)) + } + s[bech32Precompile.Address()] = bech32Precompile + return s +} + +func (s StaticPrecompiles) WithStakingPrecompile( + stakingKeeper stakingkeeper.Keeper, + bankKeeper cmn.BankKeeper, + opts ...Option, +) StaticPrecompiles { + options := defaultOptionals() + for _, opt := range opts { + opt(&options) + } + + stakingPrecompile := stakingprecompile.NewPrecompile( + stakingKeeper, + stakingkeeper.NewMsgServerImpl(&stakingKeeper), + stakingkeeper.NewQuerier(&stakingKeeper), + bankKeeper, + options.AddressCodec, + ) + + s[stakingPrecompile.Address()] = stakingPrecompile + return s +} + +func (s StaticPrecompiles) WithDistributionPrecompile( + distributionKeeper distributionkeeper.Keeper, + stakingKeeper stakingkeeper.Keeper, + bankKeeper cmn.BankKeeper, + opts ...Option, +) StaticPrecompiles { + options := defaultOptionals() + for _, opt := range opts { + opt(&options) + } + + distributionPrecompile := distprecompile.NewPrecompile( + distributionKeeper, + distributionkeeper.NewMsgServerImpl(distributionKeeper), + distributionkeeper.NewQuerier(distributionKeeper), + stakingKeeper, + bankKeeper, + options.AddressCodec, + ) + + s[distributionPrecompile.Address()] = distributionPrecompile + return s +} + +func (s StaticPrecompiles) WithICS20Precompile( + bankKeeper cmn.BankKeeper, + stakingKeeper stakingkeeper.Keeper, + transferKeeper *transferkeeper.Keeper, + channelKeeper *channelkeeper.Keeper, +) StaticPrecompiles { + ibcTransferPrecompile := ics20precompile.NewPrecompile( + bankKeeper, + stakingKeeper, + transferKeeper, + channelKeeper, + ) + + s[ibcTransferPrecompile.Address()] = ibcTransferPrecompile + return s +} + +func (s StaticPrecompiles) WithBankPrecompile( + bankKeeper cmn.BankKeeper, + erc20Keeper *erc20Keeper.Keeper, +) StaticPrecompiles { + bankPrecompile := bankprecompile.NewPrecompile(bankKeeper, erc20Keeper) + s[bankPrecompile.Address()] = bankPrecompile + return s +} + +func (s StaticPrecompiles) WithGovPrecompile( + govKeeper govkeeper.Keeper, + bankKeeper cmn.BankKeeper, + codec codec.Codec, + opts ...Option, +) StaticPrecompiles { + options := defaultOptionals() + for _, opt := range opts { + opt(&options) + } + + govPrecompile := govprecompile.NewPrecompile( + govkeeper.NewMsgServerImpl(&govKeeper), + govkeeper.NewQueryServer(&govKeeper), + bankKeeper, + codec, + options.AddressCodec, + ) + + s[govPrecompile.Address()] = govPrecompile + return s +} + +func (s StaticPrecompiles) WithSlashingPrecompile( + slashingKeeper slashingkeeper.Keeper, + bankKeeper cmn.BankKeeper, + opts ...Option, +) StaticPrecompiles { + options := defaultOptionals() + for _, opt := range opts { + opt(&options) + } + + slashingPrecompile := slashingprecompile.NewPrecompile( + slashingKeeper, + slashingkeeper.NewMsgServerImpl(slashingKeeper), + bankKeeper, + options.ValidatorAddrCodec, + options.ConsensusAddrCodec, + ) + + s[slashingPrecompile.Address()] = slashingPrecompile + return s +} From 18fe3932b49c17eaddf35b44c8c6b9b6cee6a1a7 Mon Sep 17 00:00:00 2001 From: Gjermund Garaba Date: Sun, 28 Sep 2025 23:06:55 +0300 Subject: [PATCH 2/4] lint --- precompiles/types/static_precompiles.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/precompiles/types/static_precompiles.go b/precompiles/types/static_precompiles.go index 1fcc4f59a..ca49445f9 100644 --- a/precompiles/types/static_precompiles.go +++ b/precompiles/types/static_precompiles.go @@ -4,6 +4,9 @@ import ( "fmt" "maps" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + bankprecompile "github.com/cosmos/evm/precompiles/bank" "github.com/cosmos/evm/precompiles/bech32" cmn "github.com/cosmos/evm/precompiles/common" @@ -22,8 +25,6 @@ import ( govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" ) type StaticPrecompiles map[common.Address]vm.PrecompiledContract From bd225281e24bbb218baaa051b4dd2df48f92030e Mon Sep 17 00:00:00 2001 From: Gjermund Garaba Date: Tue, 7 Oct 2025 22:51:02 +0200 Subject: [PATCH 3/4] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6447c3c0..c22565de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ - [\#664](https://github.com/cosmos/evm/pull/664) Add EIP-7702 integration test - [\#684](https://github.com/cosmos/evm/pull/684) Add unit test cases for EIP-7702 - [\#685](https://github.com/cosmos/evm/pull/685) Add EIP-7702 e2e test +- [\#680](https://github.com/cosmos/evm/pull/680) Introduce a `StaticPrecompiles` builder ### FEATURES From 09adf46289ed03ef056e59dd15b2220a0922f14f Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 9 Oct 2025 14:53:03 -0400 Subject: [PATCH 4/4] lint --- precompiles/types/defaults.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/precompiles/types/defaults.go b/precompiles/types/defaults.go index 08c9b1f1a..65b855e37 100644 --- a/precompiles/types/defaults.go +++ b/precompiles/types/defaults.go @@ -4,7 +4,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" - evmaddress "github.com/cosmos/evm/encoding/address" + evmaddress "github.com/cosmos/evm/encoding/address" cmn "github.com/cosmos/evm/precompiles/common" erc20Keeper "github.com/cosmos/evm/x/erc20/keeper" transferkeeper "github.com/cosmos/evm/x/ibc/transfer/keeper"