1234567891011121314151617import {IKeyringPair} from '@polkadot/types/types';18import {evmToAddress} from '@polkadot/util-crypto';19import {Pallets, requirePalletsOrSkip} from '../util';20import {expect, itEth, usingEthPlaygrounds} from './util';21import {CollectionLimitField} from './util/playgrounds/types';2223const DECIMALS = 18;2425describe('Create FT collection from EVM', () => {26 let donor: IKeyringPair;2728 before(async function() {29 await usingEthPlaygrounds(async (helper, privateKey) => {30 requirePalletsOrSkip(this, helper, [Pallets.Fungible]);31 donor = await privateKey({filename: __filename});32 });33 });3435 36 itEth('[eth] Set sponsorship', async ({helper}) => {37 const owner = await helper.eth.createAccountWithBalance(donor);38 const sponsor = await helper.eth.createAccountWithBalance(donor);39 const ss58Format = helper.chain.getChainProperties().ss58Format;40 const description = 'absolutely anything';4142 const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, description, 'ENVY');4344 const collection = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);45 await collection.methods.setCollectionSponsor(sponsor).send();4647 let data = (await helper.rft.getData(collectionId))!;48 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));4950 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');5152 const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);53 await sponsorCollection.methods.confirmCollectionSponsorship().send();5455 data = (await helper.rft.getData(collectionId))!;56 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));57 });5859 itEth('[cross] Set sponsorship', async ({helper}) => {60 const owner = await helper.eth.createAccountWithBalance(donor);61 const sponsor = await helper.eth.createAccountWithBalance(donor);62 const ss58Format = helper.chain.getChainProperties().ss58Format;63 const description = 'absolutely anything';64 const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, description, 'ENVY');6566 const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);67 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);68 await collection.methods.setCollectionSponsorCross(sponsorCross).send();6970 let data = (await helper.rft.getData(collectionId))!;71 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));7273 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');7475 const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);76 await sponsorCollection.methods.confirmCollectionSponsorship().send();7778 data = (await helper.rft.getData(collectionId))!;79 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));80 expect(await collection.methods.description().call()).to.deep.equal(description);81 });8283 itEth('Collection address exist', async ({helper}) => {84 const owner = await helper.eth.createAccountWithBalance(donor);85 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';86 const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);8788 expect(await collectionHelpers89 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())90 .to.be.false;9192 const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT');93 expect(await collectionHelpers94 .methods.isCollectionExist(collectionAddress).call())95 .to.be.true;96 });9798 itEth('destroyCollection', async ({helper}) => {99 const owner = await helper.eth.createAccountWithBalance(donor);100 const {collectionAddress, collectionId} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT');101 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);102103 const result = await collectionHelper.methods104 .destroyCollection(collectionAddress)105 .send({from: owner});106107 const events = helper.eth.normalizeEvents(result.events);108109 expect(events).to.be.deep.equal([110 {111 address: collectionHelper.options.address,112 event: 'CollectionDestroyed',113 args: {114 collectionId: collectionAddress,115 },116 },117 ]);118119 expect(await collectionHelper.methods120 .isCollectionExist(collectionAddress)121 .call()).to.be.false;122 expect(await helper.collection.getData(collectionId)).to.be.null;123 });124});125126describe('(!negative tests!) Create FT collection from EVM', () => {127 let donor: IKeyringPair;128 let nominal: bigint;129130 before(async function() {131 await usingEthPlaygrounds(async (helper, privateKey) => {132 requirePalletsOrSkip(this, helper, [Pallets.Fungible]);133 donor = await privateKey({filename: __filename});134 nominal = helper.balance.getOneTokenNominal();135 });136 });137138 itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {139 const owner = await helper.eth.createAccountWithBalance(donor);140 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);141 {142 const MAX_NAME_LENGTH = 64;143 const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);144 const description = 'A';145 const tokenPrefix = 'A';146147 await expect(collectionHelper.methods148 .createFTCollection(collectionName, DECIMALS, description, tokenPrefix)149 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);150 }151 {152 const MAX_DESCRIPTION_LENGTH = 256;153 const collectionName = 'A';154 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);155 const tokenPrefix = 'A';156 await expect(collectionHelper.methods157 .createFTCollection(collectionName, DECIMALS, description, tokenPrefix)158 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);159 }160 {161 const MAX_TOKEN_PREFIX_LENGTH = 16;162 const collectionName = 'A';163 const description = 'A';164 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);165 await expect(collectionHelper.methods166 .createFTCollection(collectionName, DECIMALS, description, tokenPrefix)167 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);168 }169 });170171 itEth('(!negative test!) cannot create collection if value !== 2', async ({helper}) => {172 const owner = await helper.eth.createAccountWithBalance(donor);173 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);174 const expects = [0n, 1n, 30n].map(async value => {175 await expect(collectionHelper.methods176 .createFTCollection('Peasantry', DECIMALS, 'absolutely anything', 'TWIW')177 .call({value: Number(value * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');178 });179 await Promise.all(expects);180 });181182 183 itEth('(!negative test!) [eth] Check owner', async ({helper}) => {184 const owner = await helper.eth.createAccountWithBalance(donor);185 const peasant = helper.eth.createAccount();186 const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Transgressed', DECIMALS, 'absolutely anything', 'YVNE');187 const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', peasant, true);188 const EXPECTED_ERROR = 'NoPermission';189 {190 const sponsor = await helper.eth.createAccountWithBalance(donor);191 await expect(peasantCollection.methods192 .setCollectionSponsor(sponsor)193 .call()).to.be.rejectedWith(EXPECTED_ERROR);194195 const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor, true);196 await expect(sponsorCollection.methods197 .confirmCollectionSponsorship()198 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');199 }200 {201 await expect(peasantCollection.methods202 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})203 .call()).to.be.rejectedWith(EXPECTED_ERROR);204 }205 });206207 itEth('(!negative test!) [cross] Check owner', async ({helper}) => {208 const owner = await helper.eth.createAccountWithBalance(donor);209 const peasant = helper.eth.createAccount();210 const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Transgressed', DECIMALS, 'absolutely anything', 'YVNE');211 const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', peasant);212 const EXPECTED_ERROR = 'NoPermission';213 {214 const sponsor = await helper.eth.createAccountWithBalance(donor);215 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);216 await expect(peasantCollection.methods217 .setCollectionSponsorCross(sponsorCross)218 .call()).to.be.rejectedWith(EXPECTED_ERROR);219220 const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor);221 await expect(sponsorCollection.methods222 .confirmCollectionSponsorship()223 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');224 }225 {226 await expect(peasantCollection.methods227 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})228 .call()).to.be.rejectedWith(EXPECTED_ERROR);229 }230 });231});