diff --git a/x/ibc/nft-transfer/types/packet.go b/x/ibc/nft-transfer/types/packet.go index 236856e1..d3e30105 100644 --- a/x/ibc/nft-transfer/types/packet.go +++ b/x/ibc/nft-transfer/types/packet.go @@ -62,10 +62,16 @@ func (nftpd NonFungibleTokenPacketData) ValidateBasic() error { if len(nftpd.TokenIds) != len(nftpd.TokenData) || len(nftpd.TokenIds) != len(nftpd.TokenUris) { return errors.Wrap(ErrInvalidPacket, "all token infos should have same length") } + seenTokens := make(map[string]struct{}) for _, tokenId := range nftpd.TokenIds { - if len(tokenId) == 0 { - return errors.Wrap(ErrInvalidTokenIds, "invalid zero length token id") - } + if len(tokenId) == 0 { + return errors.Wrap(ErrInvalidTokenIds, "invalid zero length token id") + } + // check duplicate + if _, exists := seenTokens[tokenId]; exists { + return errors.Wrapf(ErrInvalidTokenIds, "duplicate token id: %s", tokenId) + } + seenTokens[tokenId] = struct{}{} } return ValidatePrefixedClassId(nftpd.ClassId) } diff --git a/x/ibc/nft-transfer/types/packet_test.go b/x/ibc/nft-transfer/types/packet_test.go index 8beac499..56a4cf2f 100644 --- a/x/ibc/nft-transfer/types/packet_test.go +++ b/x/ibc/nft-transfer/types/packet_test.go @@ -27,6 +27,7 @@ func TestNonFungibleTokenPacketDataValidateBasic(t *testing.T) { {"invalid token uris", NewNonFungibleTokenPacketData(classId, "", "", []string{"1", "2"}, []string{""}, []string{"", ""}, addr1, addr2, ""), false}, {"missing sender address", NewNonFungibleTokenPacketData(classId, "", "", []string{"1", "2", "3"}, []string{"", "", ""}, []string{"", "", ""}, emptyAddr, addr2, ""), false}, {"missing recipient address", NewNonFungibleTokenPacketData(classId, "", "", []string{"1", "2", "3"}, []string{"", "", ""}, []string{"", "", ""}, addr1, emptyAddr, ""), false}, + {"duplicate token ids", NewNonFungibleTokenPacketData(classId, "", "", []string{"1", "2", "3", "1"}, []string{"", "", "", ""}, []string{"", "", "", ""}, addr1, addr2, ""), false}, } for i, tc := range testCases {