diff --git a/CHANGELOG.md b/CHANGELOG.md index c17ffc609..65aa0ccae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ ### FEATURES +- [\#665](https://github.com/cosmos/evm/pull/665) Add EvmCodec address codec implementation - [\#346](https://github.com/cosmos/evm/pull/346) Add eth_createAccessList method and implementation - [\#337](https://github.com/cosmos/evm/pull/337) Support state overrides in eth_call. - [\#502](https://github.com/cosmos/evm/pull/502) Add block time in derived logs. diff --git a/encoding/address/address_codec.go b/encoding/address/address_codec.go new file mode 100644 index 000000000..827267b9c --- /dev/null +++ b/encoding/address/address_codec.go @@ -0,0 +1,63 @@ +package address + +import ( + "strings" + + "github.com/ethereum/go-ethereum/common" + + "github.com/cosmos/evm/utils" + + "cosmossdk.io/core/address" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/bech32" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ address.Codec = (*evmCodec)(nil) + +// evmCodec defines an address codec for EVM compatible cosmos modules +type evmCodec struct { + bech32Prefix string +} + +// NewEvmCodec returns a new EvmCodec with the given bech32 prefix +func NewEvmCodec(prefix string) address.Codec { + return evmCodec{prefix} +} + +// StringToBytes decodes text to bytes using either hex or bech32 encoding +func (bc evmCodec) StringToBytes(text string) ([]byte, error) { + if len(strings.TrimSpace(text)) == 0 { + return []byte{}, sdkerrors.ErrInvalidAddress.Wrap("empty address string is not allowed") + } + + switch { + case common.IsHexAddress(text): + return common.HexToAddress(text).Bytes(), nil + case utils.IsBech32Address(text): + hrp, bz, err := bech32.DecodeAndConvert(text) + if err != nil { + return nil, err + } + if hrp != bc.bech32Prefix { + return nil, sdkerrors.ErrLogic.Wrapf("hrp does not match bech32 prefix: expected '%s' got '%s'", bc.bech32Prefix, hrp) + } + if err := sdk.VerifyAddressFormat(bz); err != nil { + return nil, err + } + return bz, nil + default: + return nil, sdkerrors.ErrUnknownAddress.Wrapf("unknown address format: %s", text) + } +} + +// BytesToString decodes bytes to text +func (bc evmCodec) BytesToString(bz []byte) (string, error) { + text, err := bech32.ConvertAndEncode(bc.bech32Prefix, bz) + if err != nil { + return "", err + } + + return text, nil +} diff --git a/encoding/address/address_codec_test.go b/encoding/address/address_codec_test.go new file mode 100644 index 000000000..d4e690c66 --- /dev/null +++ b/encoding/address/address_codec_test.go @@ -0,0 +1,165 @@ +package address_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + evmaddress "github.com/cosmos/evm/encoding/address" + + "cosmossdk.io/core/address" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +const ( + hex = "0x7cB61D4117AE31a12E393a1Cfa3BaC666481D02E" + bech32 = "cosmos10jmp6sgh4cc6zt3e8gw05wavvejgr5pwsjskvv" +) + +func TestStringToBytes(t *testing.T) { + config := sdk.GetConfig() + config.SetBech32PrefixForAccount("cosmos", "cosmospub") + addrBz := common.HexToAddress(hex).Bytes() + + testCases := []struct { + name string + cdcPrefix string + input string + expBz []byte + expErr error + }{ + { + "success: valid bech32 address", + "cosmos", + bech32, + addrBz, + nil, + }, + { + "success: valid hex address", + "cosmos", + hex, + addrBz, + nil, + }, + { + "failure: invalid bech32 address (wrong prefix)", + "evmos", + bech32, + nil, + sdkerrors.ErrLogic.Wrapf("hrp does not match bech32 prefix: expected '%s' got '%s'", "evmos", "cosmos"), + }, + { + "failure: invalid bech32 address (too long)", + "cosmos", + "cosmos10jmp6sgh4cc6zt3e8gw05wavvejgr5pwsjskvvv", // extra char at the end + nil, + sdkerrors.ErrUnknownAddress, + }, + { + "failure: invalid bech32 address (invalid format)", + "cosmos", + "cosmos10jmp6sgh4cc6zt3e8gw05wavvejgr5pwsjskv", // missing last char + nil, + sdkerrors.ErrUnknownAddress, + }, + { + "failure: invalid hex address (odd length)", + "cosmos", + "0x7cB61D4117AE31a12E393a1Cfa3BaC666481D02", // missing last char + nil, + sdkerrors.ErrUnknownAddress, + }, + { + "failure: invalid hex address (even length)", + "cosmos", + "0x7cB61D4117AE31a12E393a1Cfa3BaC666481D0", // missing last 2 char + nil, + sdkerrors.ErrUnknownAddress, + }, + { + "failure: invalid hex address (too long)", + "cosmos", + "0x7cB61D4117AE31a12E393a1Cfa3BaC666481D02E00", // extra 2 char at the end + nil, + sdkerrors.ErrUnknownAddress, + }, + { + "failure: empty string", + "cosmos", + "", + nil, + sdkerrors.ErrInvalidAddress.Wrap("empty address string is not allowed"), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + cdc := evmaddress.NewEvmCodec(tc.cdcPrefix) + bz, err := cdc.StringToBytes(tc.input) + if tc.expErr == nil { + require.NoError(t, err) + require.Equal(t, tc.expBz, bz) + } else { + require.ErrorContains(t, err, tc.expErr.Error()) + } + }) + } +} + +func TestBytesToString(t *testing.T) { + // Keep the same fixtures as your StringToBytes test + config := sdk.GetConfig() + config.SetBech32PrefixForAccount("cosmos", "cosmospub") + + addrBz := common.HexToAddress(hex).Bytes() // 20 bytes + + // Helper codec (used only where we want to derive bytes from the bech32 string) + var cdc address.Codec + + type tc struct { + name string + input func() []byte + expRes string + expErr error + } + + testCases := []tc{ + { + name: "success: from 20-byte input (hex-derived)", + input: func() []byte { + cdc = evmaddress.NewEvmCodec("cosmos") + return addrBz + }, + expRes: bech32, + expErr: nil, + }, + { + name: "success: from bech32-derived bytes", + input: func() []byte { + cdc = evmaddress.NewEvmCodec("cosmos") + bz, err := cdc.StringToBytes(bech32) + require.NoError(t, err) + require.Len(t, bz, 20) + return bz + }, + expRes: bech32, + expErr: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got, err := cdc.BytesToString(tc.input()) + if tc.expErr == nil { + require.NoError(t, err) + require.Equal(t, tc.expRes, got) + } else { + require.ErrorContains(t, err, tc.expErr.Error()) + } + }) + } +} diff --git a/encoding/config.go b/encoding/config.go index aa0c25629..97547c24e 100644 --- a/encoding/config.go +++ b/encoding/config.go @@ -3,6 +3,7 @@ package encoding import ( "google.golang.org/protobuf/reflect/protoreflect" + evmaddress "github.com/cosmos/evm/encoding/address" enccodec "github.com/cosmos/evm/encoding/codec" "github.com/cosmos/evm/ethereum/eip712" erc20types "github.com/cosmos/evm/x/erc20/types" @@ -13,7 +14,6 @@ import ( "github.com/cosmos/cosmos-sdk/client" amino "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth/migrations/legacytx" @@ -33,12 +33,8 @@ type Config struct { func MakeConfig(evmChainID uint64) Config { cdc := amino.NewLegacyAmino() signingOptions := signing.Options{ - AddressCodec: address.Bech32Codec{ - Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(), - }, - ValidatorAddressCodec: address.Bech32Codec{ - Bech32Prefix: sdk.GetConfig().GetBech32ValidatorAddrPrefix(), - }, + AddressCodec: evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + ValidatorAddressCodec: evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), CustomGetSigners: map[protoreflect.FullName]signing.GetSignersFunc{ evmtypes.MsgEthereumTxCustomGetSigner.MsgType: evmtypes.MsgEthereumTxCustomGetSigner.Fn, erc20types.MsgConvertERC20CustomGetSigner.MsgType: erc20types.MsgConvertERC20CustomGetSigner.Fn, diff --git a/ethereum/eip712/preprocess_test.go b/ethereum/eip712/preprocess_test.go index c0376fda0..a93c1c5ee 100644 --- a/ethereum/eip712/preprocess_test.go +++ b/ethereum/eip712/preprocess_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/cosmos/evm/encoding" + evmaddress "github.com/cosmos/evm/encoding/address" "github.com/cosmos/evm/ethereum/eip712" "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" @@ -18,7 +19,6 @@ import ( "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec/address" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" @@ -107,9 +107,7 @@ func TestLedgerPreprocessing(t *testing.T) { // Verify tx fields are unchanged tx := tc.txBuilder.GetTx() - addrCodec := address.Bech32Codec{ - Bech32Prefix: sdk.GetConfig().GetBech32AccountAddrPrefix(), - } + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) txFeePayer, err := addrCodec.BytesToString(tx.FeePayer()) require.NoError(t, err) diff --git a/evmd/app.go b/evmd/app.go index 2e0cdbce3..3bbcd465a 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -23,6 +23,7 @@ import ( evmante "github.com/cosmos/evm/ante" evmconfig "github.com/cosmos/evm/config" evmosencoding "github.com/cosmos/evm/encoding" + evmaddress "github.com/cosmos/evm/encoding/address" evmmempool "github.com/cosmos/evm/mempool" srvflags "github.com/cosmos/evm/server/flags" cosmosevmtypes "github.com/cosmos/evm/types" @@ -93,7 +94,6 @@ import ( signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/cosmos-sdk/version" "github.com/cosmos/cosmos-sdk/x/auth" - authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" "github.com/cosmos/cosmos-sdk/x/auth/posthandler" authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" @@ -292,7 +292,7 @@ func NewExampleApp( app.AccountKeeper = authkeeper.NewAccountKeeper( appCodec, runtime.NewKVStoreService(keys[authtypes.StoreKey]), authtypes.ProtoBaseAccount, evmconfig.GetMaccPerms(), - authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), sdk.GetConfig().GetBech32AccountAddrPrefix(), authAddr, ) @@ -327,8 +327,8 @@ func NewExampleApp( app.AccountKeeper, app.BankKeeper, authAddr, - authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), - authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), ) app.MintKeeper = mintkeeper.NewKeeper( @@ -1134,8 +1134,8 @@ func (app *EVMD) AutoCliOpts() autocli.AppOptions { return autocli.AppOptions{ Modules: modules, ModuleOptions: runtimeservices.ExtractAutoCLIOptions(app.ModuleManager.Modules), - AddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), - ValidatorAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), - ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), + AddressCodec: evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + ValidatorAddressCodec: evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), + ConsensusAddressCodec: evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), } } diff --git a/precompiles/distribution/types_test.go b/precompiles/distribution/types_test.go index 0ab01f434..1395144fd 100644 --- a/precompiles/distribution/types_test.go +++ b/precompiles/distribution/types_test.go @@ -8,16 +8,16 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + evmaddress "github.com/cosmos/evm/encoding/address" cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" ) const validatorAddr = "cosmosvaloper1qypqxpq9qcrsszg2pvxq6rs0zqg3yyc5a3kaax" func TestNewMsgSetWithdrawAddress(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") withdrawerBech32 := "cosmos1qypqxpq9qcrsszg2pvxq6rs0zqg3yyc5lzv7xu" @@ -100,7 +100,7 @@ func TestNewMsgSetWithdrawAddress(t *testing.T) { } func TestNewMsgWithdrawDelegatorReward(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") @@ -162,7 +162,7 @@ func TestNewMsgWithdrawDelegatorReward(t *testing.T) { } func TestNewMsgFundCommunityPool(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) depositorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") validCoins := []cmn.Coin{{Denom: "stake", Amount: big.NewInt(1000)}} @@ -229,7 +229,7 @@ func TestNewMsgFundCommunityPool(t *testing.T) { } func TestNewMsgDepositValidatorRewardsPool(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) depositorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") validCoins := []cmn.Coin{{Denom: "stake", Amount: big.NewInt(1000)}} @@ -299,7 +299,7 @@ func TestNewMsgDepositValidatorRewardsPool(t *testing.T) { } func TestNewDelegationRewardsRequest(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") @@ -360,7 +360,7 @@ func TestNewDelegationRewardsRequest(t *testing.T) { } func TestNewDelegationTotalRewardsRequest(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") @@ -418,7 +418,7 @@ func TestNewDelegationTotalRewardsRequest(t *testing.T) { } func TestNewDelegatorValidatorsRequest(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") @@ -476,7 +476,7 @@ func TestNewDelegatorValidatorsRequest(t *testing.T) { } func TestNewDelegatorWithdrawAddressRequest(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") diff --git a/precompiles/gov/types_test.go b/precompiles/gov/types_test.go index 60406f0e9..64907876d 100644 --- a/precompiles/gov/types_test.go +++ b/precompiles/gov/types_test.go @@ -8,14 +8,14 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + evmaddress "github.com/cosmos/evm/encoding/address" cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" ) func TestNewMsgDeposit(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) depositorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") validCoins := []cmn.Coin{{Denom: "stake", Amount: big.NewInt(1000)}} @@ -98,7 +98,7 @@ func TestNewMsgDeposit(t *testing.T) { } func TestNewMsgCancelProposal(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) proposerAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") proposalID := uint64(1) @@ -173,7 +173,7 @@ func TestNewMsgCancelProposal(t *testing.T) { } func TestNewMsgVote(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) voterAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") proposalID := uint64(1) @@ -268,7 +268,7 @@ func TestNewMsgVote(t *testing.T) { } func TestParseVoteArgs(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) voterAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") proposalID := uint64(1) @@ -336,7 +336,7 @@ func TestParseVoteArgs(t *testing.T) { } func TestParseDepositArgs(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) depositorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") proposalID := uint64(1) diff --git a/precompiles/slashing/types_test.go b/precompiles/slashing/types_test.go index c2567a05e..7acb99efe 100644 --- a/precompiles/slashing/types_test.go +++ b/precompiles/slashing/types_test.go @@ -7,14 +7,14 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + evmaddress "github.com/cosmos/evm/encoding/address" cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" ) func TestParseSigningInfoArgs(t *testing.T) { - consCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()) + consCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()) validAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") expectedConsAddr, err := consCodec.BytesToString(validAddr.Bytes()) require.NoError(t, err) diff --git a/precompiles/staking/types_test.go b/precompiles/staking/types_test.go index 2fc0c23a2..8a7d609c8 100644 --- a/precompiles/staking/types_test.go +++ b/precompiles/staking/types_test.go @@ -8,10 +8,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" + evmaddress "github.com/cosmos/evm/encoding/address" cmn "github.com/cosmos/evm/precompiles/common" sdk "github.com/cosmos/cosmos-sdk/types" - authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" ) const ( @@ -20,7 +20,7 @@ const ( ) func TestNewMsgCreateValidator(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) validatorHexAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") description := Description{ @@ -140,7 +140,7 @@ func TestNewMsgCreateValidator(t *testing.T) { } func TestNewMsgDelegate(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") amount := big.NewInt(1000000000) @@ -225,7 +225,7 @@ func TestNewMsgDelegate(t *testing.T) { } func TestNewMsgUndelegate(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") amount := big.NewInt(1000000000) @@ -310,7 +310,7 @@ func TestNewMsgUndelegate(t *testing.T) { } func TestNewMsgRedelegate(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") validatorSrcAddr := "cosmosvaloper1qypqxpq9qcrsszg2pvxq6rs0zqg3yyc5a3kaax" @@ -406,7 +406,7 @@ func TestNewMsgRedelegate(t *testing.T) { } func TestNewMsgCancelUnbondingDelegation(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") amount := big.NewInt(1000000000) @@ -501,7 +501,7 @@ func TestNewMsgCancelUnbondingDelegation(t *testing.T) { } func TestNewDelegationRequest(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") @@ -574,7 +574,7 @@ func TestNewDelegationRequest(t *testing.T) { } func TestNewUnbondingDelegationRequest(t *testing.T) { - addrCodec := authcodec.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()) + addrCodec := evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()) delegatorAddr := common.HexToAddress("0x1234567890123456789012345678901234567890") diff --git a/precompiles/types/defaults.go b/precompiles/types/defaults.go index 49cb44125..cd5c582e1 100644 --- a/precompiles/types/defaults.go +++ b/precompiles/types/defaults.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + evmaddress "github.com/cosmos/evm/encoding/address" bankprecompile "github.com/cosmos/evm/precompiles/bank" "github.com/cosmos/evm/precompiles/bech32" cmn "github.com/cosmos/evm/precompiles/common" @@ -23,7 +24,6 @@ import ( "cosmossdk.io/core/address" "github.com/cosmos/cosmos-sdk/codec" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" sdktypes "github.com/cosmos/cosmos-sdk/types" distributionkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" @@ -42,9 +42,9 @@ type Optionals struct { func defaultOptionals() Optionals { return Optionals{ - AddressCodec: addresscodec.NewBech32Codec(sdktypes.GetConfig().GetBech32AccountAddrPrefix()), - ValidatorAddrCodec: addresscodec.NewBech32Codec(sdktypes.GetConfig().GetBech32ValidatorAddrPrefix()), - ConsensusAddrCodec: addresscodec.NewBech32Codec(sdktypes.GetConfig().GetBech32ConsensusAddrPrefix()), + AddressCodec: evmaddress.NewEvmCodec(sdktypes.GetConfig().GetBech32AccountAddrPrefix()), + ValidatorAddrCodec: evmaddress.NewEvmCodec(sdktypes.GetConfig().GetBech32ValidatorAddrPrefix()), + ConsensusAddrCodec: evmaddress.NewEvmCodec(sdktypes.GetConfig().GetBech32ConsensusAddrPrefix()), } } diff --git a/tests/integration/precompiles/distribution/test_query.go b/tests/integration/precompiles/distribution/test_query.go index 5ae049a34..75a25b485 100644 --- a/tests/integration/precompiles/distribution/test_query.go +++ b/tests/integration/precompiles/distribution/test_query.go @@ -51,7 +51,7 @@ var baseTestCases = []distrTestCases{ func([]byte) {}, 100000, true, - "invalid bech32 string", + "invalid: unknown address", }, } @@ -524,7 +524,7 @@ func (s *PrecompileTestSuite) TestDelegationRewards() { func([]byte) {}, 100000, true, - "invalid bech32 string", + "invalid: unknown address", }, { "fail - nonexistent validator address", diff --git a/tests/integration/precompiles/distribution/test_setup.go b/tests/integration/precompiles/distribution/test_setup.go index 6f219b5a5..610c08203 100644 --- a/tests/integration/precompiles/distribution/test_setup.go +++ b/tests/integration/precompiles/distribution/test_setup.go @@ -3,6 +3,7 @@ package distribution import ( "github.com/stretchr/testify/suite" + evmaddress "github.com/cosmos/evm/encoding/address" "github.com/cosmos/evm/precompiles/distribution" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/testutil/integration/evm/factory" @@ -14,7 +15,6 @@ import ( "cosmossdk.io/math" sdkmath "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/codec/address" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -136,6 +136,6 @@ func (s *PrecompileTestSuite) SetupTest() { distrkeeper.NewQuerier(s.network.App.GetDistrKeeper()), *s.network.App.GetStakingKeeper(), s.network.App.GetBankKeeper(), - address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), ) } diff --git a/tests/integration/precompiles/distribution/test_tx.go b/tests/integration/precompiles/distribution/test_tx.go index 33db8c8b1..c4b868108 100644 --- a/tests/integration/precompiles/distribution/test_tx.go +++ b/tests/integration/precompiles/distribution/test_tx.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" + evmaddress "github.com/cosmos/evm/encoding/address" cmn "github.com/cosmos/evm/precompiles/common" "github.com/cosmos/evm/precompiles/distribution" "github.com/cosmos/evm/precompiles/testutil" @@ -16,7 +17,6 @@ import ( "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/codec/address" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/distribution/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -677,7 +677,7 @@ func (s *PrecompileTestSuite) TestDepositValidatorRewardsPoolMethod() { s.Require().True(success, "expected true, got false") val := s.network.GetValidators()[0] - valCodec := address.NewBech32Codec("cosmosvaloper") + valCodec := evmaddress.NewEvmCodec("cosmosvaloper") valBz, err := valCodec.StringToBytes(val.GetOperator()) s.Require().NoError(err) diff --git a/tests/integration/precompiles/distribution/test_utils.go b/tests/integration/precompiles/distribution/test_utils.go index adbece8b4..dc4efe986 100644 --- a/tests/integration/precompiles/distribution/test_utils.go +++ b/tests/integration/precompiles/distribution/test_utils.go @@ -1,12 +1,12 @@ package distribution import ( + evmaddress "github.com/cosmos/evm/encoding/address" "github.com/cosmos/evm/precompiles/staking" "github.com/cosmos/evm/testutil/keyring" "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/codec/address" sdk "github.com/cosmos/cosmos-sdk/types" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" @@ -88,7 +88,7 @@ func (s *PrecompileTestSuite) getStakingPrecompile() *staking.Precompile { stakingkeeper.NewMsgServerImpl(s.network.App.GetStakingKeeper()), stakingkeeper.NewQuerier(s.network.App.GetStakingKeeper()), s.network.App.GetBankKeeper(), - address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), ) } diff --git a/tests/integration/precompiles/gov/test_setup.go b/tests/integration/precompiles/gov/test_setup.go index 69216147e..d172947e0 100644 --- a/tests/integration/precompiles/gov/test_setup.go +++ b/tests/integration/precompiles/gov/test_setup.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/suite" + evmaddress "github.com/cosmos/evm/encoding/address" "github.com/cosmos/evm/precompiles/gov" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/testutil/integration/evm/factory" @@ -14,7 +15,6 @@ import ( "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -143,6 +143,6 @@ func (s *PrecompileTestSuite) SetupTest() { govkeeper.NewQueryServer(&govKeeper), s.network.App.GetBankKeeper(), s.network.App.AppCodec(), - address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), ) } diff --git a/tests/integration/precompiles/slashing/test_setup.go b/tests/integration/precompiles/slashing/test_setup.go index faef7a821..9ec41c529 100644 --- a/tests/integration/precompiles/slashing/test_setup.go +++ b/tests/integration/precompiles/slashing/test_setup.go @@ -3,13 +3,13 @@ package slashing import ( "github.com/stretchr/testify/suite" + evmaddress "github.com/cosmos/evm/encoding/address" "github.com/cosmos/evm/precompiles/slashing" "github.com/cosmos/evm/testutil/integration/evm/factory" "github.com/cosmos/evm/testutil/integration/evm/grpc" "github.com/cosmos/evm/testutil/integration/evm/network" testkeyring "github.com/cosmos/evm/testutil/keyring" - "github.com/cosmos/cosmos-sdk/codec/address" sdk "github.com/cosmos/cosmos-sdk/types" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" ) @@ -58,7 +58,7 @@ func (s *PrecompileTestSuite) SetupTest() { s.network.App.GetSlashingKeeper(), slashingkeeper.NewMsgServerImpl(s.network.App.GetSlashingKeeper()), s.network.App.GetBankKeeper(), - address.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), - address.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), ) } diff --git a/tests/integration/precompiles/staking/test_query.go b/tests/integration/precompiles/staking/test_query.go index f25ab74a9..b5165cfd0 100644 --- a/tests/integration/precompiles/staking/test_query.go +++ b/tests/integration/precompiles/staking/test_query.go @@ -64,7 +64,7 @@ func (s *PrecompileTestSuite) TestDelegation() { func([]byte) {}, 100000, true, - "decoding bech32 failed: invalid bech32 string", + "invalid: unknown address", }, { "success - empty delegation", diff --git a/tests/integration/precompiles/staking/test_setup.go b/tests/integration/precompiles/staking/test_setup.go index 764d22559..50c2bdc26 100644 --- a/tests/integration/precompiles/staking/test_setup.go +++ b/tests/integration/precompiles/staking/test_setup.go @@ -3,6 +3,7 @@ package staking import ( "github.com/stretchr/testify/suite" + evmaddress "github.com/cosmos/evm/encoding/address" "github.com/cosmos/evm/precompiles/staking" testconstants "github.com/cosmos/evm/testutil/constants" "github.com/cosmos/evm/testutil/integration/evm/factory" @@ -12,7 +13,6 @@ import ( sdkmath "cosmossdk.io/math" - "github.com/cosmos/cosmos-sdk/codec/address" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -86,6 +86,6 @@ func (s *PrecompileTestSuite) SetupTest() { stakingkeeper.NewMsgServerImpl(s.network.App.GetStakingKeeper()), stakingkeeper.NewQuerier(s.network.App.GetStakingKeeper()), s.network.App.GetBankKeeper(), - address.NewBech32Codec(sdk.GetConfig().GetBech32AccountAddrPrefix()), + evmaddress.NewEvmCodec(sdk.GetConfig().GetBech32AccountAddrPrefix()), ) } diff --git a/utils/utils.go b/utils/utils.go index 57f8bd0f4..543339ba0 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -25,6 +25,7 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/bech32" errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -127,6 +128,12 @@ func IsSupportedKey(pubkey cryptotypes.PubKey) bool { } } +// IsBech32Address checks if the address is a valid bech32 address. +func IsBech32Address(address string) bool { + _, _, err := bech32.DecodeAndConvert(address) + return err == nil +} + // GetAccAddressFromBech32 returns the sdk.Account address of given address, // while also changing bech32 human readable prefix (HRP) to the value set on // the global sdk.Config (eg: `evmos`). diff --git a/utils/utils_test.go b/utils/utils_test.go index c6d7d331f..b0e8c9f4f 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -33,6 +33,11 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +const ( + hex = "0x7cB61D4117AE31a12E393a1Cfa3BaC666481D02E" + bech32 = "cosmos10jmp6sgh4cc6zt3e8gw05wavvejgr5pwsjskvv" +) + func TestIsSupportedKeys(t *testing.T) { testCases := []struct { name string @@ -86,6 +91,53 @@ func TestIsSupportedKeys(t *testing.T) { } } +func TestIsBech32Address(t *testing.T) { + config := sdk.GetConfig() + config.SetBech32PrefixForAccount("cosmos", "cosmospub") + + testCases := []struct { + name string + address string + expResp bool + }{ + { + "blank bech32 address", + " ", + false, + }, + { + "invalid bech32 address", + "evmos", + false, + }, + { + "invalid address bytes", + "cosmos1123", + false, + }, + { + "evmos address", + "evmos1ltzy54ms24v590zz37r2q9hrrdcc8eslndsqwv", + true, + }, + { + "cosmos address", + "cosmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueulg2gmc", + true, + }, + { + "osmosis address", + "osmo1qql8ag4cluz6r4dz28p3w00dnc9w8ueuhnecd2", + true, + }, + } + + for _, tc := range testCases { + isValid := utils.IsBech32Address(tc.address) + require.Equal(t, tc.expResp, isValid, tc.name) + } +} + func TestGetAccAddressFromBech32(t *testing.T) { config := sdk.GetConfig() config.SetBech32PrefixForAccount("cosmos", "cosmospub") @@ -116,8 +168,8 @@ func TestGetAccAddressFromBech32(t *testing.T) { }, { "evmos address", - "cosmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueulg2gmc", - "cosmos1qql8ag4cluz6r4dz28p3w00dnc9w8ueulg2gmc", + "evmos1ltzy54ms24v590zz37r2q9hrrdcc8eslndsqwv", + "cosmos1ltzy54ms24v590zz37r2q9hrrdcc8esl3vpw5y", false, }, { @@ -254,9 +306,6 @@ func TestAddressConversion(t *testing.T) { config := sdk.GetConfig() config.SetBech32PrefixForAccount("cosmos", "cosmospub") - hex := "0x7cB61D4117AE31a12E393a1Cfa3BaC666481D02E" - bech32 := "cosmos10jmp6sgh4cc6zt3e8gw05wavvejgr5pwsjskvv" - require.Equal(t, bech32, utils.Bech32StringFromHexAddress(hex)) gotAddr, err := utils.HexAddressFromBech32String(bech32) require.NoError(t, err)