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('caller is not set as sponsor');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 events = helper.eth.normalizeEvents(result.events);164 165 expect(events).to.be.deep.equal([166 {167 address: collectionAddress,168 event: 'Transfer',169 args: {170 from: '0x0000000000000000000000000000000000000000',171 to: user,172 tokenId: '1',173 },174 },175 ]);176 177 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));178 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));179 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));180 181 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');182 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);183 expect(userBalanceAfter).to.be.eq(0n);184 expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;185 }186 }));187188 189 190 191 192 193 194 195 196197 198199 200 201202 203 204 205206 207 208 209210 211 212213 214 215 216 217 218 219 220 221 222223 224 225 226 227 228 229 230 231 232 233 234235 236 237238 239 240 241 242 243244 [245 'setCollectionSponsorCross',246 'setCollectionSponsor', 247 ].map(testCase => 248 itEth(`[${testCase}] Check that transaction via EVM spend money from sponsor address`, async ({helper}) => {249 const owner = await helper.eth.createAccountWithBalance(donor);250 const sponsor = await helper.eth.createAccountWithBalance(donor);251 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);252 253 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', '');254255 const collectionSub = helper.nft.getCollectionObject(collectionId);256 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor');257 258 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send();259 let collectionData = (await collectionSub.getData())!;260 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));261 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');262 263 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});264 collectionData = (await collectionSub.getData())!;265 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));266 267 const user = helper.eth.createAccount();268 const userCross = helper.ethCrossAccount.fromAddress(user);269 await collectionEvm.methods.addCollectionAdminCross(userCross).send();270 271 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));272 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));273 274 const mintingResult = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});275 const tokenId = mintingResult.events.Transfer.returnValues.tokenId;276 277 const events = helper.eth.normalizeEvents(mintingResult.events);278 const address = helper.ethAddress.fromCollectionId(collectionId);279 280 expect(events).to.be.deep.equal([281 {282 address,283 event: 'Transfer',284 args: {285 from: '0x0000000000000000000000000000000000000000',286 to: user,287 tokenId: '1',288 },289 },290 ]);291 expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');292 293 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));294 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);295 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));296 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;297 }));298299 itEth('Can reassign collection sponsor', async ({helper}) => {300 const owner = await helper.eth.createAccountWithBalance(donor);301 const sponsorEth = await helper.eth.createAccountWithBalance(donor);302 const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);303 const [sponsorSub] = await helper.arrange.createAccounts([100n], donor);304 const sponsorCrossSub = helper.ethCrossAccount.fromKeyringPair(sponsorSub);305306 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', '');307 const collectionSub = helper.nft.getCollectionObject(collectionId);308 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);309310 311 await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossEth).send({from: owner});312 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});313314 315 await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossSub).send({from: owner});316 const collectionSponsor = (await collectionSub.getData())?.raw.sponsorship;317 expect(collectionSponsor).to.deep.eq({Unconfirmed: sponsorSub.address});318 });319});