12345678910111213141516import {IKeyringPair} from '@polkadot/types/types';17import {usingEthPlaygrounds, itEth, expect, EthUniqueHelper} from './util/playgrounds';1819async function waitNewBlocks(helper: EthUniqueHelper, count: number) {20 21 return new Promise<void>(async (resolve) => {22 const unsubscribe = await helper.callRpc('api.rpc.chain.subscribeNewHeads', [() => {23 if (count > 0) {24 count--;25 } else {26 unsubscribe();27 resolve();28 }29 }]);30 });31}3233async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {34 const before = await helper.balance.getSubstrate(helper.address.ethToSubstrate(userAddress));35 await call();36 waitNewBlocks(helper, 1);37 const after = await helper.balance.getSubstrate(helper.address.ethToSubstrate(userAddress));3839 expect(after < before).to.be.true;4041 return before - after;42}4344describe('Add collection admins', () => {45 let donor: IKeyringPair;4647 before(async function() {48 await usingEthPlaygrounds(async (_helper, privateKey) => {49 donor = privateKey('//Alice');50 });51 });5253 itEth('Add admin by owner', async ({helper}) => {54 const owner = await helper.eth.createAccountWithBalance(donor);55 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');56 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);5758 const newAdmin = helper.eth.createAccount();5960 await collectionEvm.methods.addCollectionAdmin(newAdmin).send();61 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);62 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())63 .to.be.eq(newAdmin.toLocaleLowerCase());64 });6566 itEth.skip('Add substrate admin by owner', async ({helper}) => {67 const owner = await helper.eth.createAccountWithBalance(donor);68 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');69 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);7071 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);72 await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();7374 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);75 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())76 .to.be.eq(newAdmin.address.toLocaleLowerCase());77 });7879 itEth('Verify owner or admin', async ({helper}) => {80 const owner = await helper.eth.createAccountWithBalance(donor);81 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');8283 const newAdmin = helper.eth.createAccount();84 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);85 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.false;86 await collectionEvm.methods.addCollectionAdmin(newAdmin).send();87 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;88 });8990 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {91 const owner = await helper.eth.createAccountWithBalance(donor);92 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');9394 const admin = await helper.eth.createAccountWithBalance(donor);95 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);96 await collectionEvm.methods.addCollectionAdmin(admin).send();9798 const user = helper.eth.createAccount();99 await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: admin}))100 .to.be.rejectedWith('NoPermission');101102 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);103 expect(adminList.length).to.be.eq(1);104 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())105 .to.be.eq(admin.toLocaleLowerCase());106 });107108 itEth('(!negative tests!) Add admin by USER is not allowed', async ({helper}) => {109 const owner = await helper.eth.createAccountWithBalance(donor);110 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');111112 const notAdmin = await helper.eth.createAccountWithBalance(donor);113 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);114115 const user = helper.eth.createAccount();116 await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: notAdmin}))117 .to.be.rejectedWith('NoPermission');118119 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);120 expect(adminList.length).to.be.eq(0);121 });122123 itEth.skip('(!negative tests!) Add substrate admin by ADMIN is not allowed', async ({helper}) => {124 const owner = await helper.eth.createAccountWithBalance(donor);125 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');126127 const admin = await helper.eth.createAccountWithBalance(donor);128 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);129 await collectionEvm.methods.addCollectionAdmin(admin).send();130131 const [notAdmin] = await helper.arrange.createAccounts([10n], donor);132 await expect(collectionEvm.methods.addCollectionAdminSubstrate(notAdmin.addressRaw).call({from: admin}))133 .to.be.rejectedWith('NoPermission');134135 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);136 expect(adminList.length).to.be.eq(1);137 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())138 .to.be.eq(admin.toLocaleLowerCase());139 });140141 itEth.skip('(!negative tests!) Add substrate admin by USER is not allowed', async ({helper}) => {142 const owner = await helper.eth.createAccountWithBalance(donor);143 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');144145 const notAdmin0 = await helper.eth.createAccountWithBalance(donor);146 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);147 const [notAdmin1] = await helper.arrange.createAccounts([10n], donor);148 await expect(collectionEvm.methods.addCollectionAdminSubstrate(notAdmin1.addressRaw).call({from: notAdmin0}))149 .to.be.rejectedWith('NoPermission');150151 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);152 expect(adminList.length).to.be.eq(0);153 });154});155156describe('Remove collection admins', () => {157 let donor: IKeyringPair;158159 before(async function() {160 await usingEthPlaygrounds(async (_helper, privateKey) => {161 donor = privateKey('//Alice');162 });163 });164165 itEth('Remove admin by owner', async ({helper}) => {166 const owner = await helper.eth.createAccountWithBalance(donor);167 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');168169 const newAdmin = helper.eth.createAccount();170 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);171 await collectionEvm.methods.addCollectionAdmin(newAdmin).send();172173 {174 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);175 expect(adminList.length).to.be.eq(1);176 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())177 .to.be.eq(newAdmin.toLocaleLowerCase());178 }179180 await collectionEvm.methods.removeCollectionAdmin(newAdmin).send();181 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);182 expect(adminList.length).to.be.eq(0);183 });184185 itEth.skip('Remove substrate admin by owner', async ({helper}) => {186 const owner = await helper.eth.createAccountWithBalance(donor);187 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');188189 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);190 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);191 await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();192 {193 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);194 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())195 .to.be.eq(newAdmin.address.toLocaleLowerCase());196 }197198 await collectionEvm.methods.removeCollectionAdminSubstrate(newAdmin.addressRaw).send();199 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);200 expect(adminList.length).to.be.eq(0);201 });202203 itEth('(!negative tests!) Remove admin by ADMIN is not allowed', async ({helper}) => {204 const owner = await helper.eth.createAccountWithBalance(donor);205 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');206207 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);208209 const admin0 = await helper.eth.createAccountWithBalance(donor);210 await collectionEvm.methods.addCollectionAdmin(admin0).send();211 const admin1 = await helper.eth.createAccountWithBalance(donor);212 await collectionEvm.methods.addCollectionAdmin(admin1).send();213214 await expect(collectionEvm.methods.removeCollectionAdmin(admin1).call({from: admin0}))215 .to.be.rejectedWith('NoPermission');216 {217 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);218 expect(adminList.length).to.be.eq(2);219 expect(adminList.toString().toLocaleLowerCase())220 .to.be.deep.contains(admin0.toLocaleLowerCase())221 .to.be.deep.contains(admin1.toLocaleLowerCase());222 }223 });224225 itEth('(!negative tests!) Remove admin by USER is not allowed', async ({helper}) => {226 const owner = await helper.eth.createAccountWithBalance(donor);227 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');228229 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);230231 const admin = await helper.eth.createAccountWithBalance(donor);232 await collectionEvm.methods.addCollectionAdmin(admin).send();233 const notAdmin = helper.eth.createAccount();234235 await expect(collectionEvm.methods.removeCollectionAdmin(admin).call({from: notAdmin}))236 .to.be.rejectedWith('NoPermission');237 {238 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);239 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())240 .to.be.eq(admin.toLocaleLowerCase());241 expect(adminList.length).to.be.eq(1);242 }243 });244245 itEth.skip('(!negative tests!) Remove substrate admin by ADMIN is not allowed', async ({helper}) => {246 const owner = await helper.eth.createAccountWithBalance(donor);247 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');248249 const [adminSub] = await helper.arrange.createAccounts([10n], donor);250 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);251 await collectionEvm.methods.addCollectionAdminSubstrate(adminSub.addressRaw).send();252 const adminEth = await helper.eth.createAccountWithBalance(donor);253 await collectionEvm.methods.addCollectionAdmin(adminEth).send();254255 await expect(collectionEvm.methods.removeCollectionAdminSubstrate(adminSub.addressRaw).call({from: adminEth}))256 .to.be.rejectedWith('NoPermission');257258 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);259 expect(adminList.length).to.be.eq(2);260 expect(adminList.toString().toLocaleLowerCase())261 .to.be.deep.contains(adminSub.address.toLocaleLowerCase())262 .to.be.deep.contains(adminEth.toLocaleLowerCase());263 });264265 itEth.skip('(!negative tests!) Remove substrate admin by USER is not allowed', async ({helper}) => {266 const owner = await helper.eth.createAccountWithBalance(donor);267 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');268269 const [adminSub] = await helper.arrange.createAccounts([10n], donor);270 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);271 await collectionEvm.methods.addCollectionAdminSubstrate(adminSub.addressRaw).send();272 const notAdminEth = await helper.eth.createAccountWithBalance(donor);273274 await expect(collectionEvm.methods.removeCollectionAdminSubstrate(adminSub.addressRaw).call({from: notAdminEth}))275 .to.be.rejectedWith('NoPermission');276277 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);278 expect(adminList.length).to.be.eq(1);279 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())280 .to.be.eq(adminSub.address.toLocaleLowerCase());281 });282});283284describe('Change owner tests', () => {285 let donor: IKeyringPair;286287 before(async function() {288 await usingEthPlaygrounds(async (_helper, privateKey) => {289 donor = privateKey('//Alice');290 });291 });292293 itEth('Change owner', async ({helper}) => {294 const owner = await helper.eth.createAccountWithBalance(donor);295 const newOwner = await helper.eth.createAccountWithBalance(donor);296 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');297 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);298299 await collectionEvm.methods.setOwner(newOwner).send();300301 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.false;302 expect(await collectionEvm.methods.isOwnerOrAdmin(newOwner).call()).to.be.true;303 });304305 itEth('change owner call fee', async ({helper}) => {306 const owner = await helper.eth.createAccountWithBalance(donor);307 const newOwner = await helper.eth.createAccountWithBalance(donor);308 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');309 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);310 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwner(newOwner).send());311 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));312 expect(cost > 0);313 });314315 itEth('(!negative tests!) call setOwner by non owner', async ({helper}) => {316 const owner = await helper.eth.createAccountWithBalance(donor);317 const newOwner = await helper.eth.createAccountWithBalance(donor);318 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');319 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);320321 await expect(collectionEvm.methods.setOwner(newOwner).send({from: newOwner})).to.be.rejected;322 expect(await collectionEvm.methods.isOwnerOrAdmin(newOwner).call()).to.be.false;323 });324});325326describe('Change substrate owner tests', () => {327 let donor: IKeyringPair;328329 before(async function() {330 await usingEthPlaygrounds(async (_helper, privateKey) => {331 donor = privateKey('//Alice');332 });333 });334335 itEth.skip('Change owner', async ({helper}) => {336 const owner = await helper.eth.createAccountWithBalance(donor);337 const [newOwner] = await helper.arrange.createAccounts([10n], donor);338 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');339 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);340341 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.true;342 expect(await collectionEvm.methods.isOwnerOrAdminSubstrate(newOwner.addressRaw).call()).to.be.false;343344 await collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send();345346 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.false;347 expect(await collectionEvm.methods.isOwnerOrAdminSubstrate(newOwner.addressRaw).call()).to.be.true;348 });349350 itEth.skip('change owner call fee', async ({helper}) => {351 const owner = await helper.eth.createAccountWithBalance(donor);352 const [newOwner] = await helper.arrange.createAccounts([10n], donor);353 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');354 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);355356 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send());357 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));358 expect(cost > 0);359 });360361 itEth.skip('(!negative tests!) call setOwner by non owner', async ({helper}) => {362 const owner = await helper.eth.createAccountWithBalance(donor);363 const otherReceiver = await helper.eth.createAccountWithBalance(donor);364 const [newOwner] = await helper.arrange.createAccounts([10n], donor);365 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');366 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);367368 await expect(collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send({from: otherReceiver})).to.be.rejected;369 expect(await collectionEvm.methods.isOwnerOrAdminSubstrate(newOwner.addressRaw).call()).to.be.false;370 });371});