Skip to content

Commit ea2196a

Browse files
srdtrkmmsqe
authored andcommitted
imp(transfer,rate-limiting,pfm)!: use AddressCodec instead of Bech32 (cosmos#8573)
* imp: added address codec to transfer * imp: address codec used in transfer * fix: tests * imp: test passing * imp: added addressCodec to PFM * imp: added receiver test * test: transfer cov * test: added cases * test: more cov * test: more cov * style: single line func def * test: new test works * imp: add basic test * imp: added migration guide * doc: added changelog * refactor: address codec moved
1 parent 0b90af4 commit ea2196a

File tree

13 files changed

+107
-30
lines changed

13 files changed

+107
-30
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ Ref: https://keepachangelog.com/en/1.0.0/
3434

3535
# Changelog
3636

37+
## [Unreleased]
38+
39+
### Features
40+
* [\#8573](https://github.com/cosmos/ibc-go/pull/8573) Support custom address codecs in transfer, PFM, and rate limiting.
41+
3742
## [v10.3.0](https://github.com/cosmos/ibc-go/releases/tag/v10.3.0) - 2025-06-06
3843

3944
### Features

modules/apps/callbacks/testing/simapp/app.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ func NewSimApp(
375375
app.AccountKeeper, app.BankKeeper,
376376
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
377377
)
378+
app.TransferKeeper.SetAddressCodec(app.AccountKeeper.AddressCodec())
378379

379380
// Mock Module Stack
380381

modules/apps/transfer/keeper/keeper.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"strings"
77

8+
"cosmossdk.io/core/address"
89
corestore "cosmossdk.io/core/store"
910
"cosmossdk.io/log"
1011
sdkmath "cosmossdk.io/math"
@@ -28,6 +29,7 @@ type Keeper struct {
2829
storeService corestore.KVStoreService
2930
cdc codec.BinaryCodec
3031
legacySubspace types.ParamSubspace
32+
addressCodec address.Codec
3133

3234
ics4Wrapper porttypes.ICS4Wrapper
3335
channelKeeper types.ChannelKeeper
@@ -91,6 +93,16 @@ func (k Keeper) GetAuthority() string {
9193
return k.authority
9294
}
9395

96+
// GetAddressCodec returns the address codec used by the keeper.
97+
func (k *Keeper) GetAddressCodec() address.Codec {
98+
return k.addressCodec
99+
}
100+
101+
// SetAddressCodec sets the address codec used by the keeper.
102+
func (k *Keeper) SetAddressCodec(addressCodec address.Codec) {
103+
k.addressCodec = addressCodec
104+
}
105+
94106
// Logger returns a module-specific logger.
95107
func (Keeper) Logger(ctx sdk.Context) log.Logger {
96108
return ctx.Logger().With("module", "x/"+exported.ModuleName+"-"+types.ModuleName)

modules/apps/transfer/keeper/keeper_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,14 @@ func TestKeeperTestSuite(t *testing.T) {
4949
}
5050

5151
func (suite *KeeperTestSuite) TestNewKeeper() {
52+
ac := suite.chainA.GetSimApp().AccountKeeper.AddressCodec()
5253
testCases := []struct {
5354
name string
5455
instantiateFn func()
5556
panicMsg string
5657
}{
5758
{"success", func() {
58-
keeper.NewKeeper(
59+
k := keeper.NewKeeper(
5960
suite.chainA.GetSimApp().AppCodec(),
6061
runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(types.StoreKey)),
6162
suite.chainA.GetSimApp().GetSubspace(types.ModuleName),
@@ -66,9 +67,10 @@ func (suite *KeeperTestSuite) TestNewKeeper() {
6667
suite.chainA.GetSimApp().BankKeeper,
6768
suite.chainA.GetSimApp().ICAControllerKeeper.GetAuthority(),
6869
)
70+
k.SetAddressCodec(ac)
6971
}, ""},
7072
{"failure: transfer module account does not exist", func() {
71-
keeper.NewKeeper(
73+
k := keeper.NewKeeper(
7274
suite.chainA.GetSimApp().AppCodec(),
7375
runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(types.StoreKey)),
7476
suite.chainA.GetSimApp().GetSubspace(types.ModuleName),
@@ -79,9 +81,10 @@ func (suite *KeeperTestSuite) TestNewKeeper() {
7981
suite.chainA.GetSimApp().BankKeeper,
8082
suite.chainA.GetSimApp().ICAControllerKeeper.GetAuthority(),
8183
)
84+
k.SetAddressCodec(ac)
8285
}, "the IBC transfer module account has not been set"},
8386
{"failure: empty authority", func() {
84-
keeper.NewKeeper(
87+
k := keeper.NewKeeper(
8588
suite.chainA.GetSimApp().AppCodec(),
8689
runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(types.StoreKey)),
8790
suite.chainA.GetSimApp().GetSubspace(types.ModuleName),
@@ -92,6 +95,7 @@ func (suite *KeeperTestSuite) TestNewKeeper() {
9295
suite.chainA.GetSimApp().BankKeeper,
9396
"", // authority
9497
)
98+
k.SetAddressCodec(ac)
9599
}, "authority must be non-empty"},
96100
}
97101

modules/apps/transfer/keeper/msg_server.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@ func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.
2626
if !k.GetParams(ctx).SendEnabled {
2727
return nil, types.ErrSendDisabled
2828
}
29-
30-
sender, err := sdk.AccAddressFromBech32(msg.Sender)
29+
var sender []byte
30+
var err error
31+
if k.addressCodec == nil {
32+
sender, err = sdk.AccAddressFromBech32(msg.Sender)
33+
} else {
34+
sender, err = k.addressCodec.StringToBytes(msg.Sender)
35+
}
3136
if err != nil {
3237
return nil, err
3338
}
@@ -47,7 +52,7 @@ func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.
4752
return nil, err
4853
}
4954

50-
packetData := types.NewFungibleTokenPacketData(token.Denom.Path(), token.Amount, sender.String(), msg.Receiver, msg.Memo)
55+
packetData := types.NewFungibleTokenPacketData(token.Denom.Path(), token.Amount, msg.Sender, msg.Receiver, msg.Memo)
5156

5257
if err := packetData.ValidateBasic(); err != nil {
5358
return nil, errorsmod.Wrapf(err, "failed to validate %s packet data", types.V1)
@@ -60,7 +65,7 @@ func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.
6065
var sequence uint64
6166
if isIBCV1 {
6267
// if a V1 channel exists for the source channel, then use IBC V1 protocol
63-
sequence, err = k.transferV1Packet(ctx, msg.SourceChannel, token, msg.TimeoutHeight, msg.TimeoutTimestamp, packetData)
68+
sequence, err = k.transferV1Packet(ctx, msg.SourceChannel, token, msg.TimeoutHeight, msg.TimeoutTimestamp, sender, packetData)
6469
// telemetry for transfer occurs here, in IBC V2 this is done in the onSendPacket callback
6570
telemetry.ReportTransfer(msg.SourcePort, msg.SourceChannel, channel.Counterparty.PortId, channel.Counterparty.ChannelId, token)
6671
} else {
@@ -77,8 +82,8 @@ func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types.
7782
return &types.MsgTransferResponse{Sequence: sequence}, nil
7883
}
7984

80-
func (k Keeper) transferV1Packet(ctx sdk.Context, sourceChannel string, token types.Token, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, packetData types.FungibleTokenPacketData) (uint64, error) {
81-
if err := k.SendTransfer(ctx, types.PortID, sourceChannel, token, sdk.MustAccAddressFromBech32(packetData.Sender)); err != nil {
85+
func (k Keeper) transferV1Packet(ctx sdk.Context, sourceChannel string, token types.Token, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, sender sdk.AccAddress, packetData types.FungibleTokenPacketData) (uint64, error) {
86+
if err := k.SendTransfer(ctx, types.PortID, sourceChannel, token, sender); err != nil {
8287
return 0, err
8388
}
8489

modules/apps/transfer/keeper/msg_server_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ func (suite *KeeperTestSuite) TestMsgTransfer() {
6161
},
6262
types.ErrSendDisabled,
6363
},
64+
{
65+
"failure: zero amount",
66+
func() {
67+
msg.Token = sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)
68+
},
69+
types.ErrInvalidAmount,
70+
},
6471
{
6572
"failure: invalid sender",
6673
func() {

modules/apps/transfer/keeper/relay.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,14 @@ func (k Keeper) OnRecvPacket(
127127
return types.ErrReceiveDisabled
128128
}
129129

130-
receiver, err := sdk.AccAddressFromBech32(data.Receiver)
130+
var receiver []byte
131+
var err error
132+
if k.addressCodec == nil {
133+
receiver, err = sdk.AccAddressFromBech32(data.Receiver)
134+
} else {
135+
receiver, err = k.addressCodec.StringToBytes(data.Receiver)
136+
}
137+
131138
if err != nil {
132139
return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "failed to decode receiver address: %s", data.Receiver)
133140
}
@@ -195,7 +202,7 @@ func (k Keeper) OnRecvPacket(
195202
if err := k.BankKeeper.SendCoins(
196203
ctx, moduleAddr, receiver, sdk.NewCoins(voucher),
197204
); err != nil {
198-
return errorsmod.Wrapf(err, "failed to send coins to receiver %s", receiver.String())
205+
return errorsmod.Wrapf(err, "failed to send coins to receiver %s", data.Receiver)
199206
}
200207

201208
}
@@ -253,7 +260,7 @@ func (k Keeper) refundPacketTokens(
253260
) error {
254261
// NOTE: packet data type already checked in handler.go
255262

256-
sender, err := sdk.AccAddressFromBech32(data.Sender)
263+
sender, err := k.addressCodec.StringToBytes(data.Sender)
257264
if err != nil {
258265
return err
259266
}

modules/apps/transfer/keeper/relay_test.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package keeper_test
22

33
import (
4+
"encoding/hex"
45
"errors"
56
"fmt"
67
"strings"
@@ -47,19 +48,19 @@ func (suite *KeeperTestSuite) TestSendTransfer() {
4748
expError error
4849
}{
4950
{
50-
"successful transfer of native token",
51+
"success: transfer of native token",
5152
func() {},
5253
nil,
5354
},
5455
{
55-
"successful transfer of native token with memo",
56+
"success: transfer of native token with memo",
5657
func() {
5758
memo = "memo" //nolint:goconst
5859
},
5960
nil,
6061
},
6162
{
62-
"successful transfer of IBC token",
63+
"success: transfer of IBC token",
6364
func() {
6465
// send IBC token back to chainB
6566
denom := types.NewDenom(ibctesting.TestCoin.Denom, types.NewHop(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID))
@@ -70,7 +71,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() {
7071
nil,
7172
},
7273
{
73-
"successful transfer of IBC token with memo",
74+
"success: transfer of IBC token with memo",
7475
func() {
7576
// send IBC token back to chainB
7677
denom := types.NewDenom(ibctesting.TestCoin.Denom, types.NewHop(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID))
@@ -82,7 +83,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() {
8283
nil,
8384
},
8485
{
85-
"successful transfer of entire balance",
86+
"success: transfer of entire balance",
8687
func() {
8788
coin = sdk.NewCoin(coin.Denom, types.UnboundedSpendLimit())
8889
var ok bool
@@ -92,7 +93,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() {
9293
nil,
9394
},
9495
{
95-
"successful transfer of entire spendable balance with vesting account",
96+
"success: transfer of entire spendable balance with vesting account",
9697
func() {
9798
// create vesting account
9899
vestingAccPrivKey := secp256k1.GenPrivKey()
@@ -325,17 +326,27 @@ func (suite *KeeperTestSuite) TestOnRecvPacket_ReceiverIsNotSource() {
325326
expError error
326327
}{
327328
{
328-
"successful receive",
329+
"success: receive",
329330
func() {},
330331
nil,
331332
},
332333
{
333-
"successful receive with memo",
334+
"success: receive with memo",
334335
func() {
335336
packetData.Memo = "memo"
336337
},
337338
nil,
338339
},
340+
{
341+
"success: receive with hex receiver address",
342+
func() {
343+
suite.chainB.GetSimApp().TransferKeeper.SetAddressCodec(ibcmock.TestAddressCodec{})
344+
345+
receiver := sdk.MustAccAddressFromBech32(packetData.Receiver)
346+
packetData.Receiver = hex.EncodeToString(receiver.Bytes())
347+
},
348+
nil,
349+
},
339350
{
340351
"failure: mint zero coin",
341352
func() {

modules/apps/transfer/types/msgs.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ func NewMsgUpdateParams(signer string, params Params) *MsgUpdateParams {
3434

3535
// ValidateBasic implements sdk.Msg
3636
func (msg MsgUpdateParams) ValidateBasic() error {
37-
_, err := sdk.AccAddressFromBech32(msg.Signer)
38-
if err != nil {
39-
return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
37+
if strings.TrimSpace(msg.Signer) == "" {
38+
return errorsmod.Wrap(ibcerrors.ErrInvalidAddress, "missing sender address")
4039
}
4140

4241
return nil
@@ -96,9 +95,8 @@ func (msg MsgTransfer) ValidateBasic() error {
9695
return errorsmod.Wrap(ibcerrors.ErrInvalidCoins, msg.Token.String())
9796
}
9897

99-
_, err := sdk.AccAddressFromBech32(msg.Sender)
100-
if err != nil {
101-
return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
98+
if strings.TrimSpace(msg.Sender) == "" {
99+
return errorsmod.Wrap(ibcerrors.ErrInvalidAddress, "missing sender address")
102100
}
103101
if strings.TrimSpace(msg.Receiver) == "" {
104102
return errorsmod.Wrap(ibcerrors.ErrInvalidAddress, "missing recipient address")

modules/apps/transfer/types/msgs_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ func TestMsgUpdateParamsValidateBasic(t *testing.T) {
111111
expError error
112112
}{
113113
{"success: valid signer and valid params", types.NewMsgUpdateParams(ibctesting.TestAccAddress, types.DefaultParams()), nil},
114-
{"failure: invalid signer with valid params", types.NewMsgUpdateParams(invalidAddress, types.DefaultParams()), ibcerrors.ErrInvalidAddress},
115114
{"failure: empty signer with valid params", types.NewMsgUpdateParams(emptyAddr, types.DefaultParams()), ibcerrors.ErrInvalidAddress},
116115
}
117116

0 commit comments

Comments
 (0)