diff --git a/modules/apps/27-interchain-accounts/types/account_test.go b/modules/apps/27-interchain-accounts/types/account_test.go index 074379cc33a..d9162f11754 100644 --- a/modules/apps/27-interchain-accounts/types/account_test.go +++ b/modules/apps/27-interchain-accounts/types/account_test.go @@ -78,7 +78,7 @@ func (suite *TypesTestSuite) TestValidateAccountAddress() { }, { "address is too long", - ibctesting.LongString, + ibctesting.GenerateString(uint(types.DefaultMaxAddrLength) + 1), false, }, } diff --git a/modules/apps/27-interchain-accounts/types/port.go b/modules/apps/27-interchain-accounts/types/port.go index 54949b8a1c4..dbe1085d59a 100644 --- a/modules/apps/27-interchain-accounts/types/port.go +++ b/modules/apps/27-interchain-accounts/types/port.go @@ -7,11 +7,17 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) +const MaximumOwnerLength = 2048 // maximum length of the owner in bytes (value chosen arbitrarily) + // NewControllerPortID creates and returns a new prefixed controller port identifier using the provided owner string func NewControllerPortID(owner string) (string, error) { if strings.TrimSpace(owner) == "" { return "", sdkerrors.Wrap(ErrInvalidAccountAddress, "owner address cannot be empty") } + if len(owner) > MaximumOwnerLength { + return "", sdkerrors.Wrapf(ErrInvalidAccountAddress, "owner address must not exceed %d bytes", MaximumOwnerLength) + } + return fmt.Sprint(PortPrefix, owner), nil } diff --git a/modules/apps/27-interchain-accounts/types/port_test.go b/modules/apps/27-interchain-accounts/types/port_test.go index a5dc2532b60..3e49f740e19 100644 --- a/modules/apps/27-interchain-accounts/types/port_test.go +++ b/modules/apps/27-interchain-accounts/types/port_test.go @@ -33,6 +33,14 @@ func (suite *TypesTestSuite) TestNewControllerPortID() { "", false, }, + { + "owner address is too long", + func() { + owner = ibctesting.GenerateString(types.MaximumOwnerLength + 100) + }, + "", + false, + }, } for _, tc := range testCases { @@ -45,6 +53,9 @@ func (suite *TypesTestSuite) TestNewControllerPortID() { tc.malleate() // malleate mutates test data + // print owner + fmt.Println("OWNER: ", owner) + portID, err := types.NewControllerPortID(owner) if tc.expPass { diff --git a/modules/apps/29-fee/transfer_test.go b/modules/apps/29-fee/transfer_test.go index 12a7a556e66..d759603ea12 100644 --- a/modules/apps/29-fee/transfer_test.go +++ b/modules/apps/29-fee/transfer_test.go @@ -30,7 +30,7 @@ func (suite *FeeTestSuite) TestFeeTransfer() { msgs := []sdk.Msg{ types.NewMsgPayPacketFee(fee, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, suite.chainA.SenderAccount.GetAddress().String(), nil), - transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, coin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 100), 0), + transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, coin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 100), 0, ""), } res, err := suite.chainA.SendMsgs(msgs...) suite.Require().NoError(err) // message committed diff --git a/modules/apps/29-fee/types/msgs.go b/modules/apps/29-fee/types/msgs.go index e008bddfed5..ff707c7d2a4 100644 --- a/modules/apps/29-fee/types/msgs.go +++ b/modules/apps/29-fee/types/msgs.go @@ -16,6 +16,8 @@ const ( TypeMsgPayPacketFeeAsync = "payPacketFeeAsync" ) +const MaximumCounterpartyPayeeLength = 2048 // maximum length of the counterparty payee in bytes (value chosen arbitrarily) + // NewMsgRegisterPayee creates a new instance of MsgRegisterPayee func NewMsgRegisterPayee(portID, channelID, relayerAddr, payeeAddr string) *MsgRegisterPayee { return &MsgRegisterPayee{ @@ -92,6 +94,10 @@ func (msg MsgRegisterCounterpartyPayee) ValidateBasic() error { return ErrCounterpartyPayeeEmpty } + if len(msg.CounterpartyPayee) > MaximumCounterpartyPayeeLength { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "counterparty payee address must not exceed %d bytes", MaximumCounterpartyPayeeLength) + } + return nil } diff --git a/modules/apps/29-fee/types/msgs_test.go b/modules/apps/29-fee/types/msgs_test.go index a32f91f24d9..2ec0080bcdc 100644 --- a/modules/apps/29-fee/types/msgs_test.go +++ b/modules/apps/29-fee/types/msgs_test.go @@ -135,6 +135,13 @@ func TestMsgRegisterCountepartyPayeeValidation(t *testing.T) { }, false, }, + { + "invalid counterparty payee address: too long", + func() { + msg.CounterpartyPayee = ibctesting.GenerateString(types.MaximumCounterpartyPayeeLength + 1) + }, + false, + }, } for i, tc := range testCases { diff --git a/modules/apps/transfer/client/cli/tx.go b/modules/apps/transfer/client/cli/tx.go index f2d5ad914d1..38e2b77d697 100644 --- a/modules/apps/transfer/client/cli/tx.go +++ b/modules/apps/transfer/client/cli/tx.go @@ -117,7 +117,7 @@ corresponding to the counterparty channel. Any timeout set to 0 is disabled.`), } msg := types.NewMsgTransfer( - srcPort, srcChannel, coin, sender, receiver, timeoutHeight, timeoutTimestamp, + srcPort, srcChannel, coin, sender, receiver, timeoutHeight, timeoutTimestamp, "", ) msg.Memo = memo diff --git a/modules/apps/transfer/keeper/msg_server_test.go b/modules/apps/transfer/keeper/msg_server_test.go index 5d4a716a387..b85fc9f5bff 100644 --- a/modules/apps/transfer/keeper/msg_server_test.go +++ b/modules/apps/transfer/keeper/msg_server_test.go @@ -77,6 +77,7 @@ func (suite *KeeperTestSuite) TestMsgTransfer() { path.EndpointA.ChannelID, coin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainB.GetTimeoutHeight(), 0, // only use timeout height + "", ) msg.Memo = "memo" diff --git a/modules/apps/transfer/keeper/relay_test.go b/modules/apps/transfer/keeper/relay_test.go index aaf0f9c3a18..a34e42b979d 100644 --- a/modules/apps/transfer/keeper/relay_test.go +++ b/modules/apps/transfer/keeper/relay_test.go @@ -120,7 +120,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() { if !tc.sendFromSource { // send coin from chainB to chainA coinFromBToA := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinFromBToA, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0) + transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinFromBToA, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0, "") _, err = suite.chainB.SendMsgs(transferMsg) suite.Require().NoError(err) // message committed @@ -226,7 +226,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { if tc.recvIsSource { // send coin from chainB to chainA, receive them, acknowledge them, and send back to chainB coinFromBToA := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100)) - transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinFromBToA, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0) + transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, coinFromBToA, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), clienttypes.NewHeight(0, 110), 0, "") res, err := suite.chainB.SendMsgs(transferMsg) suite.Require().NoError(err) // message committed @@ -245,7 +245,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { } // send coin from chainA to chainB - transferMsg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, sdk.NewCoin(trace.IBCDenom(), amount), suite.chainA.SenderAccount.GetAddress().String(), receiver, clienttypes.NewHeight(0, 110), 0) + transferMsg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, sdk.NewCoin(trace.IBCDenom(), amount), suite.chainA.SenderAccount.GetAddress().String(), receiver, clienttypes.NewHeight(0, 110), 0, "") transferMsg.Memo = memo _, err := suite.chainA.SendMsgs(transferMsg) suite.Require().NoError(err) // message committed diff --git a/modules/apps/transfer/transfer_test.go b/modules/apps/transfer/transfer_test.go index d1089f0ee82..e51a82a2f0d 100644 --- a/modules/apps/transfer/transfer_test.go +++ b/modules/apps/transfer/transfer_test.go @@ -54,7 +54,7 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { coinToSendToB := sdk.NewCoin(sdk.DefaultBondDenom, amount) // send from chainA to chainB - msg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, coinToSendToB, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0) + msg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, coinToSendToB, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0, "") res, err := suite.chainA.SendMsgs(msg) suite.Require().NoError(err) // message committed @@ -80,7 +80,7 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { suite.coordinator.Setup(pathBtoC) // send from chainB to chainC - msg = types.NewMsgTransfer(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, coinSentFromAToB, suite.chainB.SenderAccount.GetAddress().String(), suite.chainC.SenderAccount.GetAddress().String(), timeoutHeight, 0) + msg = types.NewMsgTransfer(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, coinSentFromAToB, suite.chainB.SenderAccount.GetAddress().String(), suite.chainC.SenderAccount.GetAddress().String(), timeoutHeight, 0, "") res, err = suite.chainB.SendMsgs(msg) suite.Require().NoError(err) // message committed @@ -104,7 +104,7 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { suite.Require().Zero(balance.Amount.Int64()) // send from chainC back to chainB - msg = types.NewMsgTransfer(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, coinSentFromBToC, suite.chainC.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0) + msg = types.NewMsgTransfer(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, coinSentFromBToC, suite.chainC.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0, "") res, err = suite.chainC.SendMsgs(msg) suite.Require().NoError(err) // message committed diff --git a/modules/apps/transfer/types/errors.go b/modules/apps/transfer/types/errors.go index 0f0cb7c42a4..2a8d01646fe 100644 --- a/modules/apps/transfer/types/errors.go +++ b/modules/apps/transfer/types/errors.go @@ -14,4 +14,5 @@ var ( ErrSendDisabled = sdkerrors.Register(ModuleName, 7, "fungible token transfers from this chain are disabled") ErrReceiveDisabled = sdkerrors.Register(ModuleName, 8, "fungible token transfers to this chain are disabled") ErrMaxTransferChannels = sdkerrors.Register(ModuleName, 9, "max transfer channels") + ErrInvalidMemo = sdkerrors.Register(ModuleName, 10, "invalid memo") ) diff --git a/modules/apps/transfer/types/msgs.go b/modules/apps/transfer/types/msgs.go index 5df624d43d0..8ad44d83c75 100644 --- a/modules/apps/transfer/types/msgs.go +++ b/modules/apps/transfer/types/msgs.go @@ -15,6 +15,11 @@ const ( TypeMsgTransfer = "transfer" ) +const ( + MaximumReceiverLength = 2048 // maximum length of the receiver address in bytes (value chosen arbitrarily) + MaximumMemoLength = 32768 // maximum length of the memo in bytes (value chosen arbitrarily) +) + // NewMsgTransfer creates a new MsgTransfer instance // //nolint:interfacer @@ -22,6 +27,7 @@ func NewMsgTransfer( sourcePort, sourceChannel string, token sdk.Coin, sender, receiver string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, + memo string, ) *MsgTransfer { return &MsgTransfer{ SourcePort: sourcePort, @@ -31,6 +37,7 @@ func NewMsgTransfer( Receiver: receiver, TimeoutHeight: timeoutHeight, TimeoutTimestamp: timeoutTimestamp, + Memo: memo, } } @@ -69,6 +76,12 @@ func (msg MsgTransfer) ValidateBasic() error { if strings.TrimSpace(msg.Receiver) == "" { return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "missing recipient address") } + if len(msg.Receiver) > MaximumReceiverLength { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "recipient address must not exceed %d bytes", MaximumReceiverLength) + } + if len(msg.Memo) > MaximumMemoLength { + return sdkerrors.Wrapf(ErrInvalidMemo, "memo must not exceed %d bytes", MaximumMemoLength) + } return ValidateIBCDenom(msg.Token.Denom) } diff --git a/modules/apps/transfer/types/msgs_test.go b/modules/apps/transfer/types/msgs_test.go index 929de3a4d6f..53e88a9c078 100644 --- a/modules/apps/transfer/types/msgs_test.go +++ b/modules/apps/transfer/types/msgs_test.go @@ -1,4 +1,4 @@ -package types +package types_test import ( "fmt" @@ -8,7 +8,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v4/modules/core/02-client/types" + ibctesting "github.com/cosmos/ibc-go/v4/testing" ) // define constants used for testing @@ -41,20 +43,20 @@ var ( // TestMsgTransferRoute tests Route for MsgTransfer func TestMsgTransferRoute(t *testing.T) { - msg := NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0) + msg := types.NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0, "") - require.Equal(t, RouterKey, msg.Route()) + require.Equal(t, types.RouterKey, msg.Route()) } // TestMsgTransferType tests Type for MsgTransfer func TestMsgTransferType(t *testing.T) { - msg := NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0) + msg := types.NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0, "") require.Equal(t, "transfer", msg.Type()) } func TestMsgTransferGetSignBytes(t *testing.T) { - msg := NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0) + msg := types.NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0, "") expected := fmt.Sprintf(`{"type":"cosmos-sdk/MsgTransfer","value":{"receiver":"%s","sender":"%s","source_channel":"testchannel","source_port":"testportid","timeout_height":{"revision_height":"10"},"token":{"amount":"100","denom":"atom"}}}`, addr2, addr1) require.NotPanics(t, func() { res := msg.GetSignBytes() @@ -66,23 +68,24 @@ func TestMsgTransferGetSignBytes(t *testing.T) { func TestMsgTransferValidation(t *testing.T) { testCases := []struct { name string - msg *MsgTransfer + msg *types.MsgTransfer expPass bool }{ - {"valid msg with base denom", NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0), true}, - {"valid msg with trace hash", NewMsgTransfer(validPort, validChannel, ibcCoin, addr1, addr2, timeoutHeight, 0), true}, - {"invalid ibc denom", NewMsgTransfer(validPort, validChannel, invalidIBCCoin, addr1, addr2, timeoutHeight, 0), false}, - {"too short port id", NewMsgTransfer(invalidShortPort, validChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"too long port id", NewMsgTransfer(invalidLongPort, validChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"port id contains non-alpha", NewMsgTransfer(invalidPort, validChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"too short channel id", NewMsgTransfer(validPort, invalidShortChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"too long channel id", NewMsgTransfer(validPort, invalidLongChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"channel id contains non-alpha", NewMsgTransfer(validPort, invalidChannel, coin, addr1, addr2, timeoutHeight, 0), false}, - {"invalid denom", NewMsgTransfer(validPort, validChannel, invalidDenomCoin, addr1, addr2, timeoutHeight, 0), false}, - {"zero coin", NewMsgTransfer(validPort, validChannel, zeroCoin, addr1, addr2, timeoutHeight, 0), false}, - {"missing sender address", NewMsgTransfer(validPort, validChannel, coin, emptyAddr, addr2, timeoutHeight, 0), false}, - {"missing recipient address", NewMsgTransfer(validPort, validChannel, coin, addr1, "", timeoutHeight, 0), false}, - {"empty coin", NewMsgTransfer(validPort, validChannel, sdk.Coin{}, addr1, addr2, timeoutHeight, 0), false}, + {"valid msg with base denom", types.NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0, ""), true}, + {"valid msg with trace hash", types.NewMsgTransfer(validPort, validChannel, ibcCoin, addr1, addr2, timeoutHeight, 0, ""), true}, + {"invalid ibc denom", types.NewMsgTransfer(validPort, validChannel, invalidIBCCoin, addr1, addr2, timeoutHeight, 0, ""), false}, + {"too short port id", types.NewMsgTransfer(invalidShortPort, validChannel, coin, addr1, addr2, timeoutHeight, 0, ""), false}, + {"too long port id", types.NewMsgTransfer(invalidLongPort, validChannel, coin, addr1, addr2, timeoutHeight, 0, ""), false}, + {"too long memo", types.NewMsgTransfer(validPort, validChannel, coin, addr1, addr2, timeoutHeight, 0, ibctesting.GenerateString(types.MaximumMemoLength+1)), false}, + {"port id contains non-alpha", types.NewMsgTransfer(invalidPort, validChannel, coin, addr1, addr2, timeoutHeight, 0, ""), false}, + {"too short channel id", types.NewMsgTransfer(validPort, invalidShortChannel, coin, addr1, addr2, timeoutHeight, 0, ""), false}, + {"too long channel id", types.NewMsgTransfer(validPort, invalidLongChannel, coin, addr1, addr2, timeoutHeight, 0, ""), false}, + {"channel id contains non-alpha", types.NewMsgTransfer(validPort, invalidChannel, coin, addr1, addr2, timeoutHeight, 0, ""), false}, + {"invalid denom", types.NewMsgTransfer(validPort, validChannel, invalidDenomCoin, addr1, addr2, timeoutHeight, 0, ""), false}, + {"zero coin", types.NewMsgTransfer(validPort, validChannel, zeroCoin, addr1, addr2, timeoutHeight, 0, ""), false}, + {"missing sender address", types.NewMsgTransfer(validPort, validChannel, coin, emptyAddr, addr2, timeoutHeight, 0, ""), false}, + {"missing recipient address", types.NewMsgTransfer(validPort, validChannel, coin, addr1, "", timeoutHeight, 0, ""), false}, + {"empty coin", types.NewMsgTransfer(validPort, validChannel, sdk.Coin{}, addr1, addr2, timeoutHeight, 0, ""), false}, } for i, tc := range testCases { @@ -99,7 +102,7 @@ func TestMsgTransferValidation(t *testing.T) { func TestMsgTransferGetSigners(t *testing.T) { addr := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) - msg := NewMsgTransfer(validPort, validChannel, coin, addr.String(), addr2, timeoutHeight, 0) + msg := types.NewMsgTransfer(validPort, validChannel, coin, addr.String(), addr2, timeoutHeight, 0, "") res := msg.GetSigners() require.Equal(t, []sdk.AccAddress{addr}, res) diff --git a/modules/apps/transfer/types/packet_test.go b/modules/apps/transfer/types/packet_test.go index e5d21d648d2..0bf70168fd8 100644 --- a/modules/apps/transfer/types/packet_test.go +++ b/modules/apps/transfer/types/packet_test.go @@ -1,8 +1,9 @@ -package types +package types_test import ( "testing" + "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/stretchr/testify/require" ) @@ -17,18 +18,18 @@ const ( func TestFungibleTokenPacketDataValidateBasic(t *testing.T) { testCases := []struct { name string - packetData FungibleTokenPacketData + packetData types.FungibleTokenPacketData expPass bool }{ - {"valid packet", NewFungibleTokenPacketData(denom, amount, addr1, addr2), true}, - {"valid packet with large amount", NewFungibleTokenPacketData(denom, largeAmount, addr1, addr2), true}, - {"invalid denom", NewFungibleTokenPacketData("", amount, addr1, addr2), false}, - {"invalid empty amount", NewFungibleTokenPacketData(denom, "", addr1, addr2), false}, - {"invalid zero amount", NewFungibleTokenPacketData(denom, "0", addr1, addr2), false}, - {"invalid negative amount", NewFungibleTokenPacketData(denom, "-1", addr1, addr2), false}, - {"invalid large amount", NewFungibleTokenPacketData(denom, invalidLargeAmount, addr1, addr2), false}, - {"missing sender address", NewFungibleTokenPacketData(denom, amount, emptyAddr, addr2), false}, - {"missing recipient address", NewFungibleTokenPacketData(denom, amount, addr1, emptyAddr), false}, + {"valid packet", types.NewFungibleTokenPacketData(denom, amount, addr1, addr2), true}, + {"valid packet with large amount", types.NewFungibleTokenPacketData(denom, largeAmount, addr1, addr2), true}, + {"invalid denom", types.NewFungibleTokenPacketData("", amount, addr1, addr2), false}, + {"invalid empty amount", types.NewFungibleTokenPacketData(denom, "", addr1, addr2), false}, + {"invalid zero amount", types.NewFungibleTokenPacketData(denom, "0", addr1, addr2), false}, + {"invalid negative amount", types.NewFungibleTokenPacketData(denom, "-1", addr1, addr2), false}, + {"invalid large amount", types.NewFungibleTokenPacketData(denom, invalidLargeAmount, addr1, addr2), false}, + {"missing sender address", types.NewFungibleTokenPacketData(denom, amount, emptyAddr, addr2), false}, + {"missing recipient address", types.NewFungibleTokenPacketData(denom, amount, addr1, emptyAddr), false}, } for i, tc := range testCases { diff --git a/modules/apps/transfer/types/params_test.go b/modules/apps/transfer/types/params_test.go index 825efb825c1..637f1a070dc 100644 --- a/modules/apps/transfer/types/params_test.go +++ b/modules/apps/transfer/types/params_test.go @@ -1,12 +1,13 @@ -package types +package types_test import ( "testing" + "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/stretchr/testify/require" ) func TestValidateParams(t *testing.T) { - require.NoError(t, DefaultParams().Validate()) - require.NoError(t, NewParams(true, false).Validate()) + require.NoError(t, types.DefaultParams().Validate()) + require.NoError(t, types.NewParams(true, false).Validate()) } diff --git a/modules/apps/transfer/types/trace_test.go b/modules/apps/transfer/types/trace_test.go index ba0690423bd..910d454d954 100644 --- a/modules/apps/transfer/types/trace_test.go +++ b/modules/apps/transfer/types/trace_test.go @@ -1,8 +1,9 @@ -package types +package types_test import ( "testing" + "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/stretchr/testify/require" ) @@ -10,46 +11,46 @@ func TestParseDenomTrace(t *testing.T) { testCases := []struct { name string denom string - expTrace DenomTrace + expTrace types.DenomTrace }{ - {"empty denom", "", DenomTrace{}}, - {"base denom", "uatom", DenomTrace{BaseDenom: "uatom"}}, - {"base denom ending with '/'", "uatom/", DenomTrace{BaseDenom: "uatom/"}}, - {"base denom with single '/'s", "gamm/pool/1", DenomTrace{BaseDenom: "gamm/pool/1"}}, - {"base denom with double '/'s", "gamm//pool//1", DenomTrace{BaseDenom: "gamm//pool//1"}}, - {"trace info", "transfer/channel-1/uatom", DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1"}}, - {"trace info with custom port", "customtransfer/channel-1/uatom", DenomTrace{BaseDenom: "uatom", Path: "customtransfer/channel-1"}}, - {"trace info with base denom ending in '/'", "transfer/channel-1/uatom/", DenomTrace{BaseDenom: "uatom/", Path: "transfer/channel-1"}}, - {"trace info with single '/' in base denom", "transfer/channel-1/erc20/0x85bcBCd7e79Ec36f4fBBDc54F90C643d921151AA", DenomTrace{BaseDenom: "erc20/0x85bcBCd7e79Ec36f4fBBDc54F90C643d921151AA", Path: "transfer/channel-1"}}, - {"trace info with multiple '/'s in base denom", "transfer/channel-1/gamm/pool/1", DenomTrace{BaseDenom: "gamm/pool/1", Path: "transfer/channel-1"}}, - {"trace info with multiple double '/'s in base denom", "transfer/channel-1/gamm//pool//1", DenomTrace{BaseDenom: "gamm//pool//1", Path: "transfer/channel-1"}}, - {"trace info with multiple port/channel pairs", "transfer/channel-1/transfer/channel-2/uatom", DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1/transfer/channel-2"}}, - {"trace info with multiple custom ports", "customtransfer/channel-1/alternativetransfer/channel-2/uatom", DenomTrace{BaseDenom: "uatom", Path: "customtransfer/channel-1/alternativetransfer/channel-2"}}, - {"incomplete path", "transfer/uatom", DenomTrace{BaseDenom: "transfer/uatom"}}, - {"invalid path (1)", "transfer//uatom", DenomTrace{BaseDenom: "transfer//uatom", Path: ""}}, - {"invalid path (2)", "channel-1/transfer/uatom", DenomTrace{BaseDenom: "channel-1/transfer/uatom"}}, - {"invalid path (3)", "uatom/transfer", DenomTrace{BaseDenom: "uatom/transfer"}}, - {"invalid path (4)", "transfer/channel-1", DenomTrace{BaseDenom: "transfer/channel-1"}}, - {"invalid path (5)", "transfer/channel-1/", DenomTrace{Path: "transfer/channel-1"}}, - {"invalid path (6)", "transfer/channel-1/transfer", DenomTrace{BaseDenom: "transfer", Path: "transfer/channel-1"}}, - {"invalid path (7)", "transfer/channel-1/transfer/channel-2", DenomTrace{Path: "transfer/channel-1/transfer/channel-2"}}, - {"invalid path (8)", "transfer/channelToA/uatom", DenomTrace{BaseDenom: "transfer/channelToA/uatom", Path: ""}}, + {"empty denom", "", types.DenomTrace{}}, + {"base denom", "uatom", types.DenomTrace{BaseDenom: "uatom"}}, + {"base denom ending with '/'", "uatom/", types.DenomTrace{BaseDenom: "uatom/"}}, + {"base denom with single '/'s", "gamm/pool/1", types.DenomTrace{BaseDenom: "gamm/pool/1"}}, + {"base denom with double '/'s", "gamm//pool//1", types.DenomTrace{BaseDenom: "gamm//pool//1"}}, + {"trace info", "transfer/channel-1/uatom", types.DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1"}}, + {"trace info with custom port", "customtransfer/channel-1/uatom", types.DenomTrace{BaseDenom: "uatom", Path: "customtransfer/channel-1"}}, + {"trace info with base denom ending in '/'", "transfer/channel-1/uatom/", types.DenomTrace{BaseDenom: "uatom/", Path: "transfer/channel-1"}}, + {"trace info with single '/' in base denom", "transfer/channel-1/erc20/0x85bcBCd7e79Ec36f4fBBDc54F90C643d921151AA", types.DenomTrace{BaseDenom: "erc20/0x85bcBCd7e79Ec36f4fBBDc54F90C643d921151AA", Path: "transfer/channel-1"}}, + {"trace info with multiple '/'s in base denom", "transfer/channel-1/gamm/pool/1", types.DenomTrace{BaseDenom: "gamm/pool/1", Path: "transfer/channel-1"}}, + {"trace info with multiple double '/'s in base denom", "transfer/channel-1/gamm//pool//1", types.DenomTrace{BaseDenom: "gamm//pool//1", Path: "transfer/channel-1"}}, + {"trace info with multiple port/channel pairs", "transfer/channel-1/transfer/channel-2/uatom", types.DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1/transfer/channel-2"}}, + {"trace info with multiple custom ports", "customtransfer/channel-1/alternativetransfer/channel-2/uatom", types.DenomTrace{BaseDenom: "uatom", Path: "customtransfer/channel-1/alternativetransfer/channel-2"}}, + {"incomplete path", "transfer/uatom", types.DenomTrace{BaseDenom: "transfer/uatom"}}, + {"invalid path (1)", "transfer//uatom", types.DenomTrace{BaseDenom: "transfer//uatom", Path: ""}}, + {"invalid path (2)", "channel-1/transfer/uatom", types.DenomTrace{BaseDenom: "channel-1/transfer/uatom"}}, + {"invalid path (3)", "uatom/transfer", types.DenomTrace{BaseDenom: "uatom/transfer"}}, + {"invalid path (4)", "transfer/channel-1", types.DenomTrace{BaseDenom: "transfer/channel-1"}}, + {"invalid path (5)", "transfer/channel-1/", types.DenomTrace{Path: "transfer/channel-1"}}, + {"invalid path (6)", "transfer/channel-1/transfer", types.DenomTrace{BaseDenom: "transfer", Path: "transfer/channel-1"}}, + {"invalid path (7)", "transfer/channel-1/transfer/channel-2", types.DenomTrace{Path: "transfer/channel-1/transfer/channel-2"}}, + {"invalid path (8)", "transfer/channelToA/uatom", types.DenomTrace{BaseDenom: "transfer/channelToA/uatom", Path: ""}}, } for _, tc := range testCases { - trace := ParseDenomTrace(tc.denom) + trace := types.ParseDenomTrace(tc.denom) require.Equal(t, tc.expTrace, trace, tc.name) } } -func TestDenomTrace_IBCDenom(t *testing.T) { +func TestTrace_IBCDenom(t *testing.T) { testCases := []struct { name string - trace DenomTrace + trace types.DenomTrace expDenom string }{ - {"base denom", DenomTrace{BaseDenom: "uatom"}, "uatom"}, - {"trace info", DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1"}, "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9"}, + {"base denom", types.DenomTrace{BaseDenom: "uatom"}, "uatom"}, + {"trace info", types.DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1"}, "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9"}, } for _, tc := range testCases { @@ -58,22 +59,22 @@ func TestDenomTrace_IBCDenom(t *testing.T) { } } -func TestDenomTrace_Validate(t *testing.T) { +func TestTrace_Validate(t *testing.T) { testCases := []struct { name string - trace DenomTrace + trace types.DenomTrace expError bool }{ - {"base denom only", DenomTrace{BaseDenom: "uatom"}, false}, - {"base denom only with single '/'", DenomTrace{BaseDenom: "erc20/0x85bcBCd7e79Ec36f4fBBDc54F90C643d921151AA"}, false}, - {"base denom only with multiple '/'s", DenomTrace{BaseDenom: "gamm/pool/1"}, false}, - {"empty DenomTrace", DenomTrace{}, true}, - {"valid single trace info", DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1"}, false}, - {"valid multiple trace info", DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1/transfer/channel-2"}, false}, - {"single trace identifier", DenomTrace{BaseDenom: "uatom", Path: "transfer"}, true}, - {"invalid port ID", DenomTrace{BaseDenom: "uatom", Path: "(transfer)/channel-1"}, true}, - {"invalid channel ID", DenomTrace{BaseDenom: "uatom", Path: "transfer/(channel-1)"}, true}, - {"empty base denom with trace", DenomTrace{BaseDenom: "", Path: "transfer/channel-1"}, true}, + {"base denom only", types.DenomTrace{BaseDenom: "uatom"}, false}, + {"base denom only with single '/'", types.DenomTrace{BaseDenom: "erc20/0x85bcBCd7e79Ec36f4fBBDc54F90C643d921151AA"}, false}, + {"base denom only with multiple '/'s", types.DenomTrace{BaseDenom: "gamm/pool/1"}, false}, + {"empty types.DenomTrace", types.DenomTrace{}, true}, + {"valid single trace info", types.DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1"}, false}, + {"valid multiple trace info", types.DenomTrace{BaseDenom: "uatom", Path: "transfer/channel-1/transfer/channel-2"}, false}, + {"single trace identifier", types.DenomTrace{BaseDenom: "uatom", Path: "transfer"}, true}, + {"invalid port ID", types.DenomTrace{BaseDenom: "uatom", Path: "(transfer)/channel-1"}, true}, + {"invalid channel ID", types.DenomTrace{BaseDenom: "uatom", Path: "transfer/(channel-1)"}, true}, + {"empty base denom with trace", types.DenomTrace{BaseDenom: "", Path: "transfer/channel-1"}, true}, } for _, tc := range testCases { @@ -89,20 +90,20 @@ func TestDenomTrace_Validate(t *testing.T) { func TestTraces_Validate(t *testing.T) { testCases := []struct { name string - traces Traces + traces types.Traces expError bool }{ - {"empty Traces", Traces{}, false}, - {"valid multiple trace info", Traces{{BaseDenom: "uatom", Path: "transfer/channel-1/transfer/channel-2"}}, false}, + {"empty Traces", types.Traces{}, false}, + {"valid multiple trace info", types.Traces{{BaseDenom: "uatom", Path: "transfer/channel-1/transfer/channel-2"}}, false}, { "valid multiple trace info", - Traces{ + types.Traces{ {BaseDenom: "uatom", Path: "transfer/channel-1/transfer/channel-2"}, {BaseDenom: "uatom", Path: "transfer/channel-1/transfer/channel-2"}, }, true, }, - {"empty base denom with trace", Traces{{BaseDenom: "", Path: "transfer/channel-1"}}, true}, + {"empty base denom with trace", types.Traces{{BaseDenom: "", Path: "transfer/channel-1"}}, true}, } for _, tc := range testCases { @@ -134,7 +135,7 @@ func TestValidatePrefixedDenom(t *testing.T) { } for _, tc := range testCases { - err := ValidatePrefixedDenom(tc.denom) + err := types.ValidatePrefixedDenom(tc.denom) if tc.expError { require.Error(t, err, tc.name) } else { @@ -162,7 +163,7 @@ func TestValidateIBCDenom(t *testing.T) { } for _, tc := range testCases { - err := ValidateIBCDenom(tc.denom) + err := types.ValidateIBCDenom(tc.denom) if tc.expError { require.Error(t, err, tc.name) continue diff --git a/testing/utils.go b/testing/utils.go index f9f64bf72bd..9bbff926d75 100644 --- a/testing/utils.go +++ b/testing/utils.go @@ -3,6 +3,8 @@ package ibctesting import ( "testing" + "math/rand" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" tmtypes "github.com/tendermint/tendermint/types" @@ -21,3 +23,12 @@ func ApplyValSetChanges(t *testing.T, valSet *tmtypes.ValidatorSet, valUpdates [ return newVals } + +// generateString generates a random string of the given length in bytes +func GenerateString(length uint) string { + bytes := make([]byte, length) + for i := range bytes { + bytes[i] = charset[rand.Intn(len(charset))] + } + return string(bytes) +} diff --git a/testing/values.go b/testing/values.go index a73d642a9b3..36a05af8ff8 100644 --- a/testing/values.go +++ b/testing/values.go @@ -40,7 +40,8 @@ const ( Title = "title" Description = "description" - LongString = "LoremipsumdolorsitameconsecteturadipiscingeliseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquUtenimadminimveniamquisnostrudexercitationullamcolaborisnisiutaliquipexeacommodoconsequDuisauteiruredolorinreprehenderitinvoluptateelitsseillumoloreufugiatnullaariaturEcepteurintoccaectupidatatonroidentuntnulpauifficiaeseruntmollitanimidestlaborum" + // character set used for generating a random string in GenerateString + charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ) var (