12345678910111213141516import {IKeyringPair} from '@polkadot/types/types';17import {expect} from 'chai';18import {IEthCrossAccountId} from '../util/playgrounds/types';19import {usingEthPlaygrounds, itEth} from './util';20import {EthUniqueHelper} from './util/playgrounds/unique.dev';2122async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {23 const before = await helper.balance.getSubstrate(helper.address.ethToSubstrate(userAddress));24 await call();25 await helper.wait.newBlocks(1);26 const after = await helper.balance.getSubstrate(helper.address.ethToSubstrate(userAddress));2728 expect(after < before).to.be.true;2930 return before - after;31}3233describe('Add collection admins', () => {34 let donor: IKeyringPair;3536 before(async function() {37 await usingEthPlaygrounds(async (_helper, privateKey) => {38 donor = await privateKey({filename: __filename});39 });40 });4142 itEth('Add admin by owner', async ({helper}) => {43 const owner = await helper.eth.createAccountWithBalance(donor);44 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');45 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);4647 const newAdmin = helper.eth.createAccount();4849 await collectionEvm.methods.addCollectionAdmin(newAdmin).send();50 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);51 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())52 .to.be.eq(newAdmin.toLocaleLowerCase());53 });5455 itEth('Add cross account admin by owner', async ({helper, privateKey}) => {56 const owner = await helper.eth.createAccountWithBalance(donor);57 58 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');59 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);60 61 const newAdmin = await privateKey('//Bob');62 const newAdminCross = helper.ethCrossAccount.fromKeyringPair(newAdmin);63 await collectionEvm.methods.addCollectionAdminCross(newAdminCross).send();6465 const adminList = await helper.collection.getAdmins(collectionId);66 expect(adminList).to.be.like([{Substrate: newAdmin.address}]);67 });6869 itEth('Check adminlist', async ({helper, privateKey}) => {70 const owner = await helper.eth.createAccountWithBalance(donor);71 72 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');73 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);7475 const admin1 = helper.eth.createAccount();76 const admin2 = await privateKey('admin');77 await collectionEvm.methods.addCollectionAdmin(admin1).send();78 await collectionEvm.methods.addCollectionAdminSubstrate(admin2.addressRaw).send();7980 const adminListRpc = await helper.collection.getAdmins(collectionId);81 let adminListEth = await collectionEvm.methods.collectionAdmins().call();82 adminListEth = adminListEth.map((element: IEthCrossAccountId) => {83 return helper.address.convertCrossAccountFromEthCrossAcoount(element);84 });85 expect(adminListRpc).to.be.like(adminListEth);86 });8788 itEth('Verify owner or admin', async ({helper}) => {89 const owner = await helper.eth.createAccountWithBalance(donor);90 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');9192 const newAdmin = helper.eth.createAccount();93 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);94 95 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.false;96 await collectionEvm.methods.addCollectionAdmin(newAdmin).send();97 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;98 });99 100 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {101 const owner = await helper.eth.createAccountWithBalance(donor);102 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');103104 const admin = await helper.eth.createAccountWithBalance(donor);105 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);106 await collectionEvm.methods.addCollectionAdmin(admin).send();107108 const user = helper.eth.createAccount();109 await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: admin}))110 .to.be.rejectedWith('NoPermission');111112 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);113 expect(adminList.length).to.be.eq(1);114 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())115 .to.be.eq(admin.toLocaleLowerCase());116 });117118 itEth('(!negative tests!) Add admin by USER is not allowed', async ({helper}) => {119 const owner = await helper.eth.createAccountWithBalance(donor);120 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');121122 const notAdmin = await helper.eth.createAccountWithBalance(donor);123 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);124125 const user = helper.eth.createAccount();126 await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: notAdmin}))127 .to.be.rejectedWith('NoPermission');128129 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);130 expect(adminList.length).to.be.eq(0);131 });132133 itEth.skip('(!negative tests!) Add substrate admin by ADMIN is not allowed', async ({helper}) => {134 const owner = await helper.eth.createAccountWithBalance(donor);135 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');136137 const admin = await helper.eth.createAccountWithBalance(donor);138 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);139 await collectionEvm.methods.addCollectionAdmin(admin).send();140141 const [notAdmin] = await helper.arrange.createAccounts([10n], donor);142 await expect(collectionEvm.methods.addCollectionAdminSubstrate(notAdmin.addressRaw).call({from: admin}))143 .to.be.rejectedWith('NoPermission');144145 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);146 expect(adminList.length).to.be.eq(1);147 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())148 .to.be.eq(admin.toLocaleLowerCase());149 });150151 itEth.skip('(!negative tests!) Add substrate admin by USER is not allowed', async ({helper}) => {152 const owner = await helper.eth.createAccountWithBalance(donor);153 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');154155 const notAdmin0 = await helper.eth.createAccountWithBalance(donor);156 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);157 const [notAdmin1] = await helper.arrange.createAccounts([10n], donor);158 await expect(collectionEvm.methods.addCollectionAdminSubstrate(notAdmin1.addressRaw).call({from: notAdmin0}))159 .to.be.rejectedWith('NoPermission');160161 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);162 expect(adminList.length).to.be.eq(0);163 });164});165166describe('Remove collection admins', () => {167 let donor: IKeyringPair;168169 before(async function() {170 await usingEthPlaygrounds(async (_helper, privateKey) => {171 donor = await privateKey({filename: __filename});172 });173 });174175 itEth('Remove admin by owner', async ({helper}) => {176 const owner = await helper.eth.createAccountWithBalance(donor);177 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');178179 const newAdmin = helper.eth.createAccount();180 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);181 await collectionEvm.methods.addCollectionAdmin(newAdmin).send();182183 {184 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);185 expect(adminList.length).to.be.eq(1);186 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())187 .to.be.eq(newAdmin.toLocaleLowerCase());188 }189190 await collectionEvm.methods.removeCollectionAdmin(newAdmin).send();191 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);192 expect(adminList.length).to.be.eq(0);193 });194195 itEth.skip('Remove substrate admin by owner', async ({helper}) => {196 const owner = await helper.eth.createAccountWithBalance(donor);197 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');198199 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);200 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);201 await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();202 {203 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);204 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())205 .to.be.eq(newAdmin.address.toLocaleLowerCase());206 }207208 await collectionEvm.methods.removeCollectionAdminSubstrate(newAdmin.addressRaw).send();209 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);210 expect(adminList.length).to.be.eq(0);211 });212213 itEth('(!negative tests!) Remove admin by ADMIN is not allowed', async ({helper}) => {214 const owner = await helper.eth.createAccountWithBalance(donor);215 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');216217 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);218219 const admin0 = await helper.eth.createAccountWithBalance(donor);220 await collectionEvm.methods.addCollectionAdmin(admin0).send();221 const admin1 = await helper.eth.createAccountWithBalance(donor);222 await collectionEvm.methods.addCollectionAdmin(admin1).send();223224 await expect(collectionEvm.methods.removeCollectionAdmin(admin1).call({from: admin0}))225 .to.be.rejectedWith('NoPermission');226 {227 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);228 expect(adminList.length).to.be.eq(2);229 expect(adminList.toString().toLocaleLowerCase())230 .to.be.deep.contains(admin0.toLocaleLowerCase())231 .to.be.deep.contains(admin1.toLocaleLowerCase());232 }233 });234235 itEth('(!negative tests!) Remove admin by USER is not allowed', async ({helper}) => {236 const owner = await helper.eth.createAccountWithBalance(donor);237 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');238239 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);240241 const admin = await helper.eth.createAccountWithBalance(donor);242 await collectionEvm.methods.addCollectionAdmin(admin).send();243 const notAdmin = helper.eth.createAccount();244245 await expect(collectionEvm.methods.removeCollectionAdmin(admin).call({from: notAdmin}))246 .to.be.rejectedWith('NoPermission');247 {248 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);249 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())250 .to.be.eq(admin.toLocaleLowerCase());251 expect(adminList.length).to.be.eq(1);252 }253 });254255 itEth.skip('(!negative tests!) Remove substrate admin by ADMIN is not allowed', async ({helper}) => {256 const owner = await helper.eth.createAccountWithBalance(donor);257 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');258259 const [adminSub] = await helper.arrange.createAccounts([10n], donor);260 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);261 await collectionEvm.methods.addCollectionAdminSubstrate(adminSub.addressRaw).send();262 const adminEth = await helper.eth.createAccountWithBalance(donor);263 await collectionEvm.methods.addCollectionAdmin(adminEth).send();264265 await expect(collectionEvm.methods.removeCollectionAdminSubstrate(adminSub.addressRaw).call({from: adminEth}))266 .to.be.rejectedWith('NoPermission');267268 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);269 expect(adminList.length).to.be.eq(2);270 expect(adminList.toString().toLocaleLowerCase())271 .to.be.deep.contains(adminSub.address.toLocaleLowerCase())272 .to.be.deep.contains(adminEth.toLocaleLowerCase());273 });274275 itEth.skip('(!negative tests!) Remove substrate admin by USER is not allowed', async ({helper}) => {276 const owner = await helper.eth.createAccountWithBalance(donor);277 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');278279 const [adminSub] = await helper.arrange.createAccounts([10n], donor);280 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);281 await collectionEvm.methods.addCollectionAdminSubstrate(adminSub.addressRaw).send();282 const notAdminEth = await helper.eth.createAccountWithBalance(donor);283284 await expect(collectionEvm.methods.removeCollectionAdminSubstrate(adminSub.addressRaw).call({from: notAdminEth}))285 .to.be.rejectedWith('NoPermission');286287 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);288 expect(adminList.length).to.be.eq(1);289 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())290 .to.be.eq(adminSub.address.toLocaleLowerCase());291 });292});293294describe('Change owner tests', () => {295 let donor: IKeyringPair;296297 before(async function() {298 await usingEthPlaygrounds(async (_helper, privateKey) => {299 donor = await privateKey({filename: __filename});300 });301 });302303 itEth('Change owner', async ({helper}) => {304 const owner = await helper.eth.createAccountWithBalance(donor);305 const newOwner = await helper.eth.createAccountWithBalance(donor);306 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');307 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);308309 await collectionEvm.methods.changeCollectionOwner(newOwner).send();310311 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.false;312 expect(await collectionEvm.methods.isOwnerOrAdmin(newOwner).call()).to.be.true;313 });314315 itEth('change owner call fee', async ({helper}) => {316 const owner = await helper.eth.createAccountWithBalance(donor);317 const newOwner = await helper.eth.createAccountWithBalance(donor);318 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');319 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);320 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.changeCollectionOwner(newOwner).send());321 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));322 expect(cost > 0);323 });324325 itEth('(!negative tests!) call setOwner by non owner', async ({helper}) => {326 const owner = await helper.eth.createAccountWithBalance(donor);327 const newOwner = await helper.eth.createAccountWithBalance(donor);328 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');329 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);330331 await expect(collectionEvm.methods.changeCollectionOwner(newOwner).send({from: newOwner})).to.be.rejected;332 expect(await collectionEvm.methods.isOwnerOrAdmin(newOwner).call()).to.be.false;333 });334});335336describe('Change substrate owner tests', () => {337 let donor: IKeyringPair;338339 before(async function() {340 await usingEthPlaygrounds(async (_helper, privateKey) => {341 donor = await privateKey({filename: __filename});342 });343 });344345 itEth.skip('Change owner', async ({helper}) => {346 const owner = await helper.eth.createAccountWithBalance(donor);347 const [newOwner] = await helper.arrange.createAccounts([10n], donor);348 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');349 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);350351 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.true;352 expect(await collectionEvm.methods.isOwnerOrAdminSubstrate(newOwner.addressRaw).call()).to.be.false;353354 await collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send();355356 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.false;357 expect(await collectionEvm.methods.isOwnerOrAdminSubstrate(newOwner.addressRaw).call()).to.be.true;358 });359360 itEth.skip('change owner call fee', async ({helper}) => {361 const owner = await helper.eth.createAccountWithBalance(donor);362 const [newOwner] = await helper.arrange.createAccounts([10n], donor);363 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');364 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);365366 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send());367 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));368 expect(cost > 0);369 });370371 itEth.skip('(!negative tests!) call setOwner by non owner', async ({helper}) => {372 const owner = await helper.eth.createAccountWithBalance(donor);373 const otherReceiver = await helper.eth.createAccountWithBalance(donor);374 const [newOwner] = await helper.arrange.createAccounts([10n], donor);375 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');376 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);377378 await expect(collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send({from: otherReceiver})).to.be.rejected;379 expect(await collectionEvm.methods.isOwnerOrAdminSubstrate(newOwner.addressRaw).call()).to.be.false;380 });381});