diff --git a/app/app.go b/app/app.go index db47123dda..5bf5652edd 100644 --- a/app/app.go +++ b/app/app.go @@ -494,7 +494,7 @@ func New( ) // Create Transfer Keepers - app.TransferKeeper = ibctransferkeeper.NewKeeper( + app.TransferKeeper = ibctransferkeeper.NewKeeperWithAddressHandler( appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), @@ -504,6 +504,7 @@ func New( app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, + evmkeeper.NewEvmAddressHandler(&app.EvmKeeper), ) transferModule := transfer.NewAppModule(app.TransferKeeper) transferIBCModule := transfer.NewIBCModule(app.TransferKeeper) diff --git a/go.mod b/go.mod index 40503ec502..b9b293a80e 100644 --- a/go.mod +++ b/go.mod @@ -353,7 +353,7 @@ replace ( github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0 github.com/cosmos/cosmos-sdk => github.com/sei-protocol/sei-cosmos v0.3.51 github.com/cosmos/iavl => github.com/sei-protocol/sei-iavl v0.2.0 - github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.4 + github.com/cosmos/ibc-go/v3 => github.com/sei-protocol/sei-ibc-go/v3 v3.3.5 github.com/ethereum/go-ethereum => github.com/sei-protocol/go-ethereum v1.13.5-sei-9.0.20241224143343-21ee50facc96 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 github.com/sei-protocol/sei-db => github.com/sei-protocol/sei-db v0.0.46 diff --git a/go.sum b/go.sum index 8f25d861f0..6d333ab927 100644 --- a/go.sum +++ b/go.sum @@ -1354,8 +1354,8 @@ github.com/sei-protocol/sei-db v0.0.46 h1:naXfSp1I3UgJJm/iSvXpdFzr9nofEOxp/EekcA github.com/sei-protocol/sei-db v0.0.46/go.mod h1:m5g7p0QeAS3dNJHIl28zQpzOgxQmvYqPb7t4hwgIOCA= github.com/sei-protocol/sei-iavl v0.2.0 h1:OisPjXiDT+oe+aeckzDEFgkZCYuUjHgs/PP8DPicN+I= github.com/sei-protocol/sei-iavl v0.2.0/go.mod h1:qRf8QYUPfrAO7K6VDB2B2l/N7K5L76OorioGBcJBIbw= -github.com/sei-protocol/sei-ibc-go/v3 v3.3.4 h1:M1r1B2yzogs7RyXdCPgaNJlxqSC/rU2goqtfnUTXS/M= -github.com/sei-protocol/sei-ibc-go/v3 v3.3.4/go.mod h1:VwB/vWu4ysT5DN2aF78d17LYmx3omSAdq6gpKvM7XRA= +github.com/sei-protocol/sei-ibc-go/v3 v3.3.5 h1:SQRzWi9KSMuGNGd3f5RWAmsGGk7yeY1zhnEnrr/nqug= +github.com/sei-protocol/sei-ibc-go/v3 v3.3.5/go.mod h1:VwB/vWu4ysT5DN2aF78d17LYmx3omSAdq6gpKvM7XRA= github.com/sei-protocol/sei-tendermint v0.4.6 h1:Gmw4tjLSnghAdue54HJzDySDvxs2Hd5d0rrv3ajgRSA= github.com/sei-protocol/sei-tendermint v0.4.6/go.mod h1:4LSlJdhl3nf3OmohliwRNUFLOB1XWlrmSodrIP7fLh4= github.com/sei-protocol/sei-tm-db v0.0.5 h1:3WONKdSXEqdZZeLuWYfK5hP37TJpfaUa13vAyAlvaQY= diff --git a/precompiles/ibc/ibc.go b/precompiles/ibc/ibc.go index a7e24d4aed..497329e8fa 100644 --- a/precompiles/ibc/ibc.go +++ b/precompiles/ibc/ibc.go @@ -7,7 +7,6 @@ import ( "math/big" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/bech32" "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types" connectiontypes "github.com/cosmos/ibc-go/v3/modules/core/03-connection/types" @@ -352,16 +351,8 @@ func (p PrecompileExecutor) validateCommonArgs(ctx sdk.Context, args []interface } receiverAddressString, ok := args[0].(string) - if !ok { - return nil, errors.New("receiverAddress is not a string") - } - _, bz, err := bech32.DecodeAndConvert(receiverAddressString) - if err != nil { - return nil, err - } - err = sdk.VerifyAddressFormat(bz) - if err != nil { - return nil, err + if !ok || receiverAddressString == "" { + return nil, errors.New("receiverAddress is not a string or empty") } port, ok := args[1].(string) diff --git a/precompiles/ibc/ibc_test.go b/precompiles/ibc/ibc_test.go index 08a2313775..925d4bc5c1 100644 --- a/precompiles/ibc/ibc_test.go +++ b/precompiles/ibc/ibc_test.go @@ -202,7 +202,7 @@ func TestPrecompile_Run(t *testing.T) { caller: senderEvmAddress, callingContract: senderEvmAddress, input: &input{ - receiverAddr: "invalid", + receiverAddr: "", sourcePort: "transfer", sourceChannel: "channel-0", denom: "", @@ -216,7 +216,7 @@ func TestPrecompile_Run(t *testing.T) { }, wantBz: nil, wantErr: true, - wantErrMsg: "decoding bech32 failed: invalid bech32 string length 7", + wantErrMsg: "receiverAddress is not a string or empty", }, { name: "memo is added to the transfer if passed", @@ -424,7 +424,7 @@ func TestTransferWithDefaultTimeoutPrecompile_Run(t *testing.T) { caller: senderEvmAddress, callingContract: senderEvmAddress, input: &input{ - receiverAddr: "invalid", + receiverAddr: "", sourcePort: "transfer", sourceChannel: "channel-0", denom: "", @@ -435,7 +435,7 @@ func TestTransferWithDefaultTimeoutPrecompile_Run(t *testing.T) { }, wantBz: nil, wantErr: true, - wantErrMsg: "decoding bech32 failed: invalid bech32 string length 7", + wantErrMsg: "receiverAddress is not a string or empty", }, } for _, tt := range tests { diff --git a/x/evm/keeper/address.go b/x/evm/keeper/address.go index a9c946b8b8..93720607d6 100644 --- a/x/evm/keeper/address.go +++ b/x/evm/keeper/address.go @@ -84,3 +84,23 @@ func (k *Keeper) CanAddressReceive(ctx sdk.Context, addr sdk.AccAddress) bool { // if the associated address is the cast address itself, allow the address to receive (e.g. EVM contract addresses) return associatedAddr.Equals(addr) || !isAssociated // this means it's either a cast address that's not associated yet, or not a cast address at all. } + +type EvmAddressHandler struct { + evmKeeper *Keeper +} + +func NewEvmAddressHandler(evmKeeper *Keeper) EvmAddressHandler { + return EvmAddressHandler{evmKeeper: evmKeeper} +} + +func (h EvmAddressHandler) GetSeiAddressFromString(ctx sdk.Context, address string) (sdk.AccAddress, error) { + if common.IsHexAddress(address) { + parsedAddress := common.HexToAddress(address) + return h.evmKeeper.GetSeiAddressOrDefault(ctx, parsedAddress), nil + } + parsedAddress, err := sdk.AccAddressFromBech32(address) + if err != nil { + return nil, err + } + return parsedAddress, nil +} diff --git a/x/evm/keeper/address_test.go b/x/evm/keeper/address_test.go index 8a66da57f4..ed244f0093 100644 --- a/x/evm/keeper/address_test.go +++ b/x/evm/keeper/address_test.go @@ -6,6 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/sei-protocol/sei-chain/testutil/keeper" + evmkeeper "github.com/sei-protocol/sei-chain/x/evm/keeper" "github.com/stretchr/testify/require" ) @@ -73,3 +74,81 @@ func TestSendingToCastAddress(t *testing.T) { require.NotNil(t, a.BankKeeper.SendCoins(ctx, sourceAddr, castAddr, amt)) require.NotNil(t, a.BankKeeper.SendCoinsAndWei(ctx, sourceAddr, castAddr, sdk.OneInt(), sdk.OneInt())) } + +func TestEvmAddressHandler_GetSeiAddressFromString(t *testing.T) { + a := keeper.EVMTestApp + ctx := a.GetContextForDeliverTx([]byte{}) + seiAddr, evmAddr := keeper.MockAddressPair() + a.EvmKeeper.SetAddressMapping(ctx, seiAddr, evmAddr) + + _, notAssociatedEvmAddr := keeper.MockAddressPair() + castAddr := sdk.AccAddress(notAssociatedEvmAddr[:]) + + type args struct { + ctx sdk.Context + address string + } + tests := []struct { + name string + args args + want sdk.AccAddress + wantErr bool + wantErrMsg string + }{ + { + name: "returns associated Sei address if input address is a valid 0x and associated", + args: args{ + ctx: ctx, + address: evmAddr.String(), + }, + want: seiAddr, + }, + { + name: "returns default Sei address if input address is a valid 0x not associated", + args: args{ + ctx: ctx, + address: notAssociatedEvmAddr.String(), + }, + want: castAddr, + }, + { + name: "returns Sei address if input address is a valid bech32 address", + args: args{ + ctx: ctx, + address: seiAddr.String(), + }, + want: seiAddr, + }, + { + name: "returns error if address is invalid", + args: args{ + ctx: ctx, + address: "invalid", + }, + wantErr: true, + wantErrMsg: "decoding bech32 failed: invalid bech32 string length 7", + }, { + name: "returns error if address is empty", + args: args{ + ctx: ctx, + address: "", + }, + wantErr: true, + wantErrMsg: "empty address string is not allowed", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + h := evmkeeper.NewEvmAddressHandler(&a.EvmKeeper) + got, err := h.GetSeiAddressFromString(tt.args.ctx, tt.args.address) + if tt.wantErr { + require.NotNil(t, err) + require.Equal(t, tt.wantErrMsg, err.Error()) + return + } else { + require.NoError(t, err) + require.Equal(t, tt.want, got) + } + }) + } +}