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 itEth('sponsors mint transactions', async ({helper}) => {35 const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'spnr', permissions: {mintMode: true}});36 await collection.setSponsor(alice, alice.address);37 await collection.confirmSponsorship(alice);3839 const minter = helper.eth.createAccount();40 expect(await helper.balance.getEthereum(minter)).to.equal(0n);4142 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);43 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', minter);4445 await collection.addToAllowList(alice, {Ethereum: minter});4647 const result = await contract.methods.mint(minter).send();4849 const events = helper.eth.normalizeEvents(result.events);50 expect(events).to.be.deep.equal([51 {52 address: collectionAddress,53 event: 'Transfer',54 args: {55 from: '0x0000000000000000000000000000000000000000',56 to: minter,57 tokenId: '1',58 },59 },60 ]);61 });6263 64 65 66 67 68 69 70 7172 73 74 7576 77 78 7980 81 82 8384 [85 'setCollectionSponsorCross',86 'setCollectionSponsor', 87 ].map(testCase => 88 itEth(`[${testCase}] can remove collection sponsor`, async ({helper}) => {89 const owner = await helper.eth.createAccountWithBalance(donor);90 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);91 92 let result = await collectionHelpers.methods.createNFTCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});93 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);94 const sponsor = await helper.eth.createAccountWithBalance(donor);95 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);96 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner, testCase === 'setCollectionSponsor');97 98 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;99 result = await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send({from: owner});100 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;101 102 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});103 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;104 105 await collectionEvm.methods.removeCollectionSponsor().send({from: owner});106 107 const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});108 expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');109 }));110111 [112 'setCollectionSponsorCross',113 'setCollectionSponsor', 114 ].map(testCase => 115 itEth(`[${testCase}] Can sponsor from evm address via access list`, async ({helper}) => {116 const owner = await helper.eth.createAccountWithBalance(donor);117 const sponsorEth = await helper.eth.createAccountWithBalance(donor);118 const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);119 120 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Sponsor collection', '1', '1', '');121 122 const collectionSub = helper.nft.getCollectionObject(collectionId);123 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor');124 125 126 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsorEth : sponsorCrossEth).send({from: owner});127 let collectionData = (await collectionSub.getData())!;128 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));129 130 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');131 132 133 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});134 collectionData = (await collectionSub.getData())!;135 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));136 137 138 const user = helper.eth.createAccount();139 const userCross = helper.ethCrossAccount.fromAddress(user);140 const nextTokenId = await collectionEvm.methods.nextTokenId().call();141 expect(nextTokenId).to.be.equal('1');142 143 144 const oldPermissions = (await collectionSub.getData())!.raw.permissions; 145 expect(oldPermissions.mintMode).to.be.false;146 expect(oldPermissions.access).to.be.equal('Normal');147148 await collectionEvm.methods.setCollectionAccess(1 ).send({from: owner});149 await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});150 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});151 152 const newPermissions = (await collectionSub.getData())!.raw.permissions; 153 expect(newPermissions.mintMode).to.be.true;154 expect(newPermissions.access).to.be.equal('AllowList');155 156 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));157 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));158159 160 {161 const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});162 const events = helper.eth.normalizeEvents(result.events);163 164 expect(events).to.be.deep.equal([165 {166 address: collectionAddress,167 event: 'Transfer',168 args: {169 from: '0x0000000000000000000000000000000000000000',170 to: user,171 tokenId: '1',172 },173 },174 ]);175 176 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));179 180 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);251 252 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', '');253254 const collectionSub = helper.nft.getCollectionObject(collectionId);255 const collectionEvm = 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('caller is not set as sponsor');261 262 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);263 await sponsorCollection.methods.confirmCollectionSponsorship().send();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 userCollectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', user);275 276 const result = await userCollectionEvm.methods.mintWithTokenURI(user, 'Test URI').send();277 const tokenId = result.events.Transfer.returnValues.tokenId;278 279 const events = helper.eth.normalizeEvents(result.events);280 const address = helper.ethAddress.fromCollectionId(collectionId);281 282 expect(events).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 userCollectionEvm.methods.tokenURI(tokenId).call()).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 }));300});