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 const admin2Cross = helper.ethCrossAccount.fromKeyringPair(admin2);78 await collectionEvm.methods.addCollectionAdmin(admin1).send();79 await collectionEvm.methods.addCollectionAdminCross(admin2Cross).send();8081 const adminListRpc = await helper.collection.getAdmins(collectionId);82 let adminListEth = await collectionEvm.methods.collectionAdmins().call();83 adminListEth = adminListEth.map((element: IEthCrossAccountId) => {84 return helper.address.convertCrossAccountFromEthCrossAcoount(element);85 });86 expect(adminListRpc).to.be.like(adminListEth);87 });8889 itEth('Verify owner or admin', async ({helper}) => {90 const owner = await helper.eth.createAccountWithBalance(donor);91 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');9293 const newAdmin = helper.eth.createAccount();94 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);95 96 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.false;97 await collectionEvm.methods.addCollectionAdmin(newAdmin).send();98 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;99 });100 101 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {102 const owner = await helper.eth.createAccountWithBalance(donor);103 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');104105 const admin = await helper.eth.createAccountWithBalance(donor);106 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);107 await collectionEvm.methods.addCollectionAdmin(admin).send();108109 const user = helper.eth.createAccount();110 await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: admin}))111 .to.be.rejectedWith('NoPermission');112113 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);114 expect(adminList.length).to.be.eq(1);115 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())116 .to.be.eq(admin.toLocaleLowerCase());117 });118119 itEth('(!negative tests!) Add admin by USER is not allowed', async ({helper}) => {120 const owner = await helper.eth.createAccountWithBalance(donor);121 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');122123 const notAdmin = await helper.eth.createAccountWithBalance(donor);124 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);125126 const user = helper.eth.createAccount();127 await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: notAdmin}))128 .to.be.rejectedWith('NoPermission');129130 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);131 expect(adminList.length).to.be.eq(0);132 });133134 itEth('(!negative tests!) Add [cross] admin by ADMIN is not allowed', async ({helper}) => {135 const owner = await helper.eth.createAccountWithBalance(donor);136 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');137138 const admin = await helper.eth.createAccountWithBalance(donor);139 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);140 await collectionEvm.methods.addCollectionAdmin(admin).send();141142 const [notAdmin] = await helper.arrange.createAccounts([10n], donor);143 const notAdminCross = helper.ethCrossAccount.fromKeyringPair(notAdmin);144 await expect(collectionEvm.methods.addCollectionAdminCross(notAdminCross).call({from: admin}))145 .to.be.rejectedWith('NoPermission');146147 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);148 expect(adminList.length).to.be.eq(1);149 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())150 .to.be.eq(admin.toLocaleLowerCase());151 });152153 itEth('(!negative tests!) Add [cross] admin by USER is not allowed', async ({helper}) => {154 const owner = await helper.eth.createAccountWithBalance(donor);155 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');156157 const notAdmin0 = await helper.eth.createAccountWithBalance(donor);158 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);159 const [notAdmin1] = await helper.arrange.createAccounts([10n], donor);160 const notAdmin1Cross = helper.ethCrossAccount.fromKeyringPair(notAdmin1);161 await expect(collectionEvm.methods.addCollectionAdminCross(notAdmin1Cross).call({from: notAdmin0}))162 .to.be.rejectedWith('NoPermission');163164 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);165 expect(adminList.length).to.be.eq(0);166 });167});168169describe('Remove collection admins', () => {170 let donor: IKeyringPair;171172 before(async function() {173 await usingEthPlaygrounds(async (_helper, privateKey) => {174 donor = await privateKey({filename: __filename});175 });176 });177178 itEth('Remove admin by owner', async ({helper}) => {179 const owner = await helper.eth.createAccountWithBalance(donor);180 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');181182 const newAdmin = helper.eth.createAccount();183 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);184 await collectionEvm.methods.addCollectionAdmin(newAdmin).send();185186 {187 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);188 expect(adminList.length).to.be.eq(1);189 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())190 .to.be.eq(newAdmin.toLocaleLowerCase());191 }192193 await collectionEvm.methods.removeCollectionAdmin(newAdmin).send();194 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);195 expect(adminList.length).to.be.eq(0);196 });197198 itEth('Remove [cross] admin by owner', async ({helper}) => {199 const owner = await helper.eth.createAccountWithBalance(donor);200 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');201202 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);203 const newAdminCross = helper.ethCrossAccount.fromKeyringPair(newAdmin);204 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);205 await collectionEvm.methods.addCollectionAdminCross(newAdminCross).send();206 {207 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);208 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())209 .to.be.eq(newAdmin.address.toLocaleLowerCase());210 }211212 await collectionEvm.methods.removeCollectionAdminCross(newAdminCross).send();213 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);214 expect(adminList.length).to.be.eq(0);215 });216217 itEth('(!negative tests!) Remove admin by ADMIN is not allowed', async ({helper}) => {218 const owner = await helper.eth.createAccountWithBalance(donor);219 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');220221 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);222223 const admin0 = await helper.eth.createAccountWithBalance(donor);224 await collectionEvm.methods.addCollectionAdmin(admin0).send();225 const admin1 = await helper.eth.createAccountWithBalance(donor);226 await collectionEvm.methods.addCollectionAdmin(admin1).send();227228 await expect(collectionEvm.methods.removeCollectionAdmin(admin1).call({from: admin0}))229 .to.be.rejectedWith('NoPermission');230 {231 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);232 expect(adminList.length).to.be.eq(2);233 expect(adminList.toString().toLocaleLowerCase())234 .to.be.deep.contains(admin0.toLocaleLowerCase())235 .to.be.deep.contains(admin1.toLocaleLowerCase());236 }237 });238239 itEth('(!negative tests!) Remove admin by USER is not allowed', async ({helper}) => {240 const owner = await helper.eth.createAccountWithBalance(donor);241 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');242243 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);244245 const admin = await helper.eth.createAccountWithBalance(donor);246 await collectionEvm.methods.addCollectionAdmin(admin).send();247 const notAdmin = helper.eth.createAccount();248249 await expect(collectionEvm.methods.removeCollectionAdmin(admin).call({from: notAdmin}))250 .to.be.rejectedWith('NoPermission');251 {252 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);253 expect(adminList[0].asEthereum.toString().toLocaleLowerCase())254 .to.be.eq(admin.toLocaleLowerCase());255 expect(adminList.length).to.be.eq(1);256 }257 });258259 itEth('(!negative tests!) Remove [cross] admin by ADMIN is not allowed', async ({helper}) => {260 const owner = await helper.eth.createAccountWithBalance(donor);261 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');262263 const [adminSub] = await helper.arrange.createAccounts([10n], donor);264 const adminSubCross = helper.ethCrossAccount.fromKeyringPair(adminSub);265 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);266 await collectionEvm.methods.addCollectionAdminCross(adminSubCross).send();267 const adminEth = await helper.eth.createAccountWithBalance(donor);268 await collectionEvm.methods.addCollectionAdmin(adminEth).send();269270 await expect(collectionEvm.methods.removeCollectionAdminCross(adminSubCross).call({from: adminEth}))271 .to.be.rejectedWith('NoPermission');272273 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);274 expect(adminList.length).to.be.eq(2);275 expect(adminList.toString().toLocaleLowerCase())276 .to.be.deep.contains(adminSub.address.toLocaleLowerCase())277 .to.be.deep.contains(adminEth.toLocaleLowerCase());278 });279280 itEth('(!negative tests!) Remove [cross] admin by USER is not allowed', async ({helper}) => {281 const owner = await helper.eth.createAccountWithBalance(donor);282 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');283284 const [adminSub] = await helper.arrange.createAccounts([10n], donor);285 const adminSubCross = helper.ethCrossAccount.fromKeyringPair(adminSub);286 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);287 await collectionEvm.methods.addCollectionAdminCross(adminSubCross).send();288 const notAdminEth = await helper.eth.createAccountWithBalance(donor);289290 await expect(collectionEvm.methods.removeCollectionAdminCross(adminSubCross).call({from: notAdminEth}))291 .to.be.rejectedWith('NoPermission');292293 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);294 expect(adminList.length).to.be.eq(1);295 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())296 .to.be.eq(adminSub.address.toLocaleLowerCase());297 });298});299300describe('Change owner tests', () => {301 let donor: IKeyringPair;302303 before(async function() {304 await usingEthPlaygrounds(async (_helper, privateKey) => {305 donor = await privateKey({filename: __filename});306 });307 });308309 itEth('Change owner', async ({helper}) => {310 const owner = await helper.eth.createAccountWithBalance(donor);311 const newOwner = await helper.eth.createAccountWithBalance(donor);312 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');313 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);314315 await collectionEvm.methods.changeCollectionOwner(newOwner).send();316317 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.false;318 expect(await collectionEvm.methods.isOwnerOrAdmin(newOwner).call()).to.be.true;319 });320321 itEth('change owner call fee', async ({helper}) => {322 const owner = await helper.eth.createAccountWithBalance(donor);323 const newOwner = await helper.eth.createAccountWithBalance(donor);324 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');325 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);326 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.changeCollectionOwner(newOwner).send());327 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));328 expect(cost > 0);329 });330331 itEth('(!negative tests!) call setOwner by non owner', async ({helper}) => {332 const owner = await helper.eth.createAccountWithBalance(donor);333 const newOwner = await helper.eth.createAccountWithBalance(donor);334 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');335 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);336337 await expect(collectionEvm.methods.changeCollectionOwner(newOwner).send({from: newOwner})).to.be.rejected;338 expect(await collectionEvm.methods.isOwnerOrAdmin(newOwner).call()).to.be.false;339 });340});341342describe('Change substrate owner tests', () => {343 let donor: IKeyringPair;344345 before(async function() {346 await usingEthPlaygrounds(async (_helper, privateKey) => {347 donor = await privateKey({filename: __filename});348 });349 });350351 itEth('Change owner [cross]', async ({helper}) => {352 const owner = await helper.eth.createAccountWithBalance(donor);353 const [newOwner] = await helper.arrange.createAccounts([10n], donor);354 const newOwnerCross = helper.ethCrossAccount.fromKeyringPair(newOwner);355 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');356 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);357358 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.true;359 expect(await collectionEvm.methods.isOwnerOrAdminCross(newOwnerCross).call()).to.be.false;360361 await collectionEvm.methods.setOwnerCross(newOwnerCross).send();362363 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.false;364 expect(await collectionEvm.methods.isOwnerOrAdminCross(newOwnerCross).call()).to.be.true;365 });366367 itEth.skip('change owner call fee', async ({helper}) => {368 const owner = await helper.eth.createAccountWithBalance(donor);369 const [newOwner] = await helper.arrange.createAccounts([10n], donor);370 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');371 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);372373 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send());374 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));375 expect(cost > 0);376 });377378 itEth('(!negative tests!) call setOwner by non owner [cross]', async ({helper}) => {379 const owner = await helper.eth.createAccountWithBalance(donor);380 const otherReceiver = await helper.eth.createAccountWithBalance(donor);381 const [newOwner] = await helper.arrange.createAccounts([10n], donor);382 const newOwnerCross = helper.ethCrossAccount.fromKeyringPair(newOwner);383 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');384 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);385386 await expect(collectionEvm.methods.setOwnerCross(newOwnerCross).send({from: otherReceiver})).to.be.rejected;387 expect(await collectionEvm.methods.isOwnerOrAdminCross(newOwnerCross).call()).to.be.false;388 });389});