1234567891011121314151617import {IKeyringPair} from '@polkadot/types/types';18import {usingPlaygrounds} from '../util/index';19import {itEth, expect} from './util';2021describe('evm collection sponsoring', () => {22 let donor: IKeyringPair;23 let alice: IKeyringPair;24 let nominal: bigint;2526 before(async () => {27 await usingPlaygrounds(async (helper, privateKey) => {28 donor = await privateKey({filename: __filename});29 [alice] = await helper.arrange.createAccounts([100n], donor);30 nominal = helper.balance.getOneTokenNominal();31 });32 });33 34 35 itEth('sponsors mint transactions', async ({helper}) => {36 const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'spnr', permissions: {mintMode: true}});37 await collection.setSponsor(alice, alice.address);38 await collection.confirmSponsorship(alice);3940 const minter = helper.eth.createAccount();41 expect(await helper.balance.getEthereum(minter)).to.equal(0n);4243 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);44 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', minter);4546 await collection.addToAllowList(alice, {Ethereum: minter});4748 const result = await contract.methods.mint(minter).send();4950 const events = helper.eth.normalizeEvents(result.events);51 expect(events).to.be.deep.equal([52 {53 address: collectionAddress,54 event: 'Transfer',55 args: {56 from: '0x0000000000000000000000000000000000000000',57 to: minter,58 tokenId: '1',59 },60 },61 ]);62 });6364 65 66 67 68 69 70 71 7273 74 75 7677 78 79 8081 82 83 8485 [86 'setCollectionSponsorCross',87 'setCollectionSponsor', 88 ].map(testCase => 89 itEth(`[${testCase}] can remove collection sponsor`, async ({helper}) => {90 const owner = await helper.eth.createAccountWithBalance(donor);91 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);92 93 let result = await collectionHelpers.methods.createNFTCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});94 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);95 const sponsor = await helper.eth.createAccountWithBalance(donor);96 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);97 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner, testCase === 'setCollectionSponsor');98 99 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;100 result = await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send({from: owner});101 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;102 103 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});104 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;105 106 await collectionEvm.methods.removeCollectionSponsor().send({from: owner});107 108 const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});109 expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');110 }));111112 [113 'setCollectionSponsorCross',114 'setCollectionSponsor', 115 ].map(testCase => 116 itEth(`[${testCase}] Can sponsor from evm address via access list`, async ({helper}) => {117 const owner = await helper.eth.createAccountWithBalance(donor);118 const sponsorEth = await helper.eth.createAccountWithBalance(donor);119 const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);120 121 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Sponsor collection', '1', '1', '');122 123 const collectionSub = helper.nft.getCollectionObject(collectionId);124 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor');125 126 127 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsorEth : sponsorCrossEth).send({from: owner});128 let sponsorship = (await collectionSub.getData())!.raw.sponsorship;129 expect(sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));130 131 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');132 133 134 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});135 sponsorship = (await collectionSub.getData())!.raw.sponsorship;136 expect(sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));137 138 139 const user = helper.eth.createAccount();140 const userCross = helper.ethCrossAccount.fromAddress(user);141 const nextTokenId = await collectionEvm.methods.nextTokenId().call();142 expect(nextTokenId).to.be.equal('1');143 144 145 const oldPermissions = (await collectionSub.getData())!.raw.permissions; 146 expect(oldPermissions.mintMode).to.be.false;147 expect(oldPermissions.access).to.be.equal('Normal');148149 await collectionEvm.methods.setCollectionAccess(1 ).send({from: owner});150 await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});151 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});152 153 const newPermissions = (await collectionSub.getData())!.raw.permissions; 154 expect(newPermissions.mintMode).to.be.true;155 expect(newPermissions.access).to.be.equal('AllowList');156 157 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));158 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));159160 161 {162 const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});163 const event = helper.eth.normalizeEvents(result.events)164 .find(event => event.event === 'Transfer');;165 166 expect(event).to.be.deep.equal(167 {168 address: collectionAddress,169 event: 'Transfer',170 args: {171 from: '0x0000000000000000000000000000000000000000',172 to: user,173 tokenId: '1',174 },175 },176 );177 178 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));179 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));180 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));181 182 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');183 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);184 expect(userBalanceAfter).to.be.eq(0n);185 expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;186 }187 }));188189 190 191 192 193 194 195 196 197198 199200 201 202203 204 205 206207 208 209 210211 212 213214 215 216 217 218 219 220 221 222 223224 225 226 227 228 229 230 231 232 233 234 235236 237 238239 240 241 242 243 244245 [246 'setCollectionSponsorCross',247 'setCollectionSponsor', 248 ].map(testCase => 249 itEth(`[${testCase}] Check that transaction via EVM spend money from sponsor address`, async ({helper}) => {250 const owner = await helper.eth.createAccountWithBalance(donor);251 const sponsor = await helper.eth.createAccountWithBalance(donor);252 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);253 254 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', '');255256 const collectionSub = helper.nft.getCollectionObject(collectionId);257 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor');258 259 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send();260 let collectionData = (await collectionSub.getData())!;261 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));262 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmUnsetSponsorFail');263 264 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});265 collectionData = (await collectionSub.getData())!;266 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));267 268 const user = helper.eth.createAccount();269 const userCross = helper.ethCrossAccount.fromAddress(user);270 await collectionEvm.methods.addCollectionAdminCross(userCross).send();271 272 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));273 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));274 275 const mintingResult = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});276 const tokenId = mintingResult.events.Transfer.returnValues.tokenId;277 278 const event = helper.eth.normalizeEvents(mintingResult.events)279 .find(event => event.event === 'Transfer');280 const address = helper.ethAddress.fromCollectionId(collectionId);281 282 expect(event).to.be.deep.equal(283 {284 address,285 event: 'Transfer',286 args: {287 from: '0x0000000000000000000000000000000000000000',288 to: user,289 tokenId: '1',290 },291 },292 );293 expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');294 295 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));296 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);297 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));298 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;299 }));300301 itEth('Can reassign collection sponsor', async ({helper}) => {302 const owner = await helper.eth.createAccountWithBalance(donor);303 const sponsorEth = await helper.eth.createAccountWithBalance(donor);304 const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);305 const [sponsorSub] = await helper.arrange.createAccounts([100n], donor);306 const sponsorCrossSub = helper.ethCrossAccount.fromKeyringPair(sponsorSub);307308 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', '');309 const collectionSub = helper.nft.getCollectionObject(collectionId);310 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);311312 313 await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossEth).send({from: owner});314 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});315316 317 await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossSub).send({from: owner});318 const collectionSponsor = (await collectionSub.getData())?.raw.sponsorship;319 expect(collectionSponsor).to.deep.eq({Unconfirmed: sponsorSub.address});320 });321});