1234567891011121314151617import {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';19import {Pallets, requirePalletsOrSkip} from '../util';20import {expect, itEth, usingEthPlaygrounds} from './util';21import {CollectionLimitField} from './util/playgrounds/types';222324describe('Create RFT collection from EVM', () => {25 let donor: IKeyringPair;2627 before(async function() {28 await usingEthPlaygrounds(async (helper, privateKey) => {29 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);30 donor = await privateKey({filename: __filename});31 });32 });3334 itEth('Create collection', async ({helper}) => {35 const owner = await helper.eth.createAccountWithBalance(donor);3637 const name = 'CollectionEVM';38 const description = 'Some description';39 const prefix = 'token prefix';4041 const {collectionId} = await helper.eth.createRFTCollection(owner, name, description, prefix);42 const data = (await helper.rft.getData(collectionId))!;43 const collection = helper.rft.getCollectionObject(collectionId);4445 expect(data.name).to.be.eq(name);46 expect(data.description).to.be.eq(description);47 expect(data.raw.tokenPrefix).to.be.eq(prefix);48 expect(data.raw.mode).to.be.eq('ReFungible');4950 const options = await collection.getOptions();5152 expect(options.tokenPropertyPermissions).to.be.empty;53 });54555657 itEth('Create collection with properties & get description', async ({helper}) => {58 const owner = await helper.eth.createAccountWithBalance(donor);5960 const name = 'CollectionEVM';61 const description = 'Some description';62 const prefix = 'token prefix';63 const baseUri = 'BaseURI';6465 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, name, description, prefix, baseUri);66 const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft');6768 const collection = helper.rft.getCollectionObject(collectionId);69 const data = (await collection.getData())!;7071 expect(data.name).to.be.eq(name);72 expect(data.description).to.be.eq(description);73 expect(data.raw.tokenPrefix).to.be.eq(prefix);74 expect(data.raw.mode).to.be.eq('ReFungible');7576 expect(await contract.methods.description().call()).to.deep.equal(description);7778 const options = await collection.getOptions();79 expect(options.tokenPropertyPermissions).to.be.deep.equal([80 {81 key: 'URI',82 permission: {mutable: true, collectionAdmin: true, tokenOwner: false},83 },84 {85 key: 'URISuffix',86 permission: {mutable: true, collectionAdmin: true, tokenOwner: false},87 },88 ]);89 });9091 92 itEth.skip('Check collection address exist', async ({helper}) => {93 const owner = await helper.eth.createAccountWithBalance(donor);9495 const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;96 const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);97 const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);9899 expect(await collectionHelpers.methods100 .isCollectionExist(expectedCollectionAddress)101 .call()).to.be.false;102103 await collectionHelpers.methods104 .createRFTCollection('A', 'A', 'A')105 .send({value: Number(2n * helper.balance.getOneTokenNominal())});106107 expect(await collectionHelpers.methods108 .isCollectionExist(expectedCollectionAddress)109 .call()).to.be.true;110 });111112 113 itEth('[eth] Set sponsorship', async ({helper}) => {114 const owner = await helper.eth.createAccountWithBalance(donor);115 const sponsor = await helper.eth.createAccountWithBalance(donor);116 const ss58Format = helper.chain.getChainProperties().ss58Format;117 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');118119 const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true);120 await collection.methods.setCollectionSponsor(sponsor).send();121122 let data = (await helper.rft.getData(collectionId))!;123 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));124125 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');126127 const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);128 await sponsorCollection.methods.confirmCollectionSponsorship().send();129130 data = (await helper.rft.getData(collectionId))!;131 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));132 });133134 itEth('[cross] Set sponsorship', async ({helper}) => {135 const owner = await helper.eth.createAccountWithBalance(donor);136 const sponsor = await helper.eth.createAccountWithBalance(donor);137 const ss58Format = helper.chain.getChainProperties().ss58Format;138 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');139140 const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);141 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);142 await collection.methods.setCollectionSponsorCross(sponsorCross).send();143144 let data = (await helper.rft.getData(collectionId))!;145 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));146147 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');148149 const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);150 await sponsorCollection.methods.confirmCollectionSponsorship().send();151152 data = (await helper.rft.getData(collectionId))!;153 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));154 });155156 itEth('Collection address exist', async ({helper}) => {157 const owner = await helper.eth.createAccountWithBalance(donor);158 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';159 const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);160161 expect(await collectionHelpers162 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())163 .to.be.false;164165 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Exister', 'absolutely anything', 'WIWT');166 expect(await collectionHelpers167 .methods.isCollectionExist(collectionAddress).call())168 .to.be.true;169 });170});171172describe('(!negative tests!) Create RFT collection from EVM', () => {173 let donor: IKeyringPair;174 let nominal: bigint;175176 before(async function() {177 await usingEthPlaygrounds(async (helper, privateKey) => {178 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);179 donor = await privateKey({filename: __filename});180 nominal = helper.balance.getOneTokenNominal();181 });182 });183184 itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {185 const owner = await helper.eth.createAccountWithBalance(donor);186 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);187 {188 const MAX_NAME_LENGTH = 64;189 const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);190 const description = 'A';191 const tokenPrefix = 'A';192193 await expect(collectionHelper.methods194 .createRFTCollection(collectionName, description, tokenPrefix)195 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);196 }197 {198 const MAX_DESCRIPTION_LENGTH = 256;199 const collectionName = 'A';200 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);201 const tokenPrefix = 'A';202 await expect(collectionHelper.methods203 .createRFTCollection(collectionName, description, tokenPrefix)204 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);205 }206 {207 const MAX_TOKEN_PREFIX_LENGTH = 16;208 const collectionName = 'A';209 const description = 'A';210 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);211 await expect(collectionHelper.methods212 .createRFTCollection(collectionName, description, tokenPrefix)213 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);214 }215 });216217 itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {218 const owner = await helper.eth.createAccountWithBalance(donor);219 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);220 await expect(collectionHelper.methods221 .createRFTCollection('Peasantry', 'absolutely anything', 'TWIW')222 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');223 });224225 226 itEth('(!negative test!) [eth] Check owner', async ({helper}) => {227 const owner = await helper.eth.createAccountWithBalance(donor);228 const peasant = helper.eth.createAccount();229 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');230 const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', peasant, true);231 const EXPECTED_ERROR = 'NoPermission';232 {233 const sponsor = await helper.eth.createAccountWithBalance(donor);234 await expect(peasantCollection.methods235 .setCollectionSponsor(sponsor)236 .call()).to.be.rejectedWith(EXPECTED_ERROR);237238 const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);239 await expect(sponsorCollection.methods240 .confirmCollectionSponsorship()241 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');242 }243 {244 await expect(peasantCollection.methods245 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})246 .call()).to.be.rejectedWith(EXPECTED_ERROR);247 }248 });249250 itEth('(!negative test!) [cross] Check owner', async ({helper}) => {251 const owner = await helper.eth.createAccountWithBalance(donor);252 const peasant = helper.eth.createAccount();253 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');254 const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);255 const EXPECTED_ERROR = 'NoPermission';256 {257 const sponsor = await helper.eth.createAccountWithBalance(donor);258 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);259 await expect(peasantCollection.methods260 .setCollectionSponsorCross(sponsorCross)261 .call()).to.be.rejectedWith(EXPECTED_ERROR);262263 const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);264 await expect(sponsorCollection.methods265 .confirmCollectionSponsorship()266 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');267 }268 {269 await expect(peasantCollection.methods270 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})271 .call()).to.be.rejectedWith(EXPECTED_ERROR);272 }273 });274275 itEth('destroyCollection', async ({helper}) => {276 const owner = await helper.eth.createAccountWithBalance(donor);277 const {collectionAddress, collectionId} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');278 const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);279280 await expect(collectionHelper.methods281 .destroyCollection(collectionAddress)282 .send({from: owner})).to.be.fulfilled;283284 expect(await collectionHelper.methods285 .isCollectionExist(collectionAddress)286 .call()).to.be.false;287 expect(await helper.collection.getData(collectionId)).to.be.null;288 });289});