Summary of Bug
types.GenesisState.Validate and keeper.InitGenesis in modules/apps/27-gmp validate RegisteredICS27Account.AccountId.Sender with sdk.AccAddressFromBech32:
// modules/apps/27-gmp/types/genesis.go
if _, err := sdk.AccAddressFromBech32(account.AccountId.Sender); err != nil {
return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "string could not be parsed as address: %v", err)
}
The sender of a GMP packet is an identifier on the counterparty chain — an EVM hex address (0x1234…) or a bech32 address with a foreign prefix (osmo1…). GMPPacketData.ValidateBasic and OnRecvPacket accept it as an opaque string (non-empty, <= MaximumSenderLength), so the account is created and stored. ExportGenesis then produces state that fails its own Validate and cannot be passed to InitGenesis.
Expected Behaviour
An exported genesis should round-trip: ExportGenesis → Validate → InitGenesis. The sender should be validated the same way it is validated on the packet path (presence and length), not as a local bech32 address.
Impact
As soon as one ICS27 account has been created by a remote sender, <appd> export followed by validate-genesis / a restart from the exported genesis fails with decoding bech32 failed: … invalid address.
Version
main (8a8d8134), v11.x.
Steps to Reproduce
k := chain.GetSimApp().GMPKeeper
data := types.NewGMPPacketData("0x1234567890abcdef1234567890abcdef12345678", "", []byte("salt"), []byte{}, "")
_, _ = k.OnRecvPacket(ctx, &data, "07-tendermint-0") // account is created before the (empty) payload fails
gs, _ := k.ExportGenesis(ctx)
err := gs.Validate()
// err: string could not be parsed as address: decoding bech32 failed: invalid checksum ...: invalid address
I have a small patch with an AccountIdentifier.Validate helper (client ID + non-empty/bounded sender + salt length, shared by Validate and InitGenesis) and an export → validate → import regression test; happy to open the PR.
Summary of Bug
types.GenesisState.Validateandkeeper.InitGenesisinmodules/apps/27-gmpvalidateRegisteredICS27Account.AccountId.Senderwithsdk.AccAddressFromBech32:The sender of a GMP packet is an identifier on the counterparty chain — an EVM hex address (
0x1234…) or a bech32 address with a foreign prefix (osmo1…).GMPPacketData.ValidateBasicandOnRecvPacketaccept it as an opaque string (non-empty,<= MaximumSenderLength), so the account is created and stored.ExportGenesisthen produces state that fails its ownValidateand cannot be passed toInitGenesis.Expected Behaviour
An exported genesis should round-trip:
ExportGenesis→Validate→InitGenesis. The sender should be validated the same way it is validated on the packet path (presence and length), not as a local bech32 address.Impact
As soon as one ICS27 account has been created by a remote sender,
<appd> exportfollowed byvalidate-genesis/ a restart from the exported genesis fails withdecoding bech32 failed: … invalid address.Version
main(8a8d8134), v11.x.Steps to Reproduce
I have a small patch with an
AccountIdentifier.Validatehelper (client ID + non-empty/bounded sender + salt length, shared byValidateandInitGenesis) and an export → validate → import regression test; happy to open the PR.