1234567891011121314151617import {IKeyringPair} from '@polkadot/types/types';18import {Pallets, requirePalletsOrSkip, usingPlaygrounds} from '../util/index';19import {itEth, expect} from './util';2021describe('evm nft 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 let sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});105 expect(helper.address.restoreCrossAccountFromBigInt(BigInt(sponsorTuple.sub))).to.be.eq(helper.address.ethToSubstrate(sponsor, true));106 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;107108 await collectionEvm.methods.removeCollectionSponsor().send({from: owner});109110 sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});111 expect(sponsorTuple.eth).to.be.eq('0x0000000000000000000000000000000000000000');112 }));113114 [115 'setCollectionSponsorCross',116 'setCollectionSponsor', 117 ].map(testCase =>118 itEth(`[${testCase}] Can sponsor from evm address via access list`, async ({helper}) => {119 const owner = await helper.eth.createAccountWithBalance(donor);120 const sponsorEth = await helper.eth.createAccountWithBalance(donor);121 const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);122123 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Sponsor collection', '1', '1', '');124125 const collectionSub = helper.nft.getCollectionObject(collectionId);126 const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor');127128 129 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsorEth : sponsorCrossEth).send({from: owner});130 let sponsorship = (await collectionSub.getData())!.raw.sponsorship;131 expect(sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));132 133 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');134135 136 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});137 sponsorship = (await collectionSub.getData())!.raw.sponsorship;138 expect(sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));139140 141 const user = helper.eth.createAccount();142 const userCross = helper.ethCrossAccount.fromAddress(user);143 const nextTokenId = await collectionEvm.methods.nextTokenId().call();144 expect(nextTokenId).to.be.equal('1');145146 147 const oldPermissions = (await collectionSub.getData())!.raw.permissions; 148 expect(oldPermissions.mintMode).to.be.false;149 expect(oldPermissions.access).to.be.equal('Normal');150151 await collectionEvm.methods.setCollectionAccess(1 ).send({from: owner});152 await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});153 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});154155 const newPermissions = (await collectionSub.getData())!.raw.permissions; 156 expect(newPermissions.mintMode).to.be.true;157 expect(newPermissions.access).to.be.equal('AllowList');158159 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));160 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));161162 163 {164 const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});165 const event = helper.eth.normalizeEvents(result.events)166 .find(event => event.event === 'Transfer');167168 expect(event).to.be.deep.equal({169 address: collectionAddress,170 event: 'Transfer',171 args: {172 from: '0x0000000000000000000000000000000000000000',173 to: user,174 tokenId: '1',175 },176 });177178 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));181182 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);253254 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', '');255256 const collectionSub = helper.nft.getCollectionObject(collectionId);257 const collectionEvm = await 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('ConfirmSponsorshipFail');263264 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));267268 const user = helper.eth.createAccount();269 const userCross = helper.ethCrossAccount.fromAddress(user);270 await collectionEvm.methods.addCollectionAdminCross(userCross).send();271272 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));273 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));274275 const mintingResult = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});276 const tokenId = mintingResult.events.Transfer.returnValues.tokenId;277278 const event = helper.eth.normalizeEvents(mintingResult.events)279 .find(event => event.event === 'Transfer');280 const address = helper.ethAddress.fromCollectionId(collectionId);281282 expect(event).to.be.deep.equal({283 address,284 event: 'Transfer',285 args: {286 from: '0x0000000000000000000000000000000000000000',287 to: user,288 tokenId: '1',289 },290 });291 expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');292293 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 = await 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});320321describe('evm RFT collection sponsoring', () => {322 let donor: IKeyringPair;323 let alice: IKeyringPair;324 let nominal: bigint;325326 before(async function() {327 await usingPlaygrounds(async (helper, privateKey) => {328 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);329 donor = await privateKey({filename: __filename});330 [alice] = await helper.arrange.createAccounts([100n], donor);331 nominal = helper.balance.getOneTokenNominal();332 });333 });334 335 itEth('sponsors mint transactions', async ({helper}) => {336 const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'spnr', permissions: {mintMode: true}});337 await collection.setSponsor(alice, alice.address);338 await collection.confirmSponsorship(alice);339340 const minter = helper.eth.createAccount();341 expect(await helper.balance.getEthereum(minter)).to.equal(0n);342343 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);344 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', minter);345346 await collection.addToAllowList(alice, {Ethereum: minter});347348 const result = await contract.methods.mint(minter).send();349350 const events = helper.eth.normalizeEvents(result.events);351 expect(events).to.deep.include({352 address: collectionAddress,353 event: 'Transfer',354 args: {355 from: '0x0000000000000000000000000000000000000000',356 to: minter,357 tokenId: '1',358 },359 });360 });361362 363 364 365 366 367 368 369 370371 372 373 374375 376 377 378379 380 381 382383 384 itEth('[eth] Remove sponsor', async ({helper}) => {385 const owner = await helper.eth.createAccountWithBalance(donor);386 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);387388 let result = await collectionHelpers.methods.createRFTCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});389 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);390 const sponsor = await helper.eth.createAccountWithBalance(donor);391 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'rft', owner, true);392393 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;394 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});395 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;396397 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});398 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;399400 await collectionEvm.methods.removeCollectionSponsor().send({from: owner});401402 const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});403 expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');404 });405406 itEth('[cross] Remove sponsor', async ({helper}) => {407 const owner = await helper.eth.createAccountWithBalance(donor);408 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);409410 let result = await collectionHelpers.methods.createRFTCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});411 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);412 const sponsor = await helper.eth.createAccountWithBalance(donor);413 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);414 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'rft', owner);415416 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;417 result = await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send({from: owner});418 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;419420 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});421 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;422423 await collectionEvm.methods.removeCollectionSponsor().send({from: owner});424425 const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});426 expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');427 });428429 430 itEth('[eth] Sponsoring collection from evm address via access list', async ({helper}) => {431 const owner = await helper.eth.createAccountWithBalance(donor);432433 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Sponsor collection', '1', '1', '');434435 const collection = helper.rft.getCollectionObject(collectionId);436 const sponsor = await helper.eth.createAccountWithBalance(donor);437 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true);438439 await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});440 let collectionData = (await collection.getData())!;441 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));442 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');443444 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});445 collectionData = (await collection.getData())!;446 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));447448 const user = helper.eth.createAccount();449 const nextTokenId = await collectionEvm.methods.nextTokenId().call();450 expect(nextTokenId).to.be.equal('1');451452 const oldPermissions = (await collection.getData())!.raw.permissions; 453 expect(oldPermissions.mintMode).to.be.false;454 expect(oldPermissions.access).to.be.equal('Normal');455456 await collectionEvm.methods.setCollectionAccess(1 ).send({from: owner});457 await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});458 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});459460 const newPermissions = (await collection.getData())!.raw.permissions; 461 expect(newPermissions.mintMode).to.be.true;462 expect(newPermissions.access).to.be.equal('AllowList');463464 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));465 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));466467 {468 const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});469 const events = helper.eth.normalizeEvents(result.events);470471 expect(events).to.deep.include({472 address: collectionAddress,473 event: 'Transfer',474 args: {475 from: '0x0000000000000000000000000000000000000000',476 to: user,477 tokenId: '1',478 },479 });480481 const ownerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(owner));482 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));483484 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');485 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);486 expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;487 }488 });489490 itEth('[cross] Sponsoring collection from evm address via access list', async ({helper}) => {491 const owner = await helper.eth.createAccountWithBalance(donor);492493 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Sponsor collection', '1', '1', '');494495 const collection = helper.rft.getCollectionObject(collectionId);496 const sponsor = await helper.eth.createAccountWithBalance(donor);497 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);498 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);499500 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send({from: owner});501 let collectionData = (await collection.getData())!;502 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));503 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');504505 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});506 collectionData = (await collection.getData())!;507 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));508509 const user = helper.eth.createAccount();510 const userCross = helper.ethCrossAccount.fromAddress(user);511 const nextTokenId = await collectionEvm.methods.nextTokenId().call();512 expect(nextTokenId).to.be.equal('1');513514 const oldPermissions = (await collection.getData())!.raw.permissions; 515 expect(oldPermissions.mintMode).to.be.false;516 expect(oldPermissions.access).to.be.equal('Normal');517518 await collectionEvm.methods.setCollectionAccess(1 ).send({from: owner});519 await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});520 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});521522 const newPermissions = (await collection.getData())!.raw.permissions; 523 expect(newPermissions.mintMode).to.be.true;524 expect(newPermissions.access).to.be.equal('AllowList');525526 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));527 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));528529 {530 const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});531 const events = helper.eth.normalizeEvents(result.events);532533 expect(events).to.deep.include({534 address: collectionAddress,535 event: 'Transfer',536 args: {537 from: '0x0000000000000000000000000000000000000000',538 to: user,539 tokenId: '1',540 },541 });542543 const ownerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(owner));544 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));545546 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');547 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);548 expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;549 }550 });551552 553 554 555 556 557 558 559 560561 562563 564 565566 567 568 569570 571 572 573574 575 576577 578 579 580 581 582 583 584 585 586587 588 589 590 591 592 593 594 595 596 597 598599 600 601602 603 604 605 606 607608 609 itEth('[eth] Check that transaction via EVM spend money from sponsor address', async ({helper}) => {610 const owner = await helper.eth.createAccountWithBalance(donor);611612 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');613 const collection = helper.rft.getCollectionObject(collectionId);614 const sponsor = await helper.eth.createAccountWithBalance(donor);615 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true);616617 await collectionEvm.methods.setCollectionSponsor(sponsor).send();618 let collectionData = (await collection.getData())!;619 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));620 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');621622 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);623 await sponsorCollection.methods.confirmCollectionSponsorship().send();624 collectionData = (await collection.getData())!;625 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));626627 const user = helper.eth.createAccount();628 await collectionEvm.methods.addCollectionAdmin(user).send();629630 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));631 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));632633 const userCollectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', user, true);634635 const result = await userCollectionEvm.methods.mintWithTokenURI(user, 'Test URI').send();636 const tokenId = result.events.Transfer.returnValues.tokenId;637638 const events = helper.eth.normalizeEvents(result.events);639 const address = helper.ethAddress.fromCollectionId(collectionId);640641 expect(events).to.deep.include({642 address,643 event: 'Transfer',644 args: {645 from: '0x0000000000000000000000000000000000000000',646 to: user,647 tokenId: '1',648 },649 });650 expect(await userCollectionEvm.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');651652 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));653 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);654 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));655 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;656 });657658 itEth('[cross] Check that transaction via EVM spend money from sponsor address', async ({helper}) => {659 const owner = await helper.eth.createAccountWithBalance(donor);660661 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');662 const collection = helper.rft.getCollectionObject(collectionId);663 const sponsor = await helper.eth.createAccountWithBalance(donor);664 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);665 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);666667 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();668 let collectionData = (await collection.getData())!;669 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));670 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');671672 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);673 await sponsorCollection.methods.confirmCollectionSponsorship().send();674 collectionData = (await collection.getData())!;675 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));676677 const user = helper.eth.createAccount();678 const userCross = helper.ethCrossAccount.fromAddress(user);679 await collectionEvm.methods.addCollectionAdminCross(userCross).send();680681 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));682 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));683684 const userCollectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', user);685686 const result = await userCollectionEvm.methods.mintWithTokenURI(user, 'Test URI').send();687 const tokenId = result.events.Transfer.returnValues.tokenId;688689 const events = helper.eth.normalizeEvents(result.events);690 const address = helper.ethAddress.fromCollectionId(collectionId);691692 expect(events).to.deep.include({693 address,694 event: 'Transfer',695 args: {696 from: '0x0000000000000000000000000000000000000000',697 to: user,698 tokenId: '1',699 },700 });701 expect(await userCollectionEvm.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');702703 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));704 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);705 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));706 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;707 });708});709710describe('evm RFT token sponsoring', () => {711 let donor: IKeyringPair;712713 before(async function() {714 await usingPlaygrounds(async (helper, privateKey) => {715 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);716 donor = await privateKey({filename: __filename});717 });718 });719720 itEth('[cross] Check that transfer via EVM spend money from sponsor address', async ({helper}) => {721 const owner = await helper.eth.createAccountWithBalance(donor);722723 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');724 const sponsor = await helper.eth.createAccountWithBalance(donor);725 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);726 const receiver = await helper.eth.createAccountWithBalance(donor);727 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);728729 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();730731 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);732 await sponsorCollection.methods.confirmCollectionSponsorship().send();733734 const user = await helper.eth.createAccountWithBalance(donor);735 const userCross = helper.ethCrossAccount.fromAddress(user);736 await collectionEvm.methods.addCollectionAdminCross(userCross).send();737738 const userCollectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', user);739740 const result = await userCollectionEvm.methods.mintWithTokenURI(user, 'Test URI').send();741 const tokenId = result.events.Transfer.returnValues.tokenId;742743 const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, user); 744 await tokenContract.methods.repartition(2).send();745 746 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));747 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));748 const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));749750 await tokenContract.methods.transfer(receiver, 1).send();751752 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));753 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);754 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));755 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;756 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));757 expect(userBalanceAfter).to.be.eq(userBalanceBefore);758 });759760 itEth('[cross] Check that approve via EVM spend money from sponsor address', async ({helper}) => {761 const owner = await helper.eth.createAccountWithBalance(donor);762763 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');764 const sponsor = await helper.eth.createAccountWithBalance(donor);765 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);766 const receiver = await helper.eth.createAccountWithBalance(donor);767 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);768769 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();770771 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);772 await sponsorCollection.methods.confirmCollectionSponsorship().send();773774 const user = await helper.eth.createAccountWithBalance(donor);775 const userCross = helper.ethCrossAccount.fromAddress(user);776 await collectionEvm.methods.addCollectionAdminCross(userCross).send();777778 const userCollectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', user);779780 const result = await userCollectionEvm.methods.mintWithTokenURI(user, 'Test URI').send();781 const tokenId = result.events.Transfer.returnValues.tokenId;782783 const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, user); 784 await tokenContract.methods.repartition(2).send();785 786 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));787 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));788 const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));789790 await tokenContract.methods.approve(receiver, 1).send();791792 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));793 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);794 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));795 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;796 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));797 expect(userBalanceAfter).to.be.eq(userBalanceBefore);798 });799 800801 itEth('[cross] Check that transferFrom via EVM spend money from sponsor address', async ({helper}) => {802 const owner = await helper.eth.createAccountWithBalance(donor);803804 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');805 const sponsor = await helper.eth.createAccountWithBalance(donor);806 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);807 const receiver = await helper.eth.createAccountWithBalance(donor);808 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);809810 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();811812 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);813 await sponsorCollection.methods.confirmCollectionSponsorship().send();814815 const user = await helper.eth.createAccountWithBalance(donor);816 const userCross = helper.ethCrossAccount.fromAddress(user);817 await collectionEvm.methods.addCollectionAdminCross(userCross).send();818819 const userCollectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', user);820821 const result = await userCollectionEvm.methods.mintWithTokenURI(user, 'Test URI').send();822 const tokenId = result.events.Transfer.returnValues.tokenId;823824 const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, user); 825 await tokenContract.methods.repartition(2).send();826 await tokenContract.methods.approve(receiver, 1).send();827 828 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));829 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));830 const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));831 const receiverBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(receiver));832833 const receiverTokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, receiver); 834 await receiverTokenContract.methods.transferFrom(user, receiver, 1).send();835836 const receiverBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(receiver));837 expect(receiverBalanceAfter).to.be.eq(receiverBalanceBefore);838 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));839 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);840 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));841 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;842 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));843 expect(userBalanceAfter).to.be.eq(userBalanceBefore);844 });845});