Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add IBC support for 0x addresses #2051

Merged
merged 7 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
13 changes: 2 additions & 11 deletions precompiles/ibc/ibc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to add checks that the address is valid? i.e.

  1. if sei, it is proper bech32
  2. if evm, it is a valid address

Copy link
Contributor Author

@dssei dssei Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did have the bech32 check before, but i was too restrictive. In fact this address is propagated as string all the way up the stack without any checks. I guess the assumption is that it could any type of address, not only bech32 or EVM.

}

port, ok := args[1].(string)
Expand Down
8 changes: 4 additions & 4 deletions precompiles/ibc/ibc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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: "",
Expand All @@ -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",
Expand Down Expand Up @@ -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: "",
Expand All @@ -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 {
Expand Down
20 changes: 20 additions & 0 deletions x/evm/keeper/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codchen is assumption correct here that if address is not associated yet, the funds would go to an "escrow" account and then will be migrated after association?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upd: Was able to test scenario e2e and it works

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes this is correct

}
parsedAddress, err := sdk.AccAddressFromBech32(address)
if err != nil {
return nil, err
}
return parsedAddress, nil
}
79 changes: 79 additions & 0 deletions x/evm/keeper/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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)
}
})
}
}
Loading