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 });3334 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 = await 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 = await helper.ethNativeContract.collectionHelpers(owner);9293 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 = await helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner, testCase === 'setCollectionSponsor');9899 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;102103 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});104 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;105106 await collectionEvm.methods.removeCollectionSponsor().send({from: owner});107108 const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});109 expect(sponsorTuple.eth).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);120121 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Sponsor collection', '1', '1', '');122123 const collectionSub = helper.nft.getCollectionObject(collectionId);124 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor');125126 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('ConfirmSponsorshipFail');132133 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));137138 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');143144 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});152153 const newPermissions = (await collectionSub.getData())!.raw.permissions; 154 expect(newPermissions.mintMode).to.be.true;155 expect(newPermissions.access).to.be.equal('AllowList');156157 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');165166 expect(event).to.be.deep.equal({167 address: collectionAddress,168 event: 'Transfer',169 args: {170 from: '0x0000000000000000000000000000000000000000',171 to: user,172 tokenId: '1',173 },174 });175176 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));177 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));178 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));179180 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');181 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);182 expect(userBalanceAfter).to.be.eq(0n);183 expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;184 }185 }));186187 188 189 190 191 192 193 194 195196 197198 199 200201 202 203 204205 206 207 208209 210 211212 213 214 215 216 217 218 219 220 221222 223 224 225 226 227 228 229 230 231 232 233234 235 236237 238 239 240 241 242243 [244 'setCollectionSponsorCross',245 'setCollectionSponsor', 246 ].map(testCase =>247 itEth(`[${testCase}] Check that transaction via EVM spend money from sponsor address`, async ({helper}) => {248 const owner = await helper.eth.createAccountWithBalance(donor);249 const sponsor = await helper.eth.createAccountWithBalance(donor);250 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);251252 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', '');253254 const collectionSub = helper.nft.getCollectionObject(collectionId);255 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor');256 257 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send();258 let collectionData = (await collectionSub.getData())!;259 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));260 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');261262 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});263 collectionData = (await collectionSub.getData())!;264 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));265266 const user = helper.eth.createAccount();267 const userCross = helper.ethCrossAccount.fromAddress(user);268 await collectionEvm.methods.addCollectionAdminCross(userCross).send();269270 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));271 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));272273 const mintingResult = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});274 const tokenId = mintingResult.events.Transfer.returnValues.tokenId;275276 const event = helper.eth.normalizeEvents(mintingResult.events)277 .find(event => event.event === 'Transfer');278 const address = helper.ethAddress.fromCollectionId(collectionId);279280 expect(event).to.be.deep.equal({281 address,282 event: 'Transfer',283 args: {284 from: '0x0000000000000000000000000000000000000000',285 to: user,286 tokenId: '1',287 },288 });289 expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');290291 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));292 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);293 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));294 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;295 }));296297 itEth('Can reassign collection sponsor', async ({helper}) => {298 const owner = await helper.eth.createAccountWithBalance(donor);299 const sponsorEth = await helper.eth.createAccountWithBalance(donor);300 const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);301 const [sponsorSub] = await helper.arrange.createAccounts([100n], donor);302 const sponsorCrossSub = helper.ethCrossAccount.fromKeyringPair(sponsorSub);303304 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', '');305 const collectionSub = helper.nft.getCollectionObject(collectionId);306 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);307308 309 await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossEth).send({from: owner});310 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});311312 313 await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossSub).send({from: owner});314 const collectionSponsor = (await collectionSub.getData())?.raw.sponsorship;315 expect(collectionSponsor).to.deep.eq({Unconfirmed: sponsorSub.address});316 });317});