diff --git a/x/asset/nft/keeper/keeper.go b/x/asset/nft/keeper/keeper.go index f863ffe6b..b591fc8d3 100644 --- a/x/asset/nft/keeper/keeper.go +++ b/x/asset/nft/keeper/keeper.go @@ -311,6 +311,10 @@ func (k Keeper) Mint(ctx sdk.Context, settings types.MintSettings) error { return sdkerrors.Wrapf(types.ErrInvalidInput, "ID %q has been burnt for the class", settings.ID) } + if err := k.isNFTReceivable(ctx, settings.ClassID, settings.ID, settings.Recipient); err != nil { + return sdkerrors.Wrapf(cosmoserrors.ErrUnauthorized, "address %q is unauthorized to receive NFT", settings.Recipient.String()) + } + params := k.GetParams(ctx) if params.MintFee.IsPositive() { coinsToBurn := sdk.NewCoins(params.MintFee) diff --git a/x/asset/nft/keeper/keeper_test.go b/x/asset/nft/keeper/keeper_test.go index 767b28a53..c67e6e9ea 100644 --- a/x/asset/nft/keeper/keeper_test.go +++ b/x/asset/nft/keeper/keeper_test.go @@ -254,7 +254,7 @@ func TestKeeper_MintWithRecipient(t *testing.T) { URIHash: "content-hash", } - // mint first NFT + // mint NFT err = nftKeeper.Mint(ctx, settings) requireT.NoError(err) @@ -281,6 +281,46 @@ func TestKeeper_MintWithRecipient(t *testing.T) { requireT.Equal(sdkmath.ZeroInt().String(), balance.Amount.String()) } +func TestKeeper_MintWithRecipientAndWhitelisting(t *testing.T) { + requireT := require.New(t) + testApp := simapp.New() + ctx := testApp.NewContext(false, tmproto.Header{}) + nftKeeper := testApp.AssetNFTKeeper + + nftParams := types.Params{ + MintFee: sdk.NewInt64Coin(constant.DenomDev, 10_000_000), + } + requireT.NoError(nftKeeper.SetParams(ctx, nftParams)) + + addr := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + randomAddr := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + requireT.NoError(testApp.FundAccount(ctx, addr, sdk.NewCoins(nftParams.MintFee))) + classSettings := types.IssueClassSettings{ + Issuer: addr, + Symbol: "symbol", + Features: []types.ClassFeature{ + types.ClassFeature_whitelisting, + }, + } + + classID, err := nftKeeper.IssueClass(ctx, classSettings) + requireT.NoError(err) + requireT.EqualValues(classSettings.Symbol+"-"+addr.String(), classID) + + settings := types.MintSettings{ + Sender: addr, + Recipient: randomAddr, + ClassID: classID, + ID: "my-id", + URI: "https://my-nft-meta.invalid/1", + URIHash: "content-hash", + } + + // mint NFT - should fail because recipient is not whitelisted, and cannot be because nft does not exist + err = nftKeeper.Mint(ctx, settings) + requireT.ErrorIs(err, cosmoserrors.ErrUnauthorized) +} + func TestKeeper_Burn(t *testing.T) { requireT := require.New(t) testApp := simapp.New()