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});154 155 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 'setCollectionSponsorCross',364 'setCollectionSponsor', 365 ].map(testCase => 366 itEth(`[${testCase}] can remove collection sponsor`, async ({helper}) => {367 const owner = await helper.eth.createAccountWithBalance(donor);368 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);369 370 let result = await collectionHelpers.methods.createRFTCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});371 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);372 const sponsor = await helper.eth.createAccountWithBalance(donor);373 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);374 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'rft', owner, testCase === 'setCollectionSponsor');375 376 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;377 result = await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send({from: owner});378 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;379 380 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});381 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;382 383 await collectionEvm.methods.removeCollectionSponsor().send({from: owner});384 385 const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner});386 expect(sponsorTuple.eth).to.be.eq('0x0000000000000000000000000000000000000000');387 }));388389 [390 'setCollectionSponsorCross',391 'setCollectionSponsor', 392 ].map(testCase => 393 itEth(`[${testCase}] Can sponsor from evm address via access list`, async ({helper}) => {394 const owner = await helper.eth.createAccountWithBalance(donor);395 const sponsorEth = await helper.eth.createAccountWithBalance(donor);396 const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);397 398 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Sponsor collection', '1', '1', '');399 400 const collectionSub = helper.rft.getCollectionObject(collectionId);401 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, testCase === 'setCollectionSponsor');402 403 404 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsorEth : sponsorCrossEth).send({from: owner});405 let sponsorship = (await collectionSub.getData())!.raw.sponsorship;406 expect(sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));407 408 409 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');410 411 412 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});413 sponsorship = (await collectionSub.getData())!.raw.sponsorship;414 expect(sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true));415 416 417 const user = helper.eth.createAccount();418 const userCross = helper.ethCrossAccount.fromAddress(user);419 const nextTokenId = await collectionEvm.methods.nextTokenId().call();420 expect(nextTokenId).to.be.equal('1');421 422 423 const oldPermissions = (await collectionSub.getData())!.raw.permissions;424 expect(oldPermissions.mintMode).to.be.false;425 expect(oldPermissions.access).to.be.equal('Normal');426427 await collectionEvm.methods.setCollectionAccess(1 ).send({from: owner});428 await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});429 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});430 431 const newPermissions = (await collectionSub.getData())!.raw.permissions;432 expect(newPermissions.mintMode).to.be.true;433 expect(newPermissions.access).to.be.equal('AllowList');434 435 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));436 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));437438 439 {440 const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});441 const events = helper.eth.normalizeEvents(result.events);442443 expect(events).to.deep.include({444 address: collectionAddress,445 event: 'Transfer',446 args: {447 from: '0x0000000000000000000000000000000000000000',448 to: user,449 tokenId: '1',450 },451 });452 453 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));454 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth));455 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));456 457 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');458 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);459 expect(userBalanceAfter).to.be.eq(0n);460 expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;461 }462 }));463464 [465 'setCollectionSponsorCross',466 'setCollectionSponsor', 467 ].map(testCase => 468 itEth(`[${testCase}] Check that transaction via EVM spend money from sponsor address`, async ({helper}) => {469 const owner = await helper.eth.createAccountWithBalance(donor);470 const sponsor = await helper.eth.createAccountWithBalance(donor);471 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);472 473 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');474475 const collectionSub = helper.rft.getCollectionObject(collectionId);476 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, testCase === 'setCollectionSponsor');477 478 await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send();479 let collectionData = (await collectionSub.getData())!;480 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));481 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');482 483 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});484 collectionData = (await collectionSub.getData())!;485 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));486 487 const user = helper.eth.createAccount();488 const userCross = helper.ethCrossAccount.fromAddress(user);489 await collectionEvm.methods.addCollectionAdminCross(userCross).send();490 491 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));492 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));493 494 const mintingResult = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});495 const tokenId = mintingResult.events.Transfer.returnValues.tokenId;496 497 const events = helper.eth.normalizeEvents(mintingResult.events);498 const address = helper.ethAddress.fromCollectionId(collectionId);499 500 expect(events).to.deep.include({501 address,502 event: 'Transfer',503 args: {504 from: '0x0000000000000000000000000000000000000000',505 to: user,506 tokenId: '1',507 },508 });509 expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');510 511 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));512 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);513 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));514 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;515 }));516517 itEth('Check that transaction via EVM spend money from substrate sponsor address', async ({helper}) => {518 const owner = await helper.eth.createAccountWithBalance(donor);519 const sponsor = alice;520 const sponsorCross = helper.ethCrossAccount.fromKeyringPair(sponsor);521522 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');523524 const collectionSub = helper.rft.getCollectionObject(collectionId);525 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, false);526 527 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.false;528 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();529 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.true;530531 await collectionSub.confirmSponsorship(sponsor);532 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call()).to.be.false;533534 const user = helper.eth.createAccount();535 const userCross = helper.ethCrossAccount.fromAddress(user);536 await collectionEvm.methods.addCollectionAdminCross(userCross).send();537538 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));539 const sponsorBalanceBefore = await helper.balance.getSubstrate(sponsor.address);540 541 const mintingResult = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});542 const tokenId = mintingResult.events.Transfer.returnValues.tokenId;543544 const events = helper.eth.normalizeEvents(mintingResult.events);545546 expect(events).to.deep.include({547 address: collectionAddress,548 event: 'Transfer',549 args: {550 from: '0x0000000000000000000000000000000000000000',551 to: user,552 tokenId: '1',553 },554 });555 expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');556557 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));558 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);559 const sponsorBalanceAfter = await helper.balance.getSubstrate(sponsor.address);560 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;561 });562563 itEth('Sponsoring collection from substrate address via access list', async ({helper}) => {564 const owner = await helper.eth.createAccountWithBalance(donor);565 const user = helper.eth.createAccount();566 const userCross = helper.ethCrossAccount.fromAddress(user);567 const sponsor = alice;568 const sponsorCross = helper.ethCrossAccount.fromKeyringPair(sponsor);569570 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');571 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, false);572573 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send({from: owner});574575 const collectionSub = helper.rft.getCollectionObject(collectionId);576 await collectionSub.confirmSponsorship(sponsor);577578 const nextTokenId = await collectionEvm.methods.nextTokenId().call();579 expect(nextTokenId).to.be.equal('1');580581 await collectionEvm.methods.setCollectionAccess(1 ).send({from: owner});582 583 await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});584 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});585586 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));587 const sponsorBalanceBefore = await helper.balance.getSubstrate(sponsor.address);588589 {590 const nextTokenId = await collectionEvm.methods.nextTokenId().call();591 expect(nextTokenId).to.be.equal('1');592 const mintingResult = await collectionEvm.methods.mintWithTokenURI(593 user,594 'Test URI',595 ).send({from: user});596597 const events = helper.eth.normalizeEvents(mintingResult.events);598 599600 expect(events).to.deep.include({601 address: collectionAddress,602 event: 'Transfer',603 args: {604 from: '0x0000000000000000000000000000000000000000',605 to: user,606 tokenId: nextTokenId,607 },608 });609610 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));611 const sponsorBalanceAfter = await helper.balance.getSubstrate(sponsor.address);612613 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');614 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);615 expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;616 }617 });618619 itEth('Can reassign collection sponsor', async ({helper}) => {620 const owner = await helper.eth.createAccountWithBalance(donor);621 const sponsorEth = await helper.eth.createAccountWithBalance(donor);622 const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth);623 const [sponsorSub] = await helper.arrange.createAccounts([100n], donor);624 const sponsorCrossSub = helper.ethCrossAccount.fromKeyringPair(sponsorSub);625626 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');627 const collectionSub = helper.rft.getCollectionObject(collectionId);628 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);629630 631 await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossEth).send({from: owner});632 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});633634 635 await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossSub).send({from: owner});636 const collectionSponsor = (await collectionSub.getData())?.raw.sponsorship;637 expect(collectionSponsor).to.deep.eq({Unconfirmed: sponsorSub.address});638 });639});640641describe('evm RFT token sponsoring', () => {642 let donor: IKeyringPair;643644 before(async function() {645 await usingPlaygrounds(async (helper, privateKey) => {646 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);647 donor = await privateKey({filename: __filename});648 });649 });650651 itEth('[cross] Check that transfer via EVM spend money from sponsor address', async ({helper}) => {652 const owner = await helper.eth.createAccountWithBalance(donor);653654 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');655 const sponsor = await helper.eth.createAccountWithBalance(donor);656 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);657 const receiver = await helper.eth.createAccountWithBalance(donor);658 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);659660 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();661 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});662663 const user = await helper.eth.createAccountWithBalance(donor);664 const userCross = helper.ethCrossAccount.fromAddress(user);665 await collectionEvm.methods.addCollectionAdminCross(userCross).send();666667 const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});668 const tokenId = result.events.Transfer.returnValues.tokenId;669670 const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, user); 671 await tokenContract.methods.repartition(2).send();672 673 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));674 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));675 const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));676677 await tokenContract.methods.transfer(receiver, 1).send();678679 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));680 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);681 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));682 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;683 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));684 expect(userBalanceAfter).to.be.eq(userBalanceBefore);685 });686687 itEth('[cross] Check that approve via EVM spend money from sponsor address', async ({helper}) => {688 const owner = await helper.eth.createAccountWithBalance(donor);689690 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');691 const sponsor = await helper.eth.createAccountWithBalance(donor);692 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);693 const receiver = await helper.eth.createAccountWithBalance(donor);694 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);695696 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();697 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});698699 const user = await helper.eth.createAccountWithBalance(donor);700 const userCross = helper.ethCrossAccount.fromAddress(user);701 await collectionEvm.methods.addCollectionAdminCross(userCross).send();702703 const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});704 const tokenId = result.events.Transfer.returnValues.tokenId;705706 const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, user); 707 await tokenContract.methods.repartition(2).send();708 709 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));710 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));711 const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));712713 await tokenContract.methods.approve(receiver, 1).send();714715 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));716 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);717 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));718 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;719 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));720 expect(userBalanceAfter).to.be.eq(userBalanceBefore);721 });722 723724 itEth('[cross] Check that transferFrom via EVM spend money from sponsor address', async ({helper}) => {725 const owner = await helper.eth.createAccountWithBalance(donor);726727 const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner,'Sponsor collection', '1', '1', '');728 const sponsor = await helper.eth.createAccountWithBalance(donor);729 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);730 const receiver = await helper.eth.createAccountWithBalance(donor);731 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);732733 await collectionEvm.methods.setCollectionSponsorCross(sponsorCross).send();734 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});735736 const user = await helper.eth.createAccountWithBalance(donor);737 const userCross = helper.ethCrossAccount.fromAddress(user);738 await collectionEvm.methods.addCollectionAdminCross(userCross).send();739740 const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user});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 await tokenContract.methods.approve(receiver, 1).send();746 747 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));748 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));749 const userBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));750 const receiverBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(receiver));751752 const receiverTokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, receiver); 753 await receiverTokenContract.methods.transferFrom(user, receiver, 1).send();754755 const receiverBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(receiver));756 expect(receiverBalanceAfter).to.be.eq(receiverBalanceBefore);757 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));758 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);759 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));760 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;761 const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user));762 expect(userBalanceAfter).to.be.eq(userBalanceBefore);763 });764});