diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs index 249afc33ea..0159b7002c 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_Actions.cs @@ -32,8 +32,6 @@ public override Empty InitializeFromParentChain(InitializeFromParentChainInput i /// public override Empty Create(CreateInput input) { - // can not call create on side chain - Assert(State.SideChainCreator.Value == null, "Failed to create token if side chain creator already set."); var inputSymbolType = GetCreateInputSymbolType(input.Symbol); if (input.Owner == null) { @@ -52,6 +50,9 @@ private Empty CreateToken(CreateInput input, SymbolType symbolType = SymbolType. AssertValidCreateInput(input, symbolType); if (symbolType == SymbolType.Token || symbolType == SymbolType.NftCollection) { + // can not call create on side chain + Assert(State.SideChainCreator.Value == null, + "Failed to create token if side chain creator already set."); if (!IsAddressInCreateWhiteList(Context.Sender) && input.Symbol != TokenContractConstants.SeedCollectionSymbol) { @@ -468,7 +469,6 @@ public override Empty CrossChainCreateToken(CrossChainCreateTokenInput input) Owner = validateTokenInfoExistsInput.Owner ?? validateTokenInfoExistsInput.Issuer }; RegisterTokenInfo(tokenInfo); - Context.Fire(new TokenCreated { Symbol = validateTokenInfoExistsInput.Symbol, @@ -485,6 +485,7 @@ public override Empty CrossChainCreateToken(CrossChainCreateTokenInput input) return new Empty(); } + public override Empty RegisterCrossChainTokenContractAddress(RegisterCrossChainTokenContractAddressInput input) { CheckCrossChainTokenContractRegistrationControllerAuthority(); diff --git a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs index ac487122cb..2e242cf589 100644 --- a/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs +++ b/contract/AElf.Contracts.MultiToken/TokenContract_NFT_Actions.cs @@ -16,14 +16,15 @@ private Empty CreateNFTInfo(CreateInput input) { var nftCollectionInfo = AssertNftCollectionExist(input.Symbol); input.IssueChainId = input.IssueChainId == 0 ? nftCollectionInfo.IssueChainId : input.IssueChainId; - Assert(input.IssueChainId == nftCollectionInfo.IssueChainId, + Assert( + input.IssueChainId == nftCollectionInfo.IssueChainId && Context.ChainId == nftCollectionInfo.IssueChainId, "NFT create ChainId must be collection's issue chainId"); - var owner = nftCollectionInfo.Owner ?? nftCollectionInfo.Issuer; Assert(Context.Sender == owner && owner == input.Owner, "NFT owner must be collection's owner"); if (nftCollectionInfo.Symbol == TokenContractConstants.SeedCollectionSymbol) { + Assert(input.Decimals == 0 && input.TotalSupply == 1, "SEED must be unique."); Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedOwnedSymbolExternalInfoKey, out var ownedSymbol), "OwnedSymbol does not exist."); Assert(input.ExternalInfo.Value.TryGetValue(TokenContractConstants.SeedExpireTimeExternalInfoKey, diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs index 8cec0aabbd..6c92193b21 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/NftApplicationTests.cs @@ -184,6 +184,30 @@ private async Task> CreateNftCollectionAndNft(bool reuseItemId = tr return symbols; } + private async Task CreateNftFailed() + { + var collectionInfo = NftCollection1155Info; + collectionInfo.IssueChainId = 123; + var createCollectionRes = await CreateNftCollectionAsync(collectionInfo); + createCollectionRes.TransactionResult.Status.ShouldBe(TransactionResultStatus.Mined); + Nft1155Info.IssueChainId = 123; + var createNft2Res = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput + { + Symbol = $"{collectionInfo.Symbol}{Nft1155Info.Symbol}", + TokenName = Nft1155Info.TokenName, + TotalSupply = Nft1155Info.TotalSupply, + Decimals = Nft1155Info.Decimals, + Issuer = Nft1155Info.Issuer, + IsBurnable = Nft1155Info.IsBurnable, + IssueChainId = Nft1155Info.IssueChainId, + ExternalInfo = Nft1155Info.ExternalInfo, + Owner = Nft1155Info.Issuer + }); + createNft2Res.TransactionResult.Status.ShouldBe(TransactionResultStatus.Failed); + createNft2Res.TransactionResult.Error.Contains("NFT create ChainId must be collection's issue chainId") + .ShouldBeTrue(); + } + private void AssertTokenEqual(TokenCreated log, TokenInfo input) { Assert.Equal(log.TokenName, input.TokenName); @@ -204,6 +228,12 @@ public async Task MultiTokenContract_Create_1155Nft_Test() await CreateNftCollectionAndNft(); } + [Fact(DisplayName = "[MultiToken_Nft] Create 1155 nfts failed.")] + public async Task MultiTokenContract_Create_1155Nft_failed_Test() + { + await CreateNftFailed(); + } + [Fact(DisplayName = "[MultiToken_Nft] Create 721 nfts.")] public async Task MultiTokenContract_Create_721Nft_Test() { diff --git a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs index dba96e1023..0bb4ade958 100644 --- a/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs +++ b/test/AElf.Contracts.MultiToken.Tests/BVT/TokenApplicationTests.cs @@ -999,16 +999,21 @@ public async Task Side_Chain_Creat_Token_Test() }); await ApproveWithMinersAsync(proposalId); await ParliamentContractStub.Release.SendAsync(proposalId); - var createTokenRet = await TokenContractStub.Create.SendWithExceptionAsync(new CreateInput - { - Symbol = "ALI", - TokenName = "Ali", - Decimals = 4, - TotalSupply = 100_000, - Issuer = DefaultAddress, - Owner = DefaultAddress - }); - createTokenRet.TransactionResult.Error.ShouldContain( + + proposalId = await CreateProposalAsync(TokenContractAddress, + defaultParliament, nameof(TokenContractStub.Create), + new CreateInput + { + Symbol = "ALI", + TokenName = "Ali", + Decimals = 4, + TotalSupply = 100_000, + Issuer = DefaultAddress, + Owner = DefaultAddress + }); + await ApproveWithMinersAsync(proposalId); + var createTokenRe = await ParliamentContractStub.Release.SendWithExceptionAsync(proposalId); + createTokenRe.TransactionResult.Error.ShouldContain( "Failed to create token if side chain creator already set."); }