From 1ada10d2982690d81958daf7712783ea7a66f023 Mon Sep 17 00:00:00 2001 From: PraetorP Date: Mon, 24 Oct 2022 21:43:48 +0000 Subject: [PATCH] added tests for `createRTCollection` , refactor `Unique` pallet code --- --- a/pallets/unique/CHANGELOG.md +++ b/pallets/unique/CHANGELOG.md @@ -8,7 +8,7 @@ ### Changes -- Addded **CollectionHelpers** method `destroyCollection`. +- Added `destroyCollection` and `createFTCollection` methods to **CollectionHelpers**. ## [v0.2.0] 2022-09-13 --- a/pallets/unique/src/eth/mod.rs +++ b/pallets/unique/src/eth/mod.rs @@ -18,7 +18,7 @@ use core::marker::PhantomData; use ethereum as _; -use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*}; +use evm_coder::{execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight}; use frame_support::traits::Get; use crate::Pallet; @@ -27,23 +27,24 @@ CollectionById, dispatch::CollectionDispatch, erc::{ + static_property::key, CollectionHelpersEvents, - static_property::{key}, }, Pallet as PalletCommon, + }; +use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult}; use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder}; -use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult}; use sp_std::vec; use up_data_structs::{ - CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData, - CollectionMode, PropertyValue, + CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix, + CreateCollectionData, PropertyValue, }; -use crate::{Config, SelfWeightOf, weights::WeightInfo}; +use crate::{weights::WeightInfo, Config, SelfWeightOf}; -use sp_std::vec::Vec; use alloc::format; +use sp_std::vec::Vec; /// See [`CollectionHelpersCall`] pub struct EvmCollectionHelpers(SubstrateRecorder); @@ -104,6 +105,7 @@ ) } +#[inline(always)] fn create_collection_internal( caller: caller, value: value, @@ -212,7 +214,14 @@ description: string, token_prefix: string, ) -> Result
{ - self.create_nft_collection(caller, value, name, description, token_prefix) + create_collection_internal::( + caller, + value, + name, + CollectionMode::NFT, + description, + token_prefix, + ) } #[weight(>::create_collection())] @@ -225,11 +234,39 @@ description: string, token_prefix: string, ) -> Result
{ - create_refungible_collection_internal::(caller, value, name, description, token_prefix) + create_collection_internal::( + caller, + value, + name, + CollectionMode::ReFungible, + description, + token_prefix, + ) + } + + #[weight(>::create_collection())] + #[solidity(rename_selector = "createERC721MetadataCompatibleRFTCollection")] + fn create_refungible_collection_with_properties( + &mut self, + caller: caller, + value: value, + name: string, + description: string, + token_prefix: string, + base_uri: string, + ) -> Result
{ + create_collection_internal::( + caller, + value, + name, + CollectionMode::ReFungible, + description, + token_prefix, + ) } #[weight(>::create_collection())] - #[solidity(rename_selector = "createRTCollection")] + #[solidity(rename_selector = "createFTCollection")] fn create_fungible_collection( &mut self, caller: caller, --- a/pallets/unique/src/eth/stubs/CollectionHelpers.sol +++ b/pallets/unique/src/eth/stubs/CollectionHelpers.sol @@ -24,7 +24,7 @@ } /// @title Contract, which allows users to operate with collections -/// @dev the ERC-165 identifier for this interface is 0xa2c196ab +/// @dev the ERC-165 identifier for this interface is 0xd8b36039 contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents { /// Create an NFT collection /// @param name Name of the collection @@ -77,9 +77,26 @@ return 0x0000000000000000000000000000000000000000; } - /// @dev EVM selector for this function is: 0xac1e2285, - /// or in textual repr: createRTCollection(string,uint8,string,string) - function createRTCollection( + /// @dev EVM selector for this function is: 0xa5596388, + /// or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string) + function createERC721MetadataCompatibleRFTCollection( + string memory name, + string memory description, + string memory tokenPrefix, + string memory baseUri + ) public payable returns (address) { + require(false, stub_error); + name; + description; + tokenPrefix; + baseUri; + dummy = 0; + return 0x0000000000000000000000000000000000000000; + } + + /// @dev EVM selector for this function is: 0x7335b79f, + /// or in textual repr: createFTCollection(string,uint8,string,string) + function createFTCollection( string memory name, uint8 decimals, string memory description, --- a/tests/src/eth/api/CollectionHelpers.sol +++ b/tests/src/eth/api/CollectionHelpers.sol @@ -19,7 +19,7 @@ } /// @title Contract, which allows users to operate with collections -/// @dev the ERC-165 identifier for this interface is 0xa2c196ab +/// @dev the ERC-165 identifier for this interface is 0xd8b36039 interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents { /// Create an NFT collection /// @param name Name of the collection @@ -51,9 +51,18 @@ string memory tokenPrefix ) external payable returns (address); - /// @dev EVM selector for this function is: 0xac1e2285, - /// or in textual repr: createRTCollection(string,uint8,string,string) - function createRTCollection( + /// @dev EVM selector for this function is: 0xa5596388, + /// or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string) + function createERC721MetadataCompatibleRFTCollection( + string memory name, + string memory description, + string memory tokenPrefix, + string memory baseUri + ) external payable returns (address); + + /// @dev EVM selector for this function is: 0x7335b79f, + /// or in textual repr: createFTCollection(string,uint8,string,string) + function createFTCollection( string memory name, uint8 decimals, string memory description, --- a/tests/src/eth/collectionHelpersAbi.json +++ b/tests/src/eth/collectionHelpersAbi.json @@ -42,9 +42,22 @@ "inputs": [ { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "string", "name": "description", "type": "string" }, + { "internalType": "string", "name": "tokenPrefix", "type": "string" }, + { "internalType": "string", "name": "baseUri", "type": "string" } + ], + "name": "createERC721MetadataCompatibleRFTCollection", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "string", "name": "name", "type": "string" }, + { "internalType": "uint8", "name": "decimals", "type": "uint8" }, + { "internalType": "string", "name": "description", "type": "string" }, { "internalType": "string", "name": "tokenPrefix", "type": "string" } ], - "name": "createNFTCollection", + "name": "createFTCollection", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "payable", "type": "function" @@ -55,7 +68,7 @@ { "internalType": "string", "name": "description", "type": "string" }, { "internalType": "string", "name": "tokenPrefix", "type": "string" } ], - "name": "createRFTCollection", + "name": "createNFTCollection", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "payable", "type": "function" @@ -63,11 +76,10 @@ { "inputs": [ { "internalType": "string", "name": "name", "type": "string" }, - { "internalType": "uint8", "name": "decimals", "type": "uint8" }, { "internalType": "string", "name": "description", "type": "string" }, { "internalType": "string", "name": "tokenPrefix", "type": "string" } ], - "name": "createRTCollection", + "name": "createRFTCollection", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "payable", "type": "function" --- a/tests/src/eth/createFTCollection.test.ts +++ b/tests/src/eth/createFTCollection.test.ts @@ -15,6 +15,7 @@ // along with Unique Network. If not, see . import {IKeyringPair} from '@polkadot/types/types'; +import { evmToAddress } from '@polkadot/util-crypto'; import {Pallets, requirePalletsOrSkip} from '../util'; import {expect, itEth, usingEthPlaygrounds} from './util'; @@ -25,7 +26,7 @@ before(async function() { await usingEthPlaygrounds(async (helper, privateKey) => { - requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); + requirePalletsOrSkip(this, helper, [Pallets.Fungible]); donor = await privateKey('//Alice'); }); }); @@ -39,15 +40,10 @@ // todo:playgrounds this might fail when in async environment. const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created; + + const {collectionId} = await helper.eth.createFungibleCollection(owner, name, DECIMALS, description, prefix); - const collectionCreationPrice = helper.balance.getCollectionCreationPrice(); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); - - const result = await collectionHelper.methods.createRTCollection(name, DECIMALS, description, prefix).call({value: Number(collectionCreationPrice)}); - console.log(result); - const {collectionId} = await helper.eth.createFungibleCollection(owner, name, DECIMALS, description, prefix); const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created; - const data = (await helper.ft.getData(collectionId))!; expect(collectionCountAfter - collectionCountBefore).to.be.eq(1); @@ -58,197 +54,209 @@ expect(data.raw.mode).to.be.deep.eq({Fungible: DECIMALS.toString()}); }); - // // todo:playgrounds this test will fail when in async environment. - // itEth('Check collection address exist', async ({helper}) => { - // const owner = await helper.eth.createAccountWithBalance(donor); + // todo:playgrounds this test will fail when in async environment. + itEth('Check collection address exist', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); - // const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1; - // const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId); - // const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner); + const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1; + const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId); + const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner); + + expect(await collectionHelpers.methods + .isCollectionExist(expectedCollectionAddress) + .call()).to.be.false; - // expect(await collectionHelpers.methods - // .isCollectionExist(expectedCollectionAddress) - // .call()).to.be.false; + + await helper.eth.createFungibleCollection(owner, 'A', DECIMALS, 'A', 'A'); - // await collectionHelpers.methods - // .createRFTCollection('A', 'A', 'A') - // .send({value: Number(2n * helper.balance.getOneTokenNominal())}); - // expect(await collectionHelpers.methods - // .isCollectionExist(expectedCollectionAddress) - // .call()).to.be.true; - // }); + expect(await collectionHelpers.methods + .isCollectionExist(expectedCollectionAddress) + .call()).to.be.true; + }); - // itEth('Set sponsorship', async ({helper}) => { - // const owner = await helper.eth.createAccountWithBalance(donor); - // const sponsor = await helper.eth.createAccountWithBalance(donor); - // const ss58Format = helper.chain.getChainProperties().ss58Format; - // const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY'); + itEth('Set sponsorship', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const sponsor = await helper.eth.createAccountWithBalance(donor); + const ss58Format = helper.chain.getChainProperties().ss58Format; + const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, 'absolutely anything', 'ENVY'); - // const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); - // await collection.methods.setCollectionSponsor(sponsor).send(); + const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + await collection.methods.setCollectionSponsor(sponsor).send(); - // let data = (await helper.rft.getData(collectionId))!; - // expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format))); + let data = (await helper.rft.getData(collectionId))!; + expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format))); - // await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor'); + await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor'); - // const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor); - // await sponsorCollection.methods.confirmCollectionSponsorship().send(); + const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor); + await sponsorCollection.methods.confirmCollectionSponsorship().send(); - // data = (await helper.rft.getData(collectionId))!; - // expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format))); - // }); + data = (await helper.rft.getData(collectionId))!; + expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format))); + }); + + itEth('Set limits', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Limits', DECIMALS, 'absolutely anything', 'INSI'); + const limits = { + accountTokenOwnershipLimit: 1000, + sponsoredDataSize: 1024, + sponsoredDataRateLimit: 30, + tokenLimit: 1000000, + sponsorTransferTimeout: 6, + sponsorApproveTimeout: 6, + ownerCanTransfer: false, + ownerCanDestroy: false, + transfersEnabled: false, + }; - // itEth('Set limits', async ({helper}) => { - // const owner = await helper.eth.createAccountWithBalance(donor); - // const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Limits', 'absolutely anything', 'INSI'); - // const limits = { - // accountTokenOwnershipLimit: 1000, - // sponsoredDataSize: 1024, - // sponsoredDataRateLimit: 30, - // tokenLimit: 1000000, - // sponsorTransferTimeout: 6, - // sponsorApproveTimeout: 6, - // ownerCanTransfer: false, - // ownerCanDestroy: false, - // transfersEnabled: false, - // }; + const collection = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + await collection.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send(); + await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send(); + await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send(); + await collection.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send(); + await collection.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send(); + await collection.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send(); + await collection.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send(); + await collection.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send(); + await collection.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send(); + + const data = (await helper.rft.getData(collectionId))!; + expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(limits.accountTokenOwnershipLimit); + expect(data.raw.limits.sponsoredDataSize).to.be.eq(limits.sponsoredDataSize); + expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(limits.sponsoredDataRateLimit); + expect(data.raw.limits.tokenLimit).to.be.eq(limits.tokenLimit); + expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(limits.sponsorTransferTimeout); + expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(limits.sponsorApproveTimeout); + expect(data.raw.limits.ownerCanTransfer).to.be.eq(limits.ownerCanTransfer); + expect(data.raw.limits.ownerCanDestroy).to.be.eq(limits.ownerCanDestroy); + expect(data.raw.limits.transfersEnabled).to.be.eq(limits.transfersEnabled); + }); - // const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); - // await collection.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send(); - // await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send(); - // await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send(); - // await collection.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send(); - // await collection.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send(); - // await collection.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send(); - // await collection.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send(); - // await collection.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send(); - // await collection.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send(); + itEth('Collection address exist', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233'; + expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection) + .methods.isCollectionExist(collectionAddressForNonexistentCollection).call()) + .to.be.false; - // const data = (await helper.rft.getData(collectionId))!; - // expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(limits.accountTokenOwnershipLimit); - // expect(data.raw.limits.sponsoredDataSize).to.be.eq(limits.sponsoredDataSize); - // expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(limits.sponsoredDataRateLimit); - // expect(data.raw.limits.tokenLimit).to.be.eq(limits.tokenLimit); - // expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(limits.sponsorTransferTimeout); - // expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(limits.sponsorApproveTimeout); - // expect(data.raw.limits.ownerCanTransfer).to.be.eq(limits.ownerCanTransfer); - // expect(data.raw.limits.ownerCanDestroy).to.be.eq(limits.ownerCanDestroy); - // expect(data.raw.limits.transfersEnabled).to.be.eq(limits.transfersEnabled); - // }); + const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT'); + expect(await helper.ethNativeContract.collectionHelpers(collectionAddress) + .methods.isCollectionExist(collectionAddress).call()) + .to.be.true; + }); + + itEth('destroyCollection', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT'); + const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); - // itEth('Collection address exist', async ({helper}) => { - // const owner = await helper.eth.createAccountWithBalance(donor); - // const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233'; - // expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection) - // .methods.isCollectionExist(collectionAddressForNonexistentCollection).call()) - // .to.be.false; + const result = await collectionHelper.methods + .destroyCollection(collectionAddress) + .send({from: owner}); + + const events = helper.eth.normalizeEvents(result.events); - // const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Exister', 'absolutely anything', 'WIWT'); - // expect(await helper.ethNativeContract.collectionHelpers(collectionAddress) - // .methods.isCollectionExist(collectionAddress).call()) - // .to.be.true; - // }); + expect(events).to.be.deep.equal([ + { + address: collectionHelper.options.address, + event: 'CollectionDestroyed', + args: { + collectionId: collectionAddress, + }, + }, + ]); + + expect(await collectionHelper.methods + .isCollectionExist(collectionAddress) + .call()).to.be.false; + }); }); -// describe('(!negative tests!) Create RFT collection from EVM', () => { -// let donor: IKeyringPair; -// let nominal: bigint; +describe('(!negative tests!) Create FT collection from EVM', () => { + let donor: IKeyringPair; + let nominal: bigint; -// before(async function() { -// await usingEthPlaygrounds(async (helper, privateKey) => { -// requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); -// donor = privateKey('//Alice'); -// nominal = helper.balance.getOneTokenNominal(); -// }); -// }); + before(async function() { + await usingEthPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.Fungible]); + donor = await privateKey('//Alice'); + nominal = helper.balance.getOneTokenNominal(); + }); + }); -// itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => { -// const owner = await helper.eth.createAccountWithBalance(donor); -// const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); -// { -// const MAX_NAME_LENGTH = 64; -// const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1); -// const description = 'A'; -// const tokenPrefix = 'A'; + itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + { + const MAX_NAME_LENGTH = 64; + const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1); + const description = 'A'; + const tokenPrefix = 'A'; -// await expect(collectionHelper.methods -// .createRFTCollection(collectionName, description, tokenPrefix) -// .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH); -// } -// { -// const MAX_DESCRIPTION_LENGTH = 256; -// const collectionName = 'A'; -// const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1); -// const tokenPrefix = 'A'; -// await expect(collectionHelper.methods -// .createRFTCollection(collectionName, description, tokenPrefix) -// .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH); -// } -// { -// const MAX_TOKEN_PREFIX_LENGTH = 16; -// const collectionName = 'A'; -// const description = 'A'; -// const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1); -// await expect(collectionHelper.methods -// .createRFTCollection(collectionName, description, tokenPrefix) -// .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH); -// } -// }); + await expect(collectionHelper.methods + .createFTCollection(collectionName, DECIMALS, description, tokenPrefix) + .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH); + } + { + const MAX_DESCRIPTION_LENGTH = 256; + const collectionName = 'A'; + const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1); + const tokenPrefix = 'A'; + await expect(collectionHelper.methods + .createFTCollection(collectionName, DECIMALS, description, tokenPrefix) + .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH); + } + { + const MAX_TOKEN_PREFIX_LENGTH = 16; + const collectionName = 'A'; + const description = 'A'; + const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1); + await expect(collectionHelper.methods + .createFTCollection(collectionName, DECIMALS, description, tokenPrefix) + .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH); + } + }); -// itEth('(!negative test!) Create collection (no funds)', async ({helper}) => { -// const owner = await helper.eth.createAccountWithBalance(donor); -// const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); -// await expect(collectionHelper.methods -// .createRFTCollection('Peasantry', 'absolutely anything', 'TWIW') -// .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); -// }); + itEth('(!negative test!) Create collection (no funds)', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + await expect(collectionHelper.methods + .createFTCollection('Peasantry', DECIMALS, 'absolutely anything', 'TWIW') + .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); + }); -// itEth('(!negative test!) Check owner', async ({helper}) => { -// const owner = await helper.eth.createAccountWithBalance(donor); -// const peasant = helper.eth.createAccount(); -// const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE'); -// const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant); -// const EXPECTED_ERROR = 'NoPermission'; -// { -// const sponsor = await helper.eth.createAccountWithBalance(donor); -// await expect(peasantCollection.methods -// .setCollectionSponsor(sponsor) -// .call()).to.be.rejectedWith(EXPECTED_ERROR); + itEth('(!negative test!) Check owner', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const peasant = helper.eth.createAccount(); + const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Transgressed', DECIMALS, 'absolutely anything', 'YVNE'); + const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', peasant); + const EXPECTED_ERROR = 'NoPermission'; + { + const sponsor = await helper.eth.createAccountWithBalance(donor); + await expect(peasantCollection.methods + .setCollectionSponsor(sponsor) + .call()).to.be.rejectedWith(EXPECTED_ERROR); -// const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor); -// await expect(sponsorCollection.methods -// .confirmCollectionSponsorship() -// .call()).to.be.rejectedWith('caller is not set as sponsor'); -// } -// { -// await expect(peasantCollection.methods -// .setCollectionLimit('account_token_ownership_limit', '1000') -// .call()).to.be.rejectedWith(EXPECTED_ERROR); -// } -// }); + const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor); + await expect(sponsorCollection.methods + .confirmCollectionSponsorship() + .call()).to.be.rejectedWith('caller is not set as sponsor'); + } + { + await expect(peasantCollection.methods + .setCollectionLimit('account_token_ownership_limit', '1000') + .call()).to.be.rejectedWith(EXPECTED_ERROR); + } + }); -// itEth('(!negative test!) Set limits', async ({helper}) => { -// const owner = await helper.eth.createAccountWithBalance(donor); -// const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Limits', 'absolutely anything', 'ISNI'); -// const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); -// await expect(collectionEvm.methods -// .setCollectionLimit('badLimit', 'true') -// .call()).to.be.rejectedWith('unknown boolean limit "badLimit"'); -// }); - -// itEth('destroyCollection test', async ({helper}) => { -// const owner = await helper.eth.createAccountWithBalance(donor); -// const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Limits', 'absolutely anything', 'OLF'); -// const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); - -// await expect(collectionHelper.methods -// .destroyCollection(collectionAddress) -// .send({from: owner})).to.be.fulfilled; - -// expect(await collectionHelper.methods -// .isCollectionExist(collectionAddress) -// .call()).to.be.false; -// }); -// }); + itEth('(!negative test!) Set limits', async ({helper}) => { + const owner = await helper.eth.createAccountWithBalance(donor); + const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Limits', DECIMALS, 'absolutely anything', 'ISNI'); + const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + await expect(collectionEvm.methods + .setCollectionLimit('badLimit', 'true') + .call()).to.be.rejectedWith('unknown boolean limit "badLimit"'); + }); +}); --- a/tests/src/eth/createRFTCollection.test.ts +++ b/tests/src/eth/createRFTCollection.test.ts @@ -264,7 +264,7 @@ .call()).to.be.rejectedWith('unknown boolean limit "badLimit"'); }); - itEth('destroyCollection test', async ({helper}) => { + itEth('destroyCollection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF'); const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); --- a/tests/src/eth/util/playgrounds/unique.dev.ts +++ b/tests/src/eth/util/playgrounds/unique.dev.ts @@ -210,8 +210,7 @@ const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice(); const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer); - const result = await collectionHelper.methods.createRTCollection(name, decimals, description, tokenPrefix).send({value: Number(collectionCreationPrice)}); - + const result = await collectionHelper.methods.createFTCollection(name, decimals, description, tokenPrefix).send({value: Number(collectionCreationPrice)}); const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId); const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress); -- gitstuff