--- a/tests/.eslintrc.json +++ b/tests/.eslintrc.json @@ -10,7 +10,8 @@ "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 11, - "sourceType": "module" + "sourceType": "module", + "project": "**/tsconfig.json" }, "plugins": [ "@typescript-eslint", @@ -24,6 +25,7 @@ "SwitchCase": 1 } ], + "no-trailing-spaces": "warn", "function-call-argument-newline": [ "error", "consistent" --- a/tests/src/app-promotion.test.ts +++ b/tests/src/app-promotion.test.ts @@ -45,113 +45,113 @@ }); }); - describe('stake extrinsic', () => { + describe('stake extrinsic', () => { itSub('should "lock" staking balance, add it to "staked" map, and increase "totalStaked" amount', async ({helper}) => { const [staker, recepient] = [accounts.pop()!, accounts.pop()!]; const totalStakedBefore = await helper.staking.getTotalStaked(); - + // Minimum stake amount is 100: await expect(helper.staking.stake(staker, 100n * nominal - 1n)).to.be.rejected; await helper.staking.stake(staker, 100n * nominal); - + // Staker balance is: miscFrozen: 100, feeFrozen: 100, reserved: 0n... // ...so he can not transfer 900 expect(await helper.balance.getSubstrateFull(staker.address)).to.contain({miscFrozen: 100n * nominal, feeFrozen: 100n * nominal, reserved: 0n}); expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'appstake', amount: 100n * nominal, reasons: 'All'}]); await expect(helper.balance.transferToSubstrate(staker, recepient.address, 900n * nominal)).to.be.rejectedWith('balances.LiquidityRestrictions'); - + expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(100n * nominal); expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n); - // it is potentially flaky test. Promotion can credited some tokens. Maybe we need to use closeTo? - expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore + 100n * nominal); // total tokens amount staked in app-promotion increased - - + // it is potentially flaky test. Promotion can credited some tokens. Maybe we need to use closeTo? + expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore + 100n * nominal); // total tokens amount staked in app-promotion increased + + await helper.staking.stake(staker, 200n * nominal); expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(300n * nominal); const totalStakedPerBlock = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); expect(totalStakedPerBlock[0].amount).to.equal(100n * nominal); expect(totalStakedPerBlock[1].amount).to.equal(200n * nominal); }); - + itSub('should allow to create maximum 10 stakes for account', async ({helper}) => { const [staker] = await helper.arrange.createAccounts([2000n], donor); for (let i = 0; i < 10; i++) { await helper.staking.stake(staker, 100n * nominal); } - + // can have 10 stakes expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(1000n * nominal); expect(await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).to.have.length(10); - + await expect(helper.staking.stake(staker, 100n * nominal)).to.be.rejectedWith('appPromotion.NoPermission'); - + // After unstake can stake again await helper.staking.unstake(staker); await helper.staking.stake(staker, 100n * nominal); expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.equal(100n * nominal); }); - + itSub('should reject transaction if stake amount is more than total free balance minus frozen', async ({helper}) => { const staker = accounts.pop()!; - + // Can't stake full balance because Alice needs to pay some fee await expect(helper.staking.stake(staker, 1000n * nominal)).to.be.rejected; await helper.staking.stake(staker, 500n * nominal); - + // Can't stake 500 tkn because Alice has Less than 500 transferable; - await expect(helper.staking.stake(staker, 500n * nominal)).to.be.rejectedWith('balances.LiquidityRestrictions'); + await expect(helper.staking.stake(staker, 500n * nominal)).to.be.rejectedWith('balances.LiquidityRestrictions'); expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(500n * nominal); }); - + itSub('for different accounts in one block is possible', async ({helper}) => { const crowd = [accounts.pop()!, accounts.pop()!, accounts.pop()!, accounts.pop()!]; - + const crowdStartsToStake = crowd.map(user => helper.staking.stake(user, 100n * nominal)); await expect(Promise.all(crowdStartsToStake)).to.be.fulfilled; - + const crowdStakes = await Promise.all(crowd.map(address => helper.staking.getTotalStaked({Substrate: address.address}))); expect(crowdStakes).to.deep.equal([100n * nominal, 100n * nominal, 100n * nominal, 100n * nominal]); }); }); - - describe('unstake extrinsic', () => { + + describe('unstake extrinsic', () => { itSub('should change balance state from "frozen" to "reserved", add it to "pendingUnstake" map, and subtract it from totalStaked', async ({helper}) => { const [staker, recepient] = [accounts.pop()!, accounts.pop()!]; const totalStakedBefore = await helper.staking.getTotalStaked(); await helper.staking.stake(staker, 900n * nominal); await helper.staking.unstake(staker); - + // Right after unstake balance is reserved - // Staker can not transfer + // Staker can not transfer expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 900n * nominal, miscFrozen: 0n, feeFrozen: 0n}); await expect(helper.balance.transferToSubstrate(staker, recepient.address, 100n * nominal)).to.be.rejectedWith('balances.InsufficientBalance'); expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(900n * nominal); expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n); expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore); }); - + itSub('should unlock balance after unlocking period ends and remove it from "pendingUnstake"', async ({helper}) => { const staker = accounts.pop()!; await helper.staking.stake(staker, 100n * nominal); await helper.staking.unstake(staker); const [pendingUnstake] = await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address}); - + // Wait for unstaking period. Balance now free ~1000; reserved, frozen, miscFrozeb: 0n await helper.wait.forParachainBlockNumber(pendingUnstake.block); expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, miscFrozen: 0n, feeFrozen: 0n}); expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n); - + // staker can transfer: await helper.balance.transferToSubstrate(staker, donor.address, 998n * nominal); expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(1n); }); - + itSub('should successfully unstake multiple stakes', async ({helper}) => { const staker = accounts.pop()!; await helper.staking.stake(staker, 100n * nominal); await helper.staking.stake(staker, 200n * nominal); await helper.staking.stake(staker, 300n * nominal); - + // staked: [100, 200, 300]; unstaked: 0 let totalPendingUnstake = await helper.staking.getPendingUnstake({Substrate: staker.address}); let pendingUnstake = await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address}); @@ -161,7 +161,7 @@ expect(stakes[0].amount).to.equal(100n * nominal); expect(stakes[1].amount).to.equal(200n * nominal); expect(stakes[2].amount).to.equal(300n * nominal); - + // Can unstake multiple stakes await helper.staking.unstake(staker); pendingUnstake = await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address}); @@ -170,58 +170,58 @@ expect(totalPendingUnstake).to.be.equal(600n * nominal); expect(stakes).to.be.deep.equal([]); expect(pendingUnstake[0].amount).to.equal(600n * nominal); - + expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 600n * nominal, feeFrozen: 0n, miscFrozen: 0n}); await helper.wait.forParachainBlockNumber(pendingUnstake[0].block); expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, feeFrozen: 0n, miscFrozen: 0n}); expect (await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n); }); - + itSub('should not have any effects if no active stakes', async ({helper}) => { const staker = accounts.pop()!; - + // unstake has no effect if no stakes at all await helper.staking.unstake(staker); expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(0n); expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n); // TODO bigint closeTo helper - + // TODO stake() unstake() waitUnstaked() unstake(); - + // can't unstake if there are only pendingUnstakes await helper.staking.stake(staker, 100n * nominal); await helper.staking.unstake(staker); await helper.staking.unstake(staker); - + expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(100n * nominal); expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n); }); - + itSub('should keep different unlocking block for each unlocking stake', async ({helper}) => { const staker = accounts.pop()!; await helper.staking.stake(staker, 100n * nominal); await helper.staking.unstake(staker); await helper.staking.stake(staker, 120n * nominal); await helper.staking.unstake(staker); - + const unstakingPerBlock = await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address}); expect(unstakingPerBlock).has.length(2); expect(unstakingPerBlock[0].amount).to.equal(100n * nominal); expect(unstakingPerBlock[1].amount).to.equal(120n * nominal); }); - + itSub('should be possible for different accounts in one block', async ({helper}) => { const stakers = [accounts.pop()!, accounts.pop()!, accounts.pop()!]; - + await Promise.all(stakers.map(staker => helper.staking.stake(staker, 100n * nominal))); await Promise.all(stakers.map(staker => helper.staking.unstake(staker))); - + await Promise.all(stakers.map(async (staker) => { expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(100n * nominal); expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n); })); }); }); - + describe('collection sponsoring', () => { itSub('should actually sponsor transactions', async ({helper}) => { const api = helper.getApi(); @@ -230,345 +230,345 @@ const token = await collection.mintToken(collectionOwner, {Substrate: tokenSender.address}); await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId)); const palletBalanceBefore = await helper.balance.getSubstrate(palletAddress); - + await token.transfer(tokenSender, {Substrate: receiver.address}); expect (await token.getOwner()).to.be.deep.equal({Substrate: receiver.address}); const palletBalanceAfter = await helper.balance.getSubstrate(palletAddress); - + // senders balance the same, transaction has sponsored expect (await helper.balance.getSubstrate(tokenSender.address)).to.be.equal(1000n * nominal); expect (palletBalanceBefore > palletBalanceAfter).to.be.true; }); - + itSub('can not be set by non admin', async ({helper}) => { const api = helper.getApi(); const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!]; - + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); - + await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected; expect((await collection.getData())?.raw.sponsorship).to.equal('Disabled'); }); - + itSub('should set pallet address as confirmed admin', async ({helper}) => { const api = helper.getApi(); const [collectionOwner, oldSponsor] = [accounts.pop()!, accounts.pop()!]; - + // Can set sponsoring for collection without sponsor const collectionWithoutSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'No-sponsor', description: 'New Collection', tokenPrefix: 'Promotion'}); await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionWithoutSponsor.collectionId))).to.be.fulfilled; expect((await collectionWithoutSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); - + // Can set sponsoring for collection with unconfirmed sponsor const collectionWithUnconfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Unconfirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address}); expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Unconfirmed: oldSponsor.address}); await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionWithUnconfirmedSponsor.collectionId))).to.be.fulfilled; expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); - + // Can set sponsoring for collection with confirmed sponsor const collectionWithConfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Confirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address}); await collectionWithConfirmedSponsor.confirmSponsorship(oldSponsor); await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionWithConfirmedSponsor.collectionId))).to.be.fulfilled; expect((await collectionWithConfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); }); - - itSub('can be overwritten by collection owner', async ({helper}) => { + + itSub('can be overwritten by collection owner', async ({helper}) => { const api = helper.getApi(); const [collectionOwner, newSponsor] = [accounts.pop()!, accounts.pop()!]; const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); const collectionId = collection.collectionId; - + await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionId))).to.be.fulfilled; - + // Collection limits still can be changed by the owner expect(await collection.setLimits(collectionOwner, {sponsorTransferTimeout: 0})).to.be.true; expect((await collection.getData())?.raw.limits.sponsorTransferTimeout).to.be.equal(0); expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); - + // Collection sponsor can be changed too expect((await collection.setSponsor(collectionOwner, newSponsor.address))).to.be.true; expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Unconfirmed: newSponsor.address}); }); - + itSub('should not overwrite collection limits set by the owner earlier', async ({helper}) => { const api = helper.getApi(); const limits = {ownerCanDestroy: true, ownerCanTransfer: true, sponsorTransferTimeout: 0}; const collectionWithLimits = await helper.nft.mintCollection(accounts.pop()!, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits}); - + await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collectionWithLimits.collectionId))).to.be.fulfilled; expect((await collectionWithLimits.getData())?.raw.limits).to.be.deep.contain(limits); }); - + itSub('should reject transaction if collection doesn\'t exist', async ({helper}) => { const api = helper.getApi(); const collectionOwner = accounts.pop()!; - + // collection has never existed await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(999999999))).to.be.rejected; // collection has been burned const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); await collection.burn(collectionOwner); - + await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected; }); }); - + describe('stopSponsoringCollection', () => { itSub('can not be called by non-admin', async ({helper}) => { const api = helper.getApi(); const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!]; const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); - + await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.fulfilled; - + await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.rejected; expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); }); - + itSub('should set sponsoring as disabled', async ({helper}) => { const api = helper.getApi(); const [collectionOwner, recepient] = [accounts.pop()!, accounts.pop()!]; const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits: {sponsorTransferTimeout: 0}}); const token = await collection.mintToken(collectionOwner, {Substrate: collectionOwner.address}); - + await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId)); await helper.signTransaction(palletAdmin, api.tx.appPromotion.stopSponsoringCollection(collection.collectionId)); - + expect((await collection.getData())?.raw.sponsorship).to.be.equal('Disabled'); - + // Transactions are not sponsored anymore: const ownerBalanceBefore = await helper.balance.getSubstrate(collectionOwner.address); await token.transfer(collectionOwner, {Substrate: recepient.address}); const ownerBalanceAfter = await helper.balance.getSubstrate(collectionOwner.address); expect(ownerBalanceAfter < ownerBalanceBefore).to.be.equal(true); }); - + itSub('should not affect collection which is not sponsored by pallete', async ({helper}) => { const api = helper.getApi(); const collectionOwner = accounts.pop()!; const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: collectionOwner.address}); await collection.confirmSponsorship(collectionOwner); - + await expect(helper.signTransaction(palletAdmin, api.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.rejected; - + expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: collectionOwner.address}); }); - - itSub('should reject transaction if collection does not exist', async ({helper}) => { + + itSub('should reject transaction if collection does not exist', async ({helper}) => { const collectionOwner = accounts.pop()!; const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); - + await collection.burn(collectionOwner); await expect(helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.stopSponsoringCollection', [collection.collectionId], true)).to.be.rejectedWith('common.CollectionNotFound'); await expect(helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.stopSponsoringCollection', [999_999_999], true)).to.be.rejectedWith('common.CollectionNotFound'); }); }); - + describe('contract sponsoring', () => { itEth('should set palletes address as a sponsor', async ({helper}) => { const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase(); const flipper = await helper.eth.deployFlipper(contractOwner); // await deployFlipper(web3, contractOwner); - const contractHelper = helper.ethNativeContract.contractHelpers(contractOwner); - + const contractHelper = await helper.ethNativeContract.contractHelpers(contractOwner); + await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address]); - - expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; - expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); + + expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; + expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.deep.equal({ confirmed: { substrate: palletAddress, }, }); }); - + itEth('should overwrite sponsoring mode and existed sponsor', async ({helper}) => { const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase(); const flipper = await helper.eth.deployFlipper(contractOwner); // await deployFlipper(web3, contractOwner); - const contractHelper = helper.ethNativeContract.contractHelpers(contractOwner); - + const contractHelper = await helper.ethNativeContract.contractHelpers(contractOwner); + await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.fulfilled; - + // Contract is self sponsored expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.be.deep.equal({ confirmed: { ethereum: flipper.options.address.toLowerCase(), }, }); - + // set promotion sponsoring await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address], true); - + // new sponsor is pallet address - expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; - expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); + expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; + expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.deep.equal({ confirmed: { substrate: palletAddress, }, }); }); - + itEth('can be overwritten by contract owner', async ({helper}) => { const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase(); const flipper = await helper.eth.deployFlipper(contractOwner); // await deployFlipper(web3, contractOwner); - const contractHelper = helper.ethNativeContract.contractHelpers(contractOwner); - + const contractHelper = await helper.ethNativeContract.contractHelpers(contractOwner); + // contract sponsored by pallet await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address], true); - + // owner sets self sponsoring await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected; - - expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; - expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); + + expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.true; + expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.deep.equal({ confirmed: { ethereum: flipper.options.address.toLowerCase(), }, }); }); - + itEth('can not be set by non admin', async ({helper}) => { const nonAdmin = accounts.pop()!; const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase(); const flipper = await helper.eth.deployFlipper(contractOwner); // await deployFlipper(web3, contractOwner); - const contractHelper = helper.ethNativeContract.contractHelpers(contractOwner); - + const contractHelper = await helper.ethNativeContract.contractHelpers(contractOwner); + await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.fulfilled; - + // nonAdmin calls sponsorContract await expect(helper.executeExtrinsic(nonAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address], true)).to.be.rejectedWith('appPromotion.NoPermission'); - - // contract still self-sponsored + + // contract still self-sponsored expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.deep.equal({ confirmed: { ethereum: flipper.options.address.toLowerCase(), }, }); }); - + itEth('should actually sponsor transactions', async ({helper}) => { // Contract caller const caller = await helper.eth.createAccountWithBalance(donor, 1000n); const palletBalanceBefore = await helper.balance.getSubstrate(palletAddress); - + // Deploy flipper const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase(); const flipper = await helper.eth.deployFlipper(contractOwner); // await deployFlipper(web3, contractOwner); - const contractHelper = helper.ethNativeContract.contractHelpers(contractOwner); - + const contractHelper = await helper.ethNativeContract.contractHelpers(contractOwner); + // Owner sets to sponsor every tx await contractHelper.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: contractOwner}); await contractHelper.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: contractOwner}); await helper.eth.transferBalanceFromSubstrate(donor, flipper.options.address, 1000n); // transferBalanceToEth(api, alice, flipper.options.address, 1000n); - + // Set promotion to the Flipper await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address], true); - + // Caller calls Flipper await flipper.methods.flip().send({from: caller}); expect(await flipper.methods.getValue().call()).to.be.true; - + // The contracts and caller balances have not changed const callerBalance = await helper.balance.getEthereum(caller); const contractBalanceAfter = await helper.balance.getEthereum(flipper.options.address); expect(callerBalance).to.be.equal(1000n * nominal); expect(1000n * nominal === contractBalanceAfter).to.be.true; - + // The pallet balance has decreased const palletBalanceAfter = await helper.balance.getSubstrate(palletAddress); expect(palletBalanceAfter < palletBalanceBefore).to.be.true; }); }); - - describe('stopSponsoringContract', () => { + + describe('stopSponsoringContract', () => { itEth('should remove pallet address from contract sponsors', async ({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor, 1000n); const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase(); const flipper = await helper.eth.deployFlipper(contractOwner); await helper.eth.transferBalanceFromSubstrate(donor, flipper.options.address); - const contractHelper = helper.ethNativeContract.contractHelpers(contractOwner); - + const contractHelper = await helper.ethNativeContract.contractHelpers(contractOwner); + await contractHelper.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: contractOwner}); await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address], true); await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.stopSponsoringContract', [flipper.options.address], true); - - expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.false; - expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); + + expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.false; + expect((await helper.callRpc('api.query.evmContractHelpers.owner', [flipper.options.address])).toJSON()).to.be.equal(contractOwner); expect((await helper.callRpc('api.query.evmContractHelpers.sponsoring', [flipper.options.address])).toJSON()).to.deep.equal({ disabled: null, }); - + await flipper.methods.flip().send({from: caller}); expect(await flipper.methods.getValue().call()).to.be.true; - + const callerBalance = await helper.balance.getEthereum(caller); const contractBalanceAfter = await helper.balance.getEthereum(flipper.options.address); - + // caller payed for call expect(1000n * nominal > callerBalance).to.be.true; expect(contractBalanceAfter).to.be.equal(100n * nominal); }); - + itEth('can not be called by non-admin', async ({helper}) => { const nonAdmin = accounts.pop()!; const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase(); const flipper = await helper.eth.deployFlipper(contractOwner); - + await helper.executeExtrinsic(palletAdmin, 'api.tx.appPromotion.sponsorContract', [flipper.options.address]); await expect(helper.executeExtrinsic(nonAdmin, 'api.tx.appPromotion.stopSponsoringContract', [flipper.options.address])) .to.be.rejectedWith(/appPromotion\.NoPermission/); }); - + itEth('should not affect a contract which is not sponsored by pallete', async ({helper}) => { const nonAdmin = accounts.pop()!; const contractOwner = (await helper.eth.createAccountWithBalance(donor, 1000n)).toLowerCase(); const flipper = await helper.eth.deployFlipper(contractOwner); - const contractHelper = helper.ethNativeContract.contractHelpers(contractOwner); + const contractHelper = await helper.ethNativeContract.contractHelpers(contractOwner); await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.fulfilled; - + await expect(helper.executeExtrinsic(nonAdmin, 'api.tx.appPromotion.stopSponsoringContract', [flipper.options.address], true)).to.be.rejectedWith('appPromotion.NoPermission'); }); }); - + describe('payoutStakers', () => { itSub('can not be called by non admin', async ({helper}) => { const nonAdmin = accounts.pop()!; await expect(helper.admin.payoutStakers(nonAdmin, 100)).to.be.rejectedWith('appPromotion.NoPermission'); }); - + itSub('should increase total staked', async ({helper}) => { const staker = accounts.pop()!; const totalStakedBefore = await helper.staking.getTotalStaked(); await helper.staking.stake(staker, 100n * nominal); - + // Wait for rewards and pay const [stakedInBlock] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock.block)); const totalPayout = (await helper.admin.payoutStakers(palletAdmin, 100)).reduce((prev, payout) => prev + payout.payout, 0n); - + const totalStakedAfter = await helper.staking.getTotalStaked(); expect(totalStakedAfter).to.equal(totalStakedBefore + (100n * nominal) + totalPayout); // staker can unstake await helper.staking.unstake(staker); expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedAfter - calculateIncome(100n * nominal)); }); - - itSub('should credit 0.05% for staking period', async ({helper}) => { + + itSub('should credit 0.05% for staking period', async ({helper}) => { const staker = accounts.pop()!; - + await waitPromotionPeriodDoesntEnd(helper); - + await helper.staking.stake(staker, 100n * nominal); await helper.staking.stake(staker, 200n * nominal); - + // wait rewards are available: const [_stake1, stake2] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake2.block)); - + const payoutToStaker = (await helper.admin.payoutStakers(palletAdmin, 100)).find((payout) => payout.staker === staker.address)?.payout; expect(payoutToStaker + 300n * nominal).to.equal(calculateIncome(300n * nominal)); - + const totalStakedPerBlock = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); const income1 = calculateIncome(100n * nominal); const income2 = calculateIncome(200n * nominal); @@ -579,25 +579,25 @@ expect(stakerBalance).to.contain({miscFrozen: income1 + income2, feeFrozen: income1 + income2, reserved: 0n}); expect(stakerBalance.free / nominal).to.eq(999n); }); - + itSub('shoud be paid for more than one period if payments was missed', async ({helper}) => { const staker = accounts.pop()!; - + await helper.staking.stake(staker, 100n * nominal); // wait for two rewards are available: let [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake.block) + LOCKING_PERIOD); - + await helper.admin.payoutStakers(palletAdmin, 100); [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); const frozenBalanceShouldBe = calculateIncome(100n * nominal, 2); expect(stake.amount).to.be.equal(frozenBalanceShouldBe); - + const stakerFullBalance = await helper.balance.getSubstrateFull(staker.address); - + expect(stakerFullBalance).to.contain({reserved: 0n, feeFrozen: frozenBalanceShouldBe, miscFrozen: frozenBalanceShouldBe}); }); - + itSub('should not be credited for unstaked (reserved) balance', async ({helper}) => { // staker unstakes before rewards has been payed const staker = accounts.pop()!; @@ -605,37 +605,37 @@ const [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake.block) + LOCKING_PERIOD); await helper.staking.unstake(staker); - + // so he did not receive any rewards const totalBalanceBefore = await helper.balance.getSubstrate(staker.address); await helper.admin.payoutStakers(palletAdmin, 100); const totalBalanceAfter = await helper.balance.getSubstrate(staker.address); - + expect(totalBalanceBefore).to.be.equal(totalBalanceAfter); }); - + itSub('should bring compound interest', async ({helper}) => { const staker = accounts.pop()!; - + await helper.staking.stake(staker, 100n * nominal); - + let [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake.block)); - + await helper.admin.payoutStakers(palletAdmin, 100); [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); expect(stake.amount).to.equal(calculateIncome(100n * nominal)); - + await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stake.block) + LOCKING_PERIOD); await helper.admin.payoutStakers(palletAdmin, 100); [stake] = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); expect(stake.amount).to.equal(calculateIncome(100n * nominal, 2)); }); - + itSub.skip('can be paid 1000 rewards in a time', async ({helper}) => { // all other stakes should be unstaked const oneHundredStakers = await helper.arrange.createCrowd(100, 1050n, donor); - + // stakers stakes 10 times each for (let i = 0; i < 10; i++) { await Promise.all(oneHundredStakers.map(staker => helper.staking.stake(staker, 100n * nominal))); @@ -643,20 +643,20 @@ await helper.wait.newBlocks(40); await helper.admin.payoutStakers(palletAdmin, 100); }); - + itSub.skip('can handle 40.000 rewards', async ({helper}) => { const crowdStakes = async () => { // each account in the crowd stakes 2 times const crowd = await helper.arrange.createCrowd(500, 300n, donor); await Promise.all(crowd.map(account => helper.staking.stake(account, 100n * nominal))); await Promise.all(crowd.map(account => helper.staking.stake(account, 100n * nominal))); - // + // }; - + for (let i = 0; i < 40; i++) { await crowdStakes(); } - + // TODO pay rewards for some period }); }); @@ -667,7 +667,7 @@ const ACCURACY = 1_000_000_000n; // 5n / 10_000n = 0.05% p/day const income = base + base * (ACCURACY * (calcPeriod * 5n) / (10_000n * DAY)) / ACCURACY ; - + if (iter > 1) { return calculateIncome(income, iter - 1, calcPeriod); } else return income; --- a/tests/src/benchmarks/mintFee/benchmark.ts +++ b/tests/src/benchmarks/mintFee/benchmark.ts @@ -210,7 +210,7 @@ ); const collectionEthAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionContract = helper.ethNativeContract.collection( + const collectionContract = await helper.ethNativeContract.collection( collectionEthAddress, 'nft', ); @@ -290,7 +290,7 @@ ethSigner, proxyContract.options.address, async (collection) => { - const evmContract = helper.ethNativeContract.collection( + const evmContract = await helper.ethNativeContract.collection( helper.ethAddress.fromCollectionId(collection.collectionId), 'nft', ); @@ -330,7 +330,7 @@ ethSigner, proxyContract.options.address, async (collection) => { - const evmContract = helper.ethNativeContract.collection( + const evmContract = await helper.ethNativeContract.collection( helper.ethAddress.fromCollectionId(collection.collectionId), 'nft', ); --- a/tests/src/calibrate.ts +++ b/tests/src/calibrate.ts @@ -246,7 +246,7 @@ const token = await collection.mintToken(alice, {Ethereum: caller}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft', caller); + const contract = await helper.ethNativeContract.collection(address, 'nft', caller); const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gas: helper.eth.DEFAULT_GAS})); @@ -266,7 +266,7 @@ const token = await collection.mintToken(alice, {Ethereum: caller}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft', caller); + const contract = await helper.ethNativeContract.collection(address, 'nft', caller); const transferPrice = new Fract(await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gasPrice: gasPriceStr, gas: helper.eth.DEFAULT_GAS}))); @@ -287,7 +287,7 @@ const token = await collection.mintToken(alice, {Ethereum: caller}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft', caller); + const contract = await helper.ethNativeContract.collection(address, 'nft', caller); const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, token.tokenId).send({from: caller, gas: helper.eth.DEFAULT_GAS})); --- a/tests/src/eth/allowlist.test.ts +++ b/tests/src/eth/allowlist.test.ts @@ -30,7 +30,7 @@ itEth('Contract allowlist can be toggled', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const flipper = await helper.eth.deployFlipper(owner); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); // Any user is allowed by default expect(await helpers.methods.allowlistEnabled(flipper.options.address).call()).to.be.false; @@ -48,7 +48,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const caller = await helper.eth.createAccountWithBalance(donor); const flipper = await helper.eth.deployFlipper(owner); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); // User can flip with allowlist disabled await flipper.methods.flip().send({from: caller}); @@ -80,9 +80,9 @@ const owner = await helper.eth.createAccountWithBalance(donor); const user = helper.eth.createAccount(); const crossUser = helper.ethCrossAccount.fromAddress(user); - + const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); expect(await collectionEvm.methods.allowlistedCross(crossUser).call({from: owner})).to.be.false; await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner}); @@ -97,19 +97,19 @@ {mode: 'nft' as const, requiredPallets: []}, {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, {mode: 'ft' as const, requiredPallets: []}, - ].map(testCase => + ].map(testCase => itEth.ifWithPallets(`Collection allowlist can be added and removed by [cross] address for ${testCase.mode}`, testCase.requiredPallets, async ({helper}) => { const owner = (await helper.eth.createAccountWithBalance(donor)).toLowerCase(); const [userSub] = await helper.arrange.createAccounts([10n], donor); const userEth = await helper.eth.createAccountWithBalance(donor); const mintParams = testCase.mode === 'ft' ? [userEth, 100] : [userEth]; - + const {collectionAddress, collectionId} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); const userCrossSub = helper.ethCrossAccount.fromKeyringPair(userSub); const userCrossEth = helper.ethCrossAccount.fromAddress(userEth); const ownerCrossEth = helper.ethCrossAccount.fromAddress(owner); - + // Can addToCollectionAllowListCross: expect(await helper.collection.allowed(collectionId, {Substrate: userSub.address})).to.be.false; await collectionEvm.methods.addToCollectionAllowListCross(userCrossSub).send({from: owner}); @@ -121,11 +121,11 @@ expect(await helper.collection.allowed(collectionId, {Ethereum: userEth})).to.be.true; expect(await collectionEvm.methods.allowlistedCross(userCrossSub).call({from: owner})).to.be.true; expect(await collectionEvm.methods.allowlistedCross(userCrossEth).call({from: owner})).to.be.true; - + await collectionEvm.methods.mint(...mintParams).send({from: owner}); // token #1 await collectionEvm.methods.mint(...mintParams).send({from: owner}); // token #2 await collectionEvm.methods.setCollectionAccess(SponsoringMode.Allowlisted).send({from: owner}); - + // allowlisted account can transfer and transferCross from eth: await collectionEvm.methods.transfer(owner, 1).send({from: userEth}); await collectionEvm.methods.transferCross(userCrossSub, 2).send({from: userEth}); @@ -142,7 +142,7 @@ testCase.mode === 'ft' ? await helper.ft.transfer(userSub, collectionId, {Ethereum: userEth}, 2n) : await helper.collection.transferToken(userSub, collectionId, 2, {Ethereum: userEth}); - + // can removeFromCollectionAllowListCross: await collectionEvm.methods.removeFromCollectionAllowListCross(userCrossSub).send({from: owner}); await collectionEvm.methods.removeFromCollectionAllowListCross(userCrossEth).send({from: owner}); @@ -150,7 +150,7 @@ expect(await helper.collection.allowed(collectionId, {Ethereum: userEth})).to.be.false; expect(await collectionEvm.methods.allowlistedCross(userCrossSub).call({from: owner})).to.be.false; expect(await collectionEvm.methods.allowlistedCross(userCrossEth).call({from: owner})).to.be.false; - + // cannot transfer anymore await collectionEvm.methods.mint(...mintParams).send({from: owner}); await expect(collectionEvm.methods.transfer(owner, 2).send({from: userEth})).to.be.rejectedWith(/Transaction has been reverted/); @@ -165,7 +165,7 @@ {mode: 'nft' as const, cross: false, requiredPallets: []}, {mode: 'rft' as const, cross: false, requiredPallets: [Pallets.ReFungible]}, {mode: 'ft' as const, cross: false, requiredPallets: []}, - ].map(testCase => + ].map(testCase => itEth.ifWithPallets(`Non-owner cannot add or remove from collection allowlist ${testCase.cross ? 'cross ' : ''}${testCase.mode}`, testCase.requiredPallets, async ({helper}) => { // Select methods: const addToAllowList = testCase.cross ? 'addToCollectionAllowListCross' : 'addToCollectionAllowList'; @@ -179,11 +179,11 @@ const userCrossEth = helper.ethCrossAccount.fromAddress(userEth); const {collectionAddress, collectionId} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner, !testCase.cross); - + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner, !testCase.cross); + expect(await helper.collection.allowed(collectionId, {Substrate: userSub.address})).to.be.false; expect(await helper.collection.allowed(collectionId, {Ethereum: userEth})).to.be.false; - + // 1. notOwner cannot add to allow list: // 1.1 plain ethereum or cross address: await expect(collectionEvm.methods[addToAllowList](testCase.cross ? userCrossEth : userEth).call({from: notOwner})).to.be.rejectedWith('NoPermission'); @@ -200,7 +200,7 @@ expect(await helper.collection.allowed(collectionId, {Substrate: userSub.address})).to.be.true; } expect(await helper.collection.allowed(collectionId, {Ethereum: userEth})).to.be.true; - + // 3. notOwner cannot remove from allow list: // 3.1 plain ethereum or cross address: await expect(collectionEvm.methods[removeFromAllowList](testCase.cross ? userCrossEth : userEth).call({from: notOwner})).to.be.rejectedWith('NoPermission'); --- a/tests/src/eth/base.test.ts +++ b/tests/src/eth/base.test.ts @@ -57,7 +57,7 @@ const {tokenId} = await collection.mintToken(alice, {Ethereum: caller}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft', caller); + const contract = await helper.ethNativeContract.collection(address, 'nft', caller); const cost = await helper.eth.calculateFee({Ethereum: caller}, () => contract.methods.transfer(receiver, tokenId).send(caller)); @@ -79,8 +79,8 @@ const BASE_URI = 'base/'; async function checkInterface(helper: EthUniqueHelper, interfaceId: string, simpleResult: boolean, compatibleResult: boolean) { - const simple = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(simpleNftCollectionId), 'nft', minter); - const compatible = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(erc721MetadataCompatibleNftCollectionId), 'nft', minter); + const simple = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(simpleNftCollectionId), 'nft', minter); + const compatible = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(erc721MetadataCompatibleNftCollectionId), 'nft', minter); expect(await simple.methods.supportsInterface(interfaceId).call()).to.equal(simpleResult, `empty (not ERC721Metadata compatible) NFT collection returns not ${simpleResult}`); expect(await compatible.methods.supportsInterface(interfaceId).call()).to.equal(compatibleResult, `ERC721Metadata compatible NFT collection returns not ${compatibleResult}`); --- a/tests/src/eth/collectionAdmin.test.ts +++ b/tests/src/eth/collectionAdmin.test.ts @@ -50,30 +50,30 @@ const owner = await helper.eth.createAccountWithBalance(donor); const adminSub = await privateKey('//admin2'); const adminEth = helper.eth.createAccount().toLowerCase(); - + const adminDeprecated = helper.eth.createAccount().toLowerCase(); const adminCrossSub = helper.ethCrossAccount.fromKeyringPair(adminSub); const adminCrossEth = helper.ethCrossAccount.fromAddress(adminEth); - + const {collectionAddress, collectionId} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner, true); // Check isOwnerOrAdminCross returns false: expect(await collectionEvm.methods.isOwnerOrAdminCross(adminCrossSub).call()).to.be.false; expect(await collectionEvm.methods.isOwnerOrAdminCross(adminCrossEth).call()).to.be.false; expect(await collectionEvm.methods.isOwnerOrAdminCross(helper.ethCrossAccount.fromAddress(adminDeprecated)).call()).to.be.false; - - // Soft-deprecated: can addCollectionAdmin + + // Soft-deprecated: can addCollectionAdmin await collectionEvm.methods.addCollectionAdmin(adminDeprecated).send(); // Can addCollectionAdminCross for substrate and ethereum address await collectionEvm.methods.addCollectionAdminCross(adminCrossSub).send(); await collectionEvm.methods.addCollectionAdminCross(adminCrossEth).send(); - + // 1. Expect api.rpc.unique.adminlist returns admins: const adminListRpc = await helper.collection.getAdmins(collectionId); expect(adminListRpc).to.has.length(3); expect(adminListRpc).to.be.deep.contain.members([{Substrate: adminSub.address}, {Ethereum: adminEth}, {Ethereum: adminDeprecated}]); - + // 2. Expect methods.collectionAdmins == api.rpc.unique.adminlist let adminListEth = await collectionEvm.methods.collectionAdmins().call(); adminListEth = adminListEth.map((element: IEthCrossAccountId) => { @@ -96,12 +96,12 @@ const adminCrossEth = helper.ethCrossAccount.fromAddress(adminEth); const [adminSub] = await helper.arrange.createAccounts([100n], donor); const adminCrossSub = helper.ethCrossAccount.fromKeyringPair(adminSub); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); - + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + // cannot mint while not admin await expect(collectionEvm.methods.mint(owner).send({from: adminEth})).to.be.rejected; await expect(helper.nft.mintToken(adminSub, {collectionId, owner: {Ethereum: owner}})).to.be.rejectedWith(/common.PublicMintingNotAllowed/); - + // admin (sub and eth) can mint token: await collectionEvm.methods.addCollectionAdminCross(adminCrossEth).send(); await collectionEvm.methods.addCollectionAdminCross(adminCrossSub).send(); @@ -116,7 +116,7 @@ const [admin] = await helper.arrange.createAccounts([100n, 100n], donor); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const adminCross = { eth: helper.address.substrateToEth(admin.address), @@ -132,8 +132,8 @@ const adminDeprecated = helper.eth.createAccount(); const admin1Cross = helper.ethCrossAccount.fromKeyringPair(await privateKey('admin')); const admin2Cross = helper.ethCrossAccount.fromAddress(helper.address.substrateToEth((await privateKey('admin3')).address)); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); - + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + // Soft-deprecated: expect(await collectionEvm.methods.isOwnerOrAdmin(adminDeprecated).call()).to.be.false; expect(await collectionEvm.methods.isOwnerOrAdminCross(admin1Cross).call()).to.be.false; @@ -156,7 +156,7 @@ const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); const admin = await helper.eth.createAccountWithBalance(donor); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); await collectionEvm.methods.addCollectionAdmin(admin).send(); const user = helper.eth.createAccount(); @@ -175,7 +175,7 @@ const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); const notAdmin = await helper.eth.createAccountWithBalance(donor); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); const user = helper.eth.createAccount(); await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: notAdmin})) @@ -191,7 +191,7 @@ const [admin, notAdmin] = await helper.arrange.createAccounts([10n, 10n], donor); const adminCross = helper.ethCrossAccount.fromKeyringPair(admin); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); await collectionEvm.methods.addCollectionAdminCross(adminCross).send(); const notAdminCross = helper.ethCrossAccount.fromKeyringPair(notAdmin); @@ -200,7 +200,7 @@ const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]); expect(adminList.length).to.be.eq(1); - + const admin0Cross = helper.ethCrossAccount.fromKeyringPair(adminList[0]); expect(admin0Cross.eth.toLocaleLowerCase()) .to.be.eq(adminCross.eth.toLocaleLowerCase()); @@ -211,7 +211,7 @@ const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); const notAdmin0 = await helper.eth.createAccountWithBalance(donor); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const [notAdmin1] = await helper.arrange.createAccounts([10n], donor); const notAdmin1Cross = helper.ethCrossAccount.fromKeyringPair(notAdmin1); await expect(collectionEvm.methods.addCollectionAdminCross(notAdmin1Cross).call({from: notAdmin0})) @@ -237,7 +237,7 @@ const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); const newAdmin = helper.eth.createAccount(); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); await collectionEvm.methods.addCollectionAdmin(newAdmin).send(); { @@ -261,7 +261,7 @@ const adminCrossSub = helper.ethCrossAccount.fromKeyringPair(adminSub); const adminCrossEth = helper.ethCrossAccount.fromAddress(adminEth); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); await collectionEvm.methods.addCollectionAdminCross(adminCrossSub).send(); await collectionEvm.methods.addCollectionAdminCross(adminCrossEth).send(); @@ -286,7 +286,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); const admin0 = await helper.eth.createAccountWithBalance(donor); await collectionEvm.methods.addCollectionAdmin(admin0).send(); @@ -309,7 +309,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); const admin = await helper.eth.createAccountWithBalance(donor); await collectionEvm.methods.addCollectionAdmin(admin).send(); @@ -331,9 +331,9 @@ const [admin1] = await helper.arrange.createAccounts([10n], donor); const admin1Cross = helper.ethCrossAccount.fromKeyringPair(admin1); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); await collectionEvm.methods.addCollectionAdminCross(admin1Cross).send(); - + const [admin2] = await helper.arrange.createAccounts([10n], donor); const admin2Cross = helper.ethCrossAccount.fromKeyringPair(admin2); await collectionEvm.methods.addCollectionAdminCross(admin2Cross).send(); @@ -354,7 +354,7 @@ const [adminSub] = await helper.arrange.createAccounts([10n], donor); const adminSubCross = helper.ethCrossAccount.fromKeyringPair(adminSub); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); await collectionEvm.methods.addCollectionAdminCross(adminSubCross).send(); const notAdminEth = await helper.eth.createAccountWithBalance(donor); @@ -382,7 +382,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const newOwner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); await collectionEvm.methods.changeCollectionOwner(newOwner).send(); @@ -394,7 +394,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const newOwner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.changeCollectionOwner(newOwner).send()); expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); expect(cost > 0); @@ -404,7 +404,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const newOwner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); await expect(collectionEvm.methods.changeCollectionOwner(newOwner).send({from: newOwner})).to.be.rejected; expect(await collectionEvm.methods.isOwnerOrAdmin(newOwner).call()).to.be.false; @@ -428,7 +428,7 @@ const ownerCrossSub = helper.ethCrossAccount.fromKeyringPair(ownerSub); const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); expect(await collectionEvm.methods.isOwnerOrAdminCross(ownerCrossSub).call()).to.be.false; @@ -437,7 +437,7 @@ expect(await collectionEvm.methods.isOwnerOrAdminCross(ownerCrossEth).call()).to.be.true; expect(await helper.collection.getData(collectionId)) .to.have.property('normalizedOwner').that.is.eq(helper.address.ethToSubstrate(ownerEth)); - + // Can set Substrate owner: await collectionEvm.methods.changeCollectionOwnerCross(ownerCrossSub).send({from: ownerEth}); expect(await collectionEvm.methods.isOwnerOrAdminCross(ownerCrossSub).call()).to.be.true; @@ -449,7 +449,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const [newOwner] = await helper.arrange.createAccounts([10n], donor); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send()); expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); @@ -462,7 +462,7 @@ const [newOwner] = await helper.arrange.createAccounts([10n], donor); const newOwnerCross = helper.ethCrossAccount.fromKeyringPair(newOwner); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); await expect(collectionEvm.methods.changeCollectionOwnerCross(newOwnerCross).send({from: otherReceiver})).to.be.rejected; expect(await collectionEvm.methods.isOwnerOrAdminCross(newOwnerCross).call()).to.be.false; --- a/tests/src/eth/collectionHelperAddress.test.ts +++ b/tests/src/eth/collectionHelperAddress.test.ts @@ -31,42 +31,42 @@ itEth('NFT', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - + const {collectionAddress: nftCollectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC'); - const nftCollection = helper.ethNativeContract.collection(nftCollectionAddress, 'nft', owner); - + const nftCollection = await helper.ethNativeContract.collection(nftCollectionAddress, 'nft', owner); + expect((await nftCollection.methods.collectionHelperAddress().call()) .toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS); }); - + itEth.ifWithPallets('RFT ', [Pallets.ReFungible], async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress: rftCollectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC'); - const rftCollection = helper.ethNativeContract.collection(rftCollectionAddress, 'rft', owner); + const rftCollection = await helper.ethNativeContract.collection(rftCollectionAddress, 'rft', owner); expect((await rftCollection.methods.collectionHelperAddress().call()) .toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS); }); - + itEth('FT', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', 18, 'absolutely anything', 'ROC'); - const collection = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); - + const collection = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + expect((await collection.methods.collectionHelperAddress().call()) .toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS); }); - + itEth('[collectionHelpers] convert collectionId into address', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const collectionId = 7; const collectionAddress = helper.ethAddress.fromCollectionId(collectionId); - const helperContract = helper.ethNativeContract.collectionHelpers(owner); - + const helperContract = await helper.ethNativeContract.collectionHelpers(owner); + expect(await helperContract.methods.collectionAddress(collectionId).call()).to.be.equal(collectionAddress); expect(parseInt(await helperContract.methods.collectionId(collectionAddress).call())).to.be.equal(collectionId); }); - + }); --- a/tests/src/eth/collectionLimits.test.ts +++ b/tests/src/eth/collectionLimits.test.ts @@ -32,7 +32,7 @@ ownerCanDestroy: 0, transfersEnabled: 0, }; - + const expectedLimits = { accountTokenOwnershipLimit: 1000, sponsoredDataSize: 1024, @@ -44,8 +44,8 @@ ownerCanDestroy: false, transfersEnabled: false, }; - - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.case, owner); + + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.case, owner); await collectionEvm.methods.setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, limits.accountTokenOwnershipLimit).send(); await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsoredDataSize, true, limits.sponsoredDataSize).send(); await collectionEvm.methods.setCollectionLimit(CollectionLimits.SponsoredDataRateLimit, true, limits.sponsoredDataRateLimit).send(); @@ -55,7 +55,7 @@ await collectionEvm.methods.setCollectionLimit(CollectionLimits.OwnerCanTransfer, true, limits.ownerCanTransfer).send(); await collectionEvm.methods.setCollectionLimit(CollectionLimits.OwnerCanDestroy, true, limits.ownerCanDestroy).send(); await collectionEvm.methods.setCollectionLimit(CollectionLimits.TransferEnabled, true, limits.transfersEnabled).send(); - + // Check limits from sub: const data = (await helper.rft.getData(collectionId))!; expect(data.raw.limits).to.deep.eq(expectedLimits); @@ -97,13 +97,13 @@ const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createCollection(testCase.case, owner, 'Limits', 'absolutely anything', 'ISNI', 18); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.case, owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.case, owner); // Cannot set non-existing limit await expect(collectionEvm.methods .setCollectionLimit(9, true, 1) - .call()).to.be.rejectedWith('Returned error: VM Exception while processing transaction: revert Value not convertible into enum "CollectionLimits"'); - + .call()).to.be.rejectedWith('Returned error: VM Exception while processing transaction: revert Value not convertible into enum "CollectionLimits"'); + // Cannot disable limits await expect(collectionEvm.methods .setCollectionLimit(CollectionLimits.AccountTokenOwnership, false, 200) @@ -112,7 +112,7 @@ await expect(collectionEvm.methods .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, invalidLimits.accountTokenOwnershipLimit) .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`); - + await expect(collectionEvm.methods .setCollectionLimit(CollectionLimits.TransferEnabled, true, 3) .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`); @@ -131,7 +131,7 @@ const nonOwner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createCollection(testCase.case, owner, 'Limits', 'absolutely anything', 'FLO', 18); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.case, owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.case, owner); await expect(collectionEvm.methods .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000) .call({from: nonOwner})) --- a/tests/src/eth/collectionProperties.test.ts +++ b/tests/src/eth/collectionProperties.test.ts @@ -32,20 +32,20 @@ // Soft-deprecated: setCollectionProperty [ - {method: 'setCollectionProperties', mode: 'nft' as const, methodParams: [[{key: 'testKey1', value: Buffer.from('testValue1')}, {key: 'testKey2', value: Buffer.from('testValue2')}]], expectedProps: [{key: 'testKey1', value: 'testValue1'}, {key: 'testKey2', value: 'testValue2'}]}, - {method: 'setCollectionProperties', mode: 'rft' as const, methodParams: [[{key: 'testKey1', value: Buffer.from('testValue1')}, {key: 'testKey2', value: Buffer.from('testValue2')}]], expectedProps: [{key: 'testKey1', value: 'testValue1'}, {key: 'testKey2', value: 'testValue2'}]}, - {method: 'setCollectionProperties', mode: 'ft' as const, methodParams: [[{key: 'testKey1', value: Buffer.from('testValue1')}, {key: 'testKey2', value: Buffer.from('testValue2')}]], expectedProps: [{key: 'testKey1', value: 'testValue1'}, {key: 'testKey2', value: 'testValue2'}]}, + {method: 'setCollectionProperties', mode: 'nft' as const, methodParams: [[{key: 'testKey1', value: Buffer.from('testValue1')}, {key: 'testKey2', value: Buffer.from('testValue2')}]], expectedProps: [{key: 'testKey1', value: 'testValue1'}, {key: 'testKey2', value: 'testValue2'}]}, + {method: 'setCollectionProperties', mode: 'rft' as const, methodParams: [[{key: 'testKey1', value: Buffer.from('testValue1')}, {key: 'testKey2', value: Buffer.from('testValue2')}]], expectedProps: [{key: 'testKey1', value: 'testValue1'}, {key: 'testKey2', value: 'testValue2'}]}, + {method: 'setCollectionProperties', mode: 'ft' as const, methodParams: [[{key: 'testKey1', value: Buffer.from('testValue1')}, {key: 'testKey2', value: Buffer.from('testValue2')}]], expectedProps: [{key: 'testKey1', value: 'testValue1'}, {key: 'testKey2', value: 'testValue2'}]}, {method: 'setCollectionProperty', mode: 'nft' as const, methodParams: ['testKey', Buffer.from('testValue')], expectedProps: [{key: 'testKey', value: 'testValue'}]}, - ].map(testCase => + ].map(testCase => itEth.ifWithPallets(`Collection properties can be set: ${testCase.method}() for ${testCase.mode}`, testCase.mode === 'rft' ? [Pallets.ReFungible] : [], async({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); const collection = await helper[testCase.mode].mintCollection(alice, {name: 'name', description: 'test', tokenPrefix: 'test', properties: []}); await collection.addAdmin(alice, {Ethereum: caller}); - + const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(address, 'nft', caller, testCase.method === 'setCollectionProperty'); + const collectionEvm = await helper.ethNativeContract.collection(address, 'nft', caller, testCase.method === 'setCollectionProperty'); - // collectionProperties returns an empty array if no properties: + // collectionProperties returns an empty array if no properties: expect(await collectionEvm.methods.collectionProperties([]).call()).to.be.like([]); expect(await collectionEvm.methods.collectionProperties(['NonExistingKey']).call()).to.be.like([]); @@ -54,7 +54,7 @@ const raw = (await collection.getData())?.raw; expect(raw.properties).to.deep.equal(testCase.expectedProps); - // collectionProperties returns properties: + // collectionProperties returns properties: expect(await collectionEvm.methods.collectionProperties([]).call()).to.be.like(testCase.expectedProps.map(prop => helper.ethProperty.property(prop.key, prop.value))); })); @@ -64,7 +64,7 @@ await collection.addAdmin(alice, {Ethereum: caller}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft', caller); + const contract = await helper.ethNativeContract.collection(address, 'nft', caller); await expect(contract.methods.setCollectionProperties([{key: '', value: Buffer.from('val1')}]).send({from: caller})).to.be.rejected; await expect(contract.methods.setCollectionProperties([{key: 'déjà vu', value: Buffer.from('hmm...')}]).send({from: caller})).to.be.rejected; @@ -80,8 +80,8 @@ {method: 'deleteCollectionProperties', mode: 'nft' as const, methodParams: [['testKey1', 'testKey2']], expectedProps: [{key: 'testKey3', value: 'testValue3'}]}, {method: 'deleteCollectionProperties', mode: 'rft' as const, methodParams: [['testKey1', 'testKey2']], expectedProps: [{key: 'testKey3', value: 'testValue3'}]}, {method: 'deleteCollectionProperties', mode: 'ft' as const, methodParams: [['testKey1', 'testKey2']], expectedProps: [{key: 'testKey3', value: 'testValue3'}]}, - {method: 'deleteCollectionProperty', mode: 'nft' as const, methodParams: ['testKey1'], expectedProps: [{key: 'testKey2', value: 'testValue2'}, {key: 'testKey3', value: 'testValue3'}]}, - ].map(testCase => + {method: 'deleteCollectionProperty', mode: 'nft' as const, methodParams: ['testKey1'], expectedProps: [{key: 'testKey2', value: 'testValue2'}, {key: 'testKey3', value: 'testValue3'}]}, + ].map(testCase => itEth.ifWithPallets(`Collection properties can be deleted: ${testCase.method}() for ${testCase.mode}`, testCase.mode === 'rft' ? [Pallets.ReFungible] : [], async({helper}) => { const properties = [ {key: 'testKey1', value: 'testValue1'}, @@ -89,16 +89,16 @@ {key: 'testKey3', value: 'testValue3'}]; const caller = await helper.eth.createAccountWithBalance(donor); const collection = await helper[testCase.mode].mintCollection(alice, {name: 'name', description: 'test', tokenPrefix: 'test', properties}); - + await collection.addAdmin(alice, {Ethereum: caller}); - + const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft', caller, testCase.method === 'deleteCollectionProperty'); - + const contract = await helper.ethNativeContract.collection(address, 'nft', caller, testCase.method === 'deleteCollectionProperty'); + await contract.methods[testCase.method](...testCase.methodParams).send({from: caller}); - + const raw = (await collection.getData())?.raw; - + expect(raw.properties.length).to.equal(testCase.expectedProps.length); expect(raw.properties).to.deep.equal(testCase.expectedProps); })); @@ -106,7 +106,7 @@ [ {method: 'deleteCollectionProperties', methodParams: [['testKey2']]}, {method: 'deleteCollectionProperty', methodParams: ['testKey2']}, - ].map(testCase => + ].map(testCase => itEth(`cannot ${testCase.method}() of non-owned collections`, async ({helper}) => { const properties = [ {key: 'testKey1', value: 'testValue1'}, @@ -116,7 +116,7 @@ const collection = await helper.nft.mintCollection(alice, {name: 'name', description: 'test', tokenPrefix: 'test', properties}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(address, 'nft', caller, testCase.method === 'deleteCollectionProperty'); + const collectionEvm = await helper.ethNativeContract.collection(address, 'nft', caller, testCase.method === 'deleteCollectionProperty'); await expect(collectionEvm.methods[testCase.method](...testCase.methodParams).send({from: caller})).to.be.rejected; expect(await collection.getProperties()).to.deep.eq(properties); @@ -127,7 +127,7 @@ const collection = await helper.nft.mintCollection(alice, {name: 'name', description: 'test', tokenPrefix: 'test', properties: [{key: 'testKey', value: 'testValue'}]}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft', caller); + const contract = await helper.ethNativeContract.collection(address, 'nft', caller); const value = await contract.methods.collectionProperty('testKey').call(); expect(value).to.equal(helper.getWeb3().utils.toHex('testValue')); @@ -146,75 +146,75 @@ [ {case: 'nft' as const}, {case: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, - ].map(testCase => + ].map(testCase => itEth.ifWithPallets(`ERC721Metadata property can be set for ${testCase.case} collection`, testCase.requiredPallets || [], async ({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); const bruh = await helper.eth.createAccountWithBalance(donor); - + const BASE_URI = 'base/'; const SUFFIX = 'suffix1'; const URI = 'uri1'; - - const collectionHelpers = helper.ethNativeContract.collectionHelpers(caller); + + const collectionHelpers = await helper.ethNativeContract.collectionHelpers(caller); const creatorMethod = testCase.case === 'rft' ? 'createRFTCollection' : 'createNFTCollection'; - + const {collectionId, collectionAddress} = await helper.eth[creatorMethod](caller, 'n', 'd', 'p'); const bruhCross = helper.ethCrossAccount.fromAddress(bruh); - - const contract = helper.ethNativeContract.collectionById(collectionId, testCase.case, caller); + + const contract = await helper.ethNativeContract.collectionById(collectionId, testCase.case, caller); await contract.methods.addCollectionAdminCross(bruhCross).send(); // to check that admin will work too - + const collection1 = helper.nft.getCollectionObject(collectionId); const data1 = await collection1.getData(); expect(data1?.raw.flags.erc721metadata).to.be.false; expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.false; - + await collectionHelpers.methods.makeCollectionERC721MetadataCompatible(collectionAddress, BASE_URI) .send({from: bruh}); - + expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.true; - + const collection2 = helper.nft.getCollectionObject(collectionId); const data2 = await collection2.getData(); expect(data2?.raw.flags.erc721metadata).to.be.true; - + const propertyPermissions = data2?.raw.tokenPropertyPermissions; expect(propertyPermissions?.length).to.equal(2); - + expect(propertyPermissions.find((tpp: ITokenPropertyPermission) => { return tpp.key === 'URI' && tpp.permission.mutable && tpp.permission.collectionAdmin && !tpp.permission.tokenOwner; })).to.be.not.null; - + expect(propertyPermissions.find((tpp: ITokenPropertyPermission) => { return tpp.key === 'URISuffix' && tpp.permission.mutable && tpp.permission.collectionAdmin && !tpp.permission.tokenOwner; })).to.be.not.null; - + expect(data2?.raw.properties?.find((property: IProperty) => { return property.key === 'baseURI' && property.value === BASE_URI; })).to.be.not.null; - + const token1Result = await contract.methods.mint(bruh).send(); const tokenId1 = token1Result.events.Transfer.returnValues.tokenId; - + expect(await contract.methods.tokenURI(tokenId1).call()).to.equal(BASE_URI); - + await contract.methods.setProperties(tokenId1, [{key: 'URISuffix', value: Buffer.from(SUFFIX)}]).send(); expect(await contract.methods.tokenURI(tokenId1).call()).to.equal(BASE_URI + SUFFIX); - + await contract.methods.setProperties(tokenId1, [{key: 'URI', value: Buffer.from(URI)}]).send(); expect(await contract.methods.tokenURI(tokenId1).call()).to.equal(URI); - + await contract.methods.deleteProperties(tokenId1, ['URI']).send(); expect(await contract.methods.tokenURI(tokenId1).call()).to.equal(BASE_URI + SUFFIX); - + const token2Result = await contract.methods.mintWithTokenURI(bruh, URI).send(); const tokenId2 = token2Result.events.Transfer.returnValues.tokenId; - + expect(await contract.methods.tokenURI(tokenId2).call()).to.equal(URI); - + await contract.methods.deleteProperties(tokenId2, ['URI']).send(); expect(await contract.methods.tokenURI(tokenId2).call()).to.equal(BASE_URI); - + await contract.methods.setProperties(tokenId2, [{key: 'URISuffix', value: Buffer.from(SUFFIX)}]).send(); expect(await contract.methods.tokenURI(tokenId2).call()).to.equal(BASE_URI + SUFFIX); })); --- a/tests/src/eth/collectionSponsoring.test.ts +++ b/tests/src/eth/collectionSponsoring.test.ts @@ -30,7 +30,7 @@ nominal = helper.balance.getOneTokenNominal(); }); }); - + // TODO: move to substrate tests itEth('sponsors mint transactions', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'spnr', permissions: {mintMode: true}}); @@ -41,7 +41,7 @@ expect(await helper.balance.getEthereum(minter)).to.equal(0n); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', minter); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', minter); await collection.addToAllowList(alice, {Ethereum: minter}); @@ -85,26 +85,26 @@ [ 'setCollectionSponsorCross', 'setCollectionSponsor', // Soft-deprecated - ].map(testCase => + ].map(testCase => itEth(`[${testCase}] can remove collection sponsor`, async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner); - + const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner); + let result = await collectionHelpers.methods.createNFTCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)}); const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId); const sponsor = await helper.eth.createAccountWithBalance(donor); const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor); - const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner, testCase === 'setCollectionSponsor'); - + const collectionEvm = await helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner, testCase === 'setCollectionSponsor'); + expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false; result = await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send({from: owner}); expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true; - + await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor}); expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false; - + await collectionEvm.methods.removeCollectionSponsor().send({from: owner}); - + const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner}); expect(sponsorTuple.eth).to.be.eq('0x0000000000000000000000000000000000000000'); })); @@ -112,35 +112,35 @@ [ 'setCollectionSponsorCross', 'setCollectionSponsor', // Soft-deprecated - ].map(testCase => + ].map(testCase => itEth(`[${testCase}] Can sponsor from evm address via access list`, async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const sponsorEth = await helper.eth.createAccountWithBalance(donor); const sponsorCrossEth = helper.ethCrossAccount.fromAddress(sponsorEth); - + const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Sponsor collection', '1', '1', ''); - + const collectionSub = helper.nft.getCollectionObject(collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor'); - + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor'); + // Set collection sponsor: await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsorEth : sponsorCrossEth).send({from: owner}); let sponsorship = (await collectionSub.getData())!.raw.sponsorship; expect(sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true)); // Account cannot confirm sponsorship if it is not set as a sponsor await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail'); - + // Sponsor can confirm sponsorship: await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth}); sponsorship = (await collectionSub.getData())!.raw.sponsorship; expect(sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsorEth, true)); - + // Create user with no balance: const user = helper.eth.createAccount(); const userCross = helper.ethCrossAccount.fromAddress(user); const nextTokenId = await collectionEvm.methods.nextTokenId().call(); expect(nextTokenId).to.be.equal('1'); - + // Set collection permissions: const oldPermissions = (await collectionSub.getData())!.raw.permissions; // (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman(); expect(oldPermissions.mintMode).to.be.false; @@ -149,11 +149,11 @@ await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner}); await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner}); await collectionEvm.methods.setCollectionMintMode(true).send({from: owner}); - + const newPermissions = (await collectionSub.getData())!.raw.permissions; // (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman(); expect(newPermissions.mintMode).to.be.true; expect(newPermissions.access).to.be.equal('AllowList'); - + const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner)); const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth)); @@ -162,7 +162,7 @@ const result = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user}); const event = helper.eth.normalizeEvents(result.events) .find(event => event.event === 'Transfer'); - + expect(event).to.be.deep.equal({ address: collectionAddress, event: 'Transfer', @@ -172,11 +172,11 @@ tokenId: '1', }, }); - + const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner)); const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsorEth)); const userBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(user)); - + expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI'); expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter); expect(userBalanceAfter).to.be.eq(0n); @@ -243,40 +243,40 @@ [ 'setCollectionSponsorCross', 'setCollectionSponsor', // Soft-deprecated - ].map(testCase => + ].map(testCase => itEth(`[${testCase}] Check that transaction via EVM spend money from sponsor address`, async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor); - + const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', ''); const collectionSub = helper.nft.getCollectionObject(collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor'); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, testCase === 'setCollectionSponsor'); // Set collection sponsor: await collectionEvm.methods[testCase](testCase === 'setCollectionSponsor' ? sponsor : sponsorCross).send(); let collectionData = (await collectionSub.getData())!; expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true)); await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail'); - + await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor}); collectionData = (await collectionSub.getData())!; expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true)); - + const user = helper.eth.createAccount(); const userCross = helper.ethCrossAccount.fromAddress(user); await collectionEvm.methods.addCollectionAdminCross(userCross).send(); - + const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner)); const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor)); - + const mintingResult = await collectionEvm.methods.mintWithTokenURI(user, 'Test URI').send({from: user}); const tokenId = mintingResult.events.Transfer.returnValues.tokenId; - + const event = helper.eth.normalizeEvents(mintingResult.events) .find(event => event.event === 'Transfer'); const address = helper.ethAddress.fromCollectionId(collectionId); - + expect(event).to.be.deep.equal({ address, event: 'Transfer', @@ -287,7 +287,7 @@ }, }); expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI'); - + const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner)); expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore); const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor)); @@ -303,7 +303,7 @@ const {collectionAddress, collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner,'Sponsor collection', '1', '1', ''); const collectionSub = helper.nft.getCollectionObject(collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); // Set and confirm sponsor: await collectionEvm.methods.setCollectionSponsorCross(sponsorCrossEth).send({from: owner}); --- a/tests/src/eth/contractSponsoring.test.ts +++ b/tests/src/eth/contractSponsoring.test.ts @@ -34,7 +34,7 @@ itEth('Self sponsoring can be set by the address that deployed the contract', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const flipper = await helper.eth.deployFlipper(owner); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); // 1. owner can set selfSponsoring: expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false; @@ -71,7 +71,7 @@ itEth('Self sponsoring cannot be set by the address that did not deployed the contract', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const notOwner = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false; @@ -81,7 +81,7 @@ itEth('Sponsoring can be set by the address that has deployed the contract', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false; @@ -92,18 +92,18 @@ itEth('Sponsoring cannot be set by the address that did not deployed the contract', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const notOwner = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false; await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).call({from: notOwner})).to.be.rejectedWith('NoPermission'); expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false; }); - + itEth('Sponsor can be set by the address that deployed the contract', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); // 1. owner can set a sponsor: @@ -124,12 +124,12 @@ }, ]); }); - + itEth('Sponsor cannot be set by the address that did not deployed the contract', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); const notOwner = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false; @@ -140,7 +140,7 @@ itEth('Sponsorship can be confirmed by the address that pending as sponsor', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false; @@ -173,7 +173,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); const notSponsor = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false; @@ -185,7 +185,7 @@ itEth('Sponsorship can not be confirmed by the address that not set as sponsor', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const notSponsor = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false; @@ -196,7 +196,7 @@ itEth('Sponsor can be removed by the address that deployed the contract', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false; @@ -229,14 +229,14 @@ const owner = await helper.eth.createAccountWithBalance(donor); const notOwner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false; await helpers.methods.setSponsor(flipper.options.address, sponsor).send(); await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor}); expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true; - + await expect(helpers.methods.removeSponsor(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission'); await expect(helpers.methods.removeSponsor(flipper.options.address).send({from: notOwner})).to.be.rejected; expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true; @@ -246,7 +246,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); const caller = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); await helpers.methods.setSponsor(flipper.options.address, sponsor).send(); @@ -271,7 +271,7 @@ itEth('In generous mode, non-allowlisted user transaction will be self sponsored', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const caller = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); await helpers.methods.selfSponsoredEnable(flipper.options.address).send(); @@ -303,24 +303,24 @@ const sponsor = await helper.eth.createAccountWithBalance(donor); const caller = helper.eth.createAccount(); await helper.eth.transferBalanceFromSubstrate(donor, caller, testCase.balance); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); - + await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner}); await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner}); - + await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner}); await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner}); - + await helpers.methods.setSponsor(flipper.options.address, sponsor).send(); await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor}); - + const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor)); expect(sponsorBalanceBefore > 0n).to.be.true; - + await flipper.methods.flip().send({from: caller}); expect(await flipper.methods.getValue().call()).to.be.true; - + // Balance should be taken from flipper instead of caller const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor)); expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true; @@ -333,7 +333,7 @@ itEth('Non-allow-listed address can call a contract. Sponsor balance should not decrease', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const caller = helper.eth.createAccount(); - const contractHelpers = helper.ethNativeContract.contractHelpers(owner); + const contractHelpers = await helper.ethNativeContract.contractHelpers(owner); // Deploy flipper and send some tokens: const flipper = await helper.eth.deployFlipper(owner); @@ -348,7 +348,7 @@ await contractHelpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner}); await contractHelpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner}); - // 1. Caller has no UNQ and is not in allow list. So he cannot flip: + // 1. Caller has no UNQ and is not in allow list. So he cannot flip: await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/Returned error: insufficient funds for gas \* price \+ value/); expect(await flipper.methods.getValue().call()).to.be.false; @@ -361,9 +361,9 @@ const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); const caller = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); - + const originalCallerBalance = await helper.balance.getEthereum(caller); await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner}); await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner}); @@ -393,7 +393,7 @@ // TODO: Find a way to calculate default rate limit itEth('Default rate limit equal 7200', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.sponsoringRateLimit(flipper.options.address).call()).to.be.equal('7200'); @@ -412,7 +412,7 @@ ` // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; - + contract TestContract { event Result(bool); @@ -432,7 +432,7 @@ } return testContract; } - + async function deployTestContract(helper: EthUniqueHelper, owner: string) { const compiled = await compileTestContract(helper); return await helper.ethContract.deployByAbi(owner, compiled.abi, compiled.object); @@ -447,7 +447,7 @@ itEth('Default fee limit', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equal('115792089237316195423570985008687907853269984665640564039457584007913129639935'); @@ -455,7 +455,7 @@ itEth('Set fee limit', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); await helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send(); @@ -465,7 +465,7 @@ itEth('Negative test - set fee limit by non-owner', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const stranger = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const flipper = await helper.eth.deployFlipper(owner); await expect(helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send({from: stranger})).to.be.rejected; @@ -475,13 +475,13 @@ const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); const user = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const testContract = await deployTestContract(helper, owner); - + await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner}); await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner}); - + await helpers.methods.setSponsor(testContract.options.address, sponsor).send(); await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor}); @@ -500,13 +500,13 @@ itEth('Negative test - check that evm.call transactions exceeding fee limit are not executed', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); const testContract = await deployTestContract(helper, owner); - + await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner}); await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner}); - + await helpers.methods.setSponsor(testContract.options.address, sponsor).send(); await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor}); @@ -525,7 +525,7 @@ ); // expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.be.equal(originalAliceBalance); expect(await helper.balance.getSubstrate(alice.address)).to.be.equal(originalAliceBalance); - + await helper.eth.sendEVM( alice, testContract.options.address, --- a/tests/src/eth/createFTCollection.seqtest.ts +++ b/tests/src/eth/createFTCollection.seqtest.ts @@ -32,16 +32,16 @@ itEth('Create collection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - + const name = 'CollectionEVM'; const description = 'Some description'; const prefix = 'token prefix'; - + // todo:playgrounds this might fail when in async environment. const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created; const {collectionId} = await helper.eth.createFungibleCollection(owner, name, DECIMALS, description, prefix); - + const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created; const data = (await helper.ft.getData(collectionId))!; @@ -59,16 +59,16 @@ const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1; const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId); - const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner); expect(await collectionHelpers.methods .isCollectionExist(expectedCollectionAddress) .call()).to.be.false; - + await helper.eth.createFungibleCollection(owner, 'A', DECIMALS, 'A', 'A'); - + expect(await collectionHelpers.methods .isCollectionExist(expectedCollectionAddress) .call()).to.be.true; --- a/tests/src/eth/createFTCollection.test.ts +++ b/tests/src/eth/createFTCollection.test.ts @@ -18,7 +18,7 @@ import {evmToAddress} from '@polkadot/util-crypto'; import {Pallets, requirePalletsOrSkip} from '../util'; import {expect, itEth, usingEthPlaygrounds} from './util'; -import { CollectionLimits } from './util/playgrounds/types'; +import {CollectionLimits} from './util/playgrounds/types'; const DECIMALS = 18; @@ -31,17 +31,17 @@ donor = await privateKey({filename: __filename}); }); }); - + // Soft-deprecated itEth('[eth] Set sponsorship', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.eth.createAccountWithBalance(donor); const ss58Format = helper.chain.getChainProperties().ss58Format; const description = 'absolutely anything'; - + const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, description, 'ENVY'); - const collection = helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true); + const collection = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true); await collection.methods.setCollectionSponsor(sponsor).send(); let data = (await helper.rft.getData(collectionId))!; @@ -49,7 +49,7 @@ await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail'); - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true); + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true); await sponsorCollection.methods.confirmCollectionSponsorship().send(); data = (await helper.rft.getData(collectionId))!; @@ -62,8 +62,8 @@ const ss58Format = helper.chain.getChainProperties().ss58Format; const description = 'absolutely anything'; const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, description, 'ENVY'); - - const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + + const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner); const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor); await collection.methods.setCollectionSponsorCross(sponsorCross).send(); @@ -72,7 +72,7 @@ await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail'); - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor); + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor); await sponsorCollection.methods.confirmCollectionSponsorship().send(); data = (await helper.rft.getData(collectionId))!; @@ -83,27 +83,29 @@ itEth('Collection address exist', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233'; - expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection) + const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner); + + expect(await collectionHelpers .methods.isCollectionExist(collectionAddressForNonexistentCollection).call()) .to.be.false; - + const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT'); - expect(await helper.ethNativeContract.collectionHelpers(collectionAddress) + expect(await collectionHelpers .methods.isCollectionExist(collectionAddress).call()) .to.be.true; }); - + itEth('destroyCollection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress, collectionId} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT'); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const result = await collectionHelper.methods .destroyCollection(collectionAddress) .send({from: owner}); const events = helper.eth.normalizeEvents(result.events); - + expect(events).to.be.deep.equal([ { address: collectionHelper.options.address, @@ -135,7 +137,7 @@ itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); { const MAX_NAME_LENGTH = 64; const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1); @@ -165,10 +167,10 @@ .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH); } }); - + itEth('(!negative test!) cannot create collection if value !== 2', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const expects = [0n, 1n, 30n].map(async value => { await expect(collectionHelper.methods .createFTCollection('Peasantry', DECIMALS, 'absolutely anything', 'TWIW') @@ -182,15 +184,15 @@ const owner = await helper.eth.createAccountWithBalance(donor); const peasant = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Transgressed', DECIMALS, 'absolutely anything', 'YVNE'); - const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', peasant, true); + const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', peasant, true); const EXPECTED_ERROR = 'NoPermission'; { const sponsor = await helper.eth.createAccountWithBalance(donor); await expect(peasantCollection.methods .setCollectionSponsor(sponsor) .call()).to.be.rejectedWith(EXPECTED_ERROR); - - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor, true); + + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor, true); await expect(sponsorCollection.methods .confirmCollectionSponsorship() .call()).to.be.rejectedWith('ConfirmSponsorshipFail'); @@ -206,7 +208,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const peasant = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Transgressed', DECIMALS, 'absolutely anything', 'YVNE'); - const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', peasant); + const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', peasant); const EXPECTED_ERROR = 'NoPermission'; { const sponsor = await helper.eth.createAccountWithBalance(donor); @@ -214,8 +216,8 @@ await expect(peasantCollection.methods .setCollectionSponsorCross(sponsorCross) .call()).to.be.rejectedWith(EXPECTED_ERROR); - - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor); + + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor); await expect(sponsorCollection.methods .confirmCollectionSponsorship() .call()).to.be.rejectedWith('ConfirmSponsorshipFail'); @@ -225,5 +227,5 @@ .setCollectionLimit(CollectionLimits.AccountTokenOwnership, true, 1000) .call()).to.be.rejectedWith(EXPECTED_ERROR); } - }); + }); }); --- a/tests/src/eth/createNFTCollection.seqtest.ts +++ b/tests/src/eth/createNFTCollection.seqtest.ts @@ -37,7 +37,7 @@ // todo:playgrounds this might fail when in async environment. const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created; const {collectionId, collectionAddress, events} = await helper.eth.createNFTCollection(owner, name, description, prefix); - + expect(events).to.be.deep.equal([ { address: '0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F', @@ -48,7 +48,7 @@ }, }, ]); - + const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created; const collection = helper.nft.getCollectionObject(collectionId); @@ -72,7 +72,7 @@ const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1; const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId); - const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner); expect(await collectionHelpers.methods .isCollectionExist(expectedCollectionAddress) --- a/tests/src/eth/createNFTCollection.test.ts +++ b/tests/src/eth/createNFTCollection.test.ts @@ -17,7 +17,7 @@ import {evmToAddress} from '@polkadot/util-crypto'; import {IKeyringPair} from '@polkadot/types/types'; import {expect, itEth, usingEthPlaygrounds} from './util'; -import { CollectionLimits } from './util/playgrounds/types'; +import {CollectionLimits} from './util/playgrounds/types'; describe('Create NFT collection from EVM', () => { @@ -38,8 +38,8 @@ const baseUri = 'BaseURI'; const {collectionId, collectionAddress, events} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, name, description, prefix, baseUri); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); - + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft'); + expect(events).to.be.deep.equal([ { address: '0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F', @@ -53,14 +53,14 @@ const collection = helper.nft.getCollectionObject(collectionId); const data = (await collection.getData())!; - + expect(data.name).to.be.eq(name); expect(data.description).to.be.eq(description); expect(data.raw.tokenPrefix).to.be.eq(prefix); expect(data.raw.mode).to.be.eq('NFT'); - + expect(await contract.methods.description().call()).to.deep.equal(description); - + const options = await collection.getOptions(); expect(options.tokenPropertyPermissions).to.be.deep.equal([ { @@ -81,7 +81,7 @@ const ss58Format = helper.chain.getChainProperties().ss58Format; const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC'); - const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); await collection.methods.setCollectionSponsor(sponsor).send(); let data = (await helper.nft.getData(collectionId))!; @@ -89,7 +89,7 @@ await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail'); - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true); + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true); await sponsorCollection.methods.confirmCollectionSponsorship().send(); data = (await helper.nft.getData(collectionId))!; @@ -103,7 +103,7 @@ const description = 'absolutely anything'; const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', description, 'ROC'); - const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor); await collection.methods.setCollectionSponsorCross(sponsorCross).send(); @@ -112,24 +112,26 @@ await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail'); - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor); + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor); await sponsorCollection.methods.confirmCollectionSponsorship().send(); data = (await helper.nft.getData(collectionId))!; expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format))); - + expect(await sponsorCollection.methods.description().call()).to.deep.equal(description); }); itEth('Collection address exist', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233'; - expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection) + const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner); + + expect(await collectionHelpers .methods.isCollectionExist(collectionAddressForNonexistentCollection).call()) .to.be.false; const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Exister', 'absolutely anything', 'EVC'); - expect(await helper.ethNativeContract.collectionHelpers(collectionAddress) + expect(await collectionHelpers .methods.isCollectionExist(collectionAddress).call()) .to.be.true; }); @@ -148,7 +150,7 @@ itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); { const MAX_NAME_LENGTH = 64; const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1); @@ -182,7 +184,7 @@ itEth('(!negative test!) Create collection (no funds)', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); await expect(collectionHelper.methods .createNFTCollection('Peasantry', 'absolutely anything', 'CVE') .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); @@ -193,7 +195,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const malfeasant = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Transgressed', 'absolutely anything', 'COR'); - const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant, true); + const malfeasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant, true); const EXPECTED_ERROR = 'NoPermission'; { const sponsor = await helper.eth.createAccountWithBalance(donor); @@ -201,7 +203,7 @@ .setCollectionSponsor(sponsor) .call()).to.be.rejectedWith(EXPECTED_ERROR); - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true); + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true); await expect(sponsorCollection.methods .confirmCollectionSponsorship() .call()).to.be.rejectedWith('ConfirmSponsorshipFail'); @@ -217,7 +219,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const malfeasant = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Transgressed', 'absolutely anything', 'COR'); - const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant); + const malfeasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant); const EXPECTED_ERROR = 'NoPermission'; { const sponsor = await helper.eth.createAccountWithBalance(donor); @@ -226,7 +228,7 @@ .setCollectionSponsorCross(sponsorCross) .call()).to.be.rejectedWith(EXPECTED_ERROR); - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor); + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor); await expect(sponsorCollection.methods .confirmCollectionSponsorship() .call()).to.be.rejectedWith('ConfirmSponsorshipFail'); @@ -241,7 +243,7 @@ itEth('destroyCollection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF'); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const result = await collectionHelper.methods @@ -249,7 +251,7 @@ .send({from: owner}); const events = helper.eth.normalizeEvents(result.events); - + expect(events).to.be.deep.equal([ { address: collectionHelper.options.address, @@ -265,4 +267,4 @@ .call()).to.be.false; expect(await helper.collection.getData(collectionId)).to.be.null; }); -}); \ No newline at end of file +}); --- a/tests/src/eth/createRFTCollection.test.ts +++ b/tests/src/eth/createRFTCollection.test.ts @@ -33,11 +33,11 @@ itEth('Create collection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - + const name = 'CollectionEVM'; const description = 'Some description'; const prefix = 'token prefix'; - + const {collectionId} = await helper.eth.createRFTCollection(owner, name, description, prefix); const data = (await helper.rft.getData(collectionId))!; const collection = helper.rft.getCollectionObject(collectionId); @@ -52,8 +52,8 @@ expect(options.tokenPropertyPermissions).to.be.empty; }); - + itEth('Create collection with properties & get description', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); @@ -63,11 +63,11 @@ const baseUri = 'BaseURI'; const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, name, description, prefix, baseUri); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft'); const collection = helper.rft.getCollectionObject(collectionId); const data = (await collection.getData())!; - + expect(data.name).to.be.eq(name); expect(data.description).to.be.eq(description); expect(data.raw.tokenPrefix).to.be.eq(prefix); @@ -87,14 +87,14 @@ }, ]); }); - + // this test will occasionally fail when in async environment. itEth.skip('Check collection address exist', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1; const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId); - const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner); expect(await collectionHelpers.methods .isCollectionExist(expectedCollectionAddress) @@ -103,12 +103,12 @@ await collectionHelpers.methods .createRFTCollection('A', 'A', 'A') .send({value: Number(2n * helper.balance.getOneTokenNominal())}); - + expect(await collectionHelpers.methods .isCollectionExist(expectedCollectionAddress) .call()).to.be.true; }); - + // Soft-deprecated itEth('[eth] Set sponsorship', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); @@ -116,7 +116,7 @@ const ss58Format = helper.chain.getChainProperties().ss58Format; const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY'); - const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true); + const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true); await collection.methods.setCollectionSponsor(sponsor).send(); let data = (await helper.rft.getData(collectionId))!; @@ -124,7 +124,7 @@ await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail'); - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true); + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true); await sponsorCollection.methods.confirmCollectionSponsorship().send(); data = (await helper.rft.getData(collectionId))!; @@ -137,7 +137,7 @@ const ss58Format = helper.chain.getChainProperties().ss58Format; const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY'); - const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner); const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor); await collection.methods.setCollectionSponsorCross(sponsorCross).send(); @@ -146,7 +146,7 @@ await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail'); - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor); + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor); await sponsorCollection.methods.confirmCollectionSponsorship().send(); data = (await helper.rft.getData(collectionId))!; @@ -156,12 +156,14 @@ itEth('Collection address exist', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233'; - expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection) + const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner); + + expect(await collectionHelpers .methods.isCollectionExist(collectionAddressForNonexistentCollection).call()) .to.be.false; - + const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Exister', 'absolutely anything', 'WIWT'); - expect(await helper.ethNativeContract.collectionHelpers(collectionAddress) + expect(await collectionHelpers .methods.isCollectionExist(collectionAddress).call()) .to.be.true; }); @@ -181,7 +183,7 @@ itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); { const MAX_NAME_LENGTH = 64; const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1); @@ -211,10 +213,10 @@ .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH); } }); - + itEth('(!negative test!) Create collection (no funds)', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); await expect(collectionHelper.methods .createRFTCollection('Peasantry', 'absolutely anything', 'TWIW') .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); @@ -225,15 +227,15 @@ const owner = await helper.eth.createAccountWithBalance(donor); const peasant = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE'); - const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant, true); + const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', peasant, true); const EXPECTED_ERROR = 'NoPermission'; { const sponsor = await helper.eth.createAccountWithBalance(donor); await expect(peasantCollection.methods .setCollectionSponsor(sponsor) .call()).to.be.rejectedWith(EXPECTED_ERROR); - - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true); + + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true); await expect(sponsorCollection.methods .confirmCollectionSponsorship() .call()).to.be.rejectedWith('ConfirmSponsorshipFail'); @@ -249,7 +251,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const peasant = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE'); - const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant); + const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', peasant); const EXPECTED_ERROR = 'NoPermission'; { const sponsor = await helper.eth.createAccountWithBalance(donor); @@ -257,8 +259,8 @@ await expect(peasantCollection.methods .setCollectionSponsorCross(sponsorCross) .call()).to.be.rejectedWith(EXPECTED_ERROR); - - const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor); + + const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor); await expect(sponsorCollection.methods .confirmCollectionSponsorship() .call()).to.be.rejectedWith('ConfirmSponsorshipFail'); @@ -269,16 +271,16 @@ .call()).to.be.rejectedWith(EXPECTED_ERROR); } }); - + itEth('destroyCollection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress, collectionId} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF'); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); - + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); + await expect(collectionHelper.methods .destroyCollection(collectionAddress) .send({from: owner})).to.be.fulfilled; - + expect(await collectionHelper.methods .isCollectionExist(collectionAddress) .call()).to.be.false; --- a/tests/src/eth/crossTransfer.test.ts +++ b/tests/src/eth/crossTransfer.test.ts @@ -30,8 +30,8 @@ [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); }); }); - - itEth('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async ({helper}) => { + + itEth('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async ({helper}) => { const bobCA = CrossAccountId.fromKeyring(bob); const charlieCA = CrossAccountId.fromKeyring(charlie); @@ -52,7 +52,7 @@ await collection.setLimits(alice, {ownerCanTransfer: true}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'ft', aliceProxy); + const contract = await helper.ethNativeContract.collection(address, 'ft', aliceProxy); await collection.mint(alice, 200n, {Ethereum: aliceProxy}); await contract.methods.transfer(bobProxy, 50).send({from: aliceProxy}); @@ -73,10 +73,10 @@ [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); }); }); - + itEth('The private key X create a substrate address. Alice sends a token to the corresponding EVM address, and X can send it to Bob in the substrate', async ({helper}) => { const charlieEth = CrossAccountId.fromKeyring(charlie, 'Ethereum'); - + const collection = await helper.nft.mintCollection(alice); await collection.setLimits(alice, {ownerCanTransfer: true}); const token = await collection.mintToken(alice); @@ -93,7 +93,7 @@ await collection.setLimits(alice, {ownerCanTransfer: true}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft', aliceProxy); + const contract = await helper.ethNativeContract.collection(address, 'nft', aliceProxy); const token = await collection.mintToken(alice); await token.transfer(alice, {Ethereum: aliceProxy}); --- a/tests/src/eth/destroyCollection.test.ts +++ b/tests/src/eth/destroyCollection.test.ts @@ -32,29 +32,29 @@ }); }); - testCases.map((testCase) => + testCases.map((testCase) => itEth.ifWithPallets(`Cannot burn non-owned or non-existing collection ${testCase.case}`, testCase.requiredPallets, async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const signer = await helper.eth.createAccountWithBalance(donor); - + const unexistedCollection = helper.ethAddress.fromCollectionId(1000000); - - const collectionHelpers = helper.ethNativeContract.collectionHelpers(signer); + + const collectionHelpers = await helper.ethNativeContract.collectionHelpers(signer); const {collectionAddress} = await helper.eth.createCollection(testCase.case, owner, ...testCase.params as [string, string, string, number?]); // cannot burn collec await expect(collectionHelpers.methods .destroyCollection(collectionAddress) .send({from: signer})).to.be.rejected; - + await expect(collectionHelpers.methods .destroyCollection(unexistedCollection) .send({from: signer})).to.be.rejected; - + expect(await collectionHelpers.methods .isCollectionExist(unexistedCollection) .call()).to.be.false; - + expect(await collectionHelpers.methods .isCollectionExist(collectionAddress) .call()).to.be.true; --- a/tests/src/eth/ethFeesAreCorrect.test.ts +++ b/tests/src/eth/ethFeesAreCorrect.test.ts @@ -32,7 +32,7 @@ itEth('web3 fees are the same as evm.call fees', async ({helper}) => { const collection = await helper.nft.mintCollection(minter, {}); - + const owner = await helper.eth.createAccountWithBalance(donor); const receiver = await helper.eth.createAccountWithBalance(donor); const aliceEth = helper.address.substrateToEth(alice.address); @@ -41,7 +41,7 @@ const {tokenId: tokenB} = await collection.mintToken(minter, {Ethereum: aliceEth}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const balanceBeforeWeb3Transfer = await helper.balance.getEthereum(owner); await contract.methods.transfer(receiver, tokenA).send({from: owner}); @@ -50,7 +50,7 @@ const encodedCall = contract.methods.transfer(receiver, tokenB) .encodeABI(); - + const balanceBeforeEvmCall = await helper.balance.getSubstrate(alice.address); await helper.eth.sendEVM( alice, --- a/tests/src/eth/events.test.ts +++ b/tests/src/eth/events.test.ts @@ -22,7 +22,7 @@ import {CollectionLimits, EthTokenPermissions, NormalizedEvent} from './util/playgrounds/types'; let donor: IKeyringPair; - + before(async function () { await usingEthPlaygrounds(async (_helper, privateKey) => { donor = await privateKey({filename: __filename}); @@ -53,7 +53,7 @@ clearEvents(ethEvents, subEvents); } { - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const result = await collectionHelper.methods.destroyCollection(collectionAddress).send({from:owner}); await helper.wait.newBlocks(1); expect(result.events).to.containSubset({ @@ -71,9 +71,9 @@ async function testCollectionPropertySetAndDeleted(helper: EthUniqueHelper, mode: TCollectionMode) { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, mode, owner); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); - + const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); + const ethEvents: any = []; collectionHelper.events.allEvents((_: any, event: any) => { ethEvents.push(event); @@ -112,8 +112,8 @@ async function testPropertyPermissionSet(helper: EthUniqueHelper, mode: TCollectionMode) { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, mode, owner); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const ethEvents: any = []; collectionHelper.events.allEvents((_: any, event: any) => { ethEvents.push(event); @@ -121,8 +121,8 @@ const {unsubscribe, collectedEvents: subEvents} = await helper.subscribeEvents([{section: 'common', names: ['PropertyPermissionSet']}]); await collection.methods.setTokenPropertyPermissions([ ['A', [ - [EthTokenPermissions.Mutable, true], - [EthTokenPermissions.TokenOwner, true], + [EthTokenPermissions.Mutable, true], + [EthTokenPermissions.TokenOwner, true], [EthTokenPermissions.CollectionAdmin, true]], ], ]).send({from: owner}); @@ -143,8 +143,8 @@ const owner = await helper.eth.createAccountWithBalance(donor); const user = helper.ethCrossAccount.createAccount(); const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, mode, owner); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const ethEvents: any[] = []; collectionHelper.events.allEvents((_: any, event: any) => { ethEvents.push(event); @@ -185,8 +185,8 @@ const owner = await helper.eth.createAccountWithBalance(donor); const user = helper.ethCrossAccount.createAccount(); const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, mode, owner); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const ethEvents: any = []; collectionHelper.events.allEvents((_: any, event: any) => { ethEvents.push(event); @@ -225,8 +225,8 @@ async function testCollectionLimitSet(helper: EthUniqueHelper, mode: TCollectionMode) { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, mode, owner); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const ethEvents: any = []; collectionHelper.events.allEvents((_: any, event: any) => { ethEvents.push(event); @@ -252,8 +252,8 @@ const owner = await helper.eth.createAccountWithBalance(donor); const newOwner = helper.ethCrossAccount.createAccount(); const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, mode, owner); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const ethEvents: any = []; collectionHelper.events.allEvents((_: any, event: any) => { ethEvents.push(event); @@ -278,8 +278,8 @@ async function testCollectionPermissionSet(helper: EthUniqueHelper, mode: TCollectionMode) { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, mode, owner); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const ethEvents: any = []; collectionHelper.events.allEvents((_: any, event: any) => { ethEvents.push(event); @@ -319,8 +319,8 @@ const owner = await helper.eth.createAccountWithBalance(donor); const sponsor = await helper.ethCrossAccount.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, mode, owner); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const ethEvents: any = []; collectionHelper.events.allEvents((_: any, event: any) => { ethEvents.push(event); @@ -373,14 +373,14 @@ async function testTokenPropertySetAndDeleted(helper: EthUniqueHelper, mode: TCollectionMode) { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createCollection(mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, mode, owner); - const collectionHelper = helper.ethNativeContract.collectionHelpers(owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, mode, owner); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner); const result = await collection.methods.mint(owner).send({from: owner}); const tokenId = result.events.Transfer.returnValues.tokenId; await collection.methods.setTokenPropertyPermissions([ ['A', [ - [EthTokenPermissions.Mutable, true], - [EthTokenPermissions.TokenOwner, true], + [EthTokenPermissions.Mutable, true], + [EthTokenPermissions.TokenOwner, true], [EthTokenPermissions.CollectionAdmin, true]], ], ]).send({from: owner}); @@ -431,23 +431,23 @@ itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => { await testCollectionPropertySetAndDeleted(helper, mode); }); - + itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => { await testAllowListAddressAddedAndRemoved(helper, mode); }); - + itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => { await testCollectionAdminAddedAndRemoved(helper, mode); }); - + itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => { await testCollectionLimitSet(helper, mode); }); - + itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => { await testCollectionOwnerChanged(helper, mode); }); - + itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => { await testCollectionPermissionSet(helper, mode); }); @@ -467,27 +467,27 @@ itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => { await testCollectionPropertySetAndDeleted(helper, mode); }); - + itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => { await testPropertyPermissionSet(helper, mode); }); - + itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => { await testAllowListAddressAddedAndRemoved(helper, mode); }); - + itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => { await testCollectionAdminAddedAndRemoved(helper, mode); }); - + itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => { await testCollectionLimitSet(helper, mode); }); - + itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => { await testCollectionOwnerChanged(helper, mode); }); - + itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => { await testCollectionPermissionSet(helper, mode); }); @@ -495,7 +495,7 @@ itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => { await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode); }); - + itEth('CollectionChanged event for TokenPropertySet, TokenPropertyDeleted', async ({helper}) => { await testTokenPropertySetAndDeleted(helper, mode); }); @@ -518,27 +518,27 @@ itEth('CollectionChanged event for CollectionPropertySet and CollectionPropertyDeleted', async ({helper}) => { await testCollectionPropertySetAndDeleted(helper, mode); }); - + itEth('CollectionChanged event for PropertyPermissionSet', async ({helper}) => { await testPropertyPermissionSet(helper, mode); }); - + itEth('CollectionChanged event for AllowListAddressAdded, AllowListAddressRemoved', async ({helper}) => { await testAllowListAddressAddedAndRemoved(helper, mode); }); - + itEth('CollectionChanged event for CollectionAdminAdded, CollectionAdminRemoved', async ({helper}) => { await testCollectionAdminAddedAndRemoved(helper, mode); }); - + itEth('CollectionChanged event for CollectionLimitSet', async ({helper}) => { await testCollectionLimitSet(helper, mode); }); - + itEth('CollectionChanged event for CollectionOwnerChanged', async ({helper}) => { await testCollectionOwnerChanged(helper, mode); }); - + itEth('CollectionChanged event for CollectionPermissionSet', async ({helper}) => { await testCollectionPermissionSet(helper, mode); }); @@ -546,7 +546,7 @@ itEth('CollectionChanged event for CollectionSponsorSet, SponsorshipConfirmed, CollectionSponsorRemoved', async ({helper}) => { await testCollectionSponsorSetAndConfirmedAndThenRemoved(helper, mode); }); - + itEth('CollectionChanged event for TokenPropertySet, TokenPropertyDeleted', async ({helper}) => { await testTokenPropertySetAndDeleted(helper, mode); }); --- a/tests/src/eth/fractionalizer/fractionalizer.test.ts +++ b/tests/src/eth/fractionalizer/fractionalizer.test.ts @@ -63,7 +63,7 @@ nftCollectionAddress: string, nftTokenId: number, rftTokenAddress: string }> => { const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT'); - const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); + const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); const mintResult = await nftContract.methods.mint(owner).send({from: owner}); const nftTokenId = mintResult.events.Transfer.returnValues.tokenId; @@ -93,7 +93,7 @@ const owner = await helper.eth.createAccountWithBalance(donor, 10n); const fractionalizer = await deployContract(helper, owner); const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT'); - const rftContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); + const rftContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); const fractionalizerAddressCross = helper.ethCrossAccount.fromAddress(fractionalizer.options.address); await rftContract.methods.addCollectionAdminCross(fractionalizerAddressCross).send({from: owner}); @@ -148,7 +148,7 @@ const owner = await helper.eth.createAccountWithBalance(donor, 20n); const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT'); - const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); + const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); const mintResult = await nftContract.methods.mint(owner).send({from: owner}); const nftTokenId = mintResult.events.Transfer.returnValues.tokenId; @@ -168,7 +168,7 @@ }); const rftTokenAddress = result.events.Fractionalized.returnValues._rftToken; - const rftTokenContract = helper.ethNativeContract.rftToken(rftTokenAddress); + const rftTokenContract = await helper.ethNativeContract.rftToken(rftTokenAddress); expect(await rftTokenContract.methods.balanceOf(owner).call()).to.equal('100'); }); @@ -181,7 +181,7 @@ const {collectionId, tokenId} = helper.ethAddress.extractTokenId(rftTokenAddress); const refungibleAddress = helper.ethAddress.fromCollectionId(collectionId); expect(rftCollectionAddress).to.be.equal(refungibleAddress); - const refungibleTokenContract = helper.ethNativeContract.rftToken(rftTokenAddress, owner); + const refungibleTokenContract = await helper.ethNativeContract.rftToken(rftTokenAddress, owner); await refungibleTokenContract.methods.approve(fractionalizer.options.address, 100).send({from: owner}); const result = await fractionalizer.methods.rft2nft(refungibleAddress, tokenId).send({from: owner}); expect(result.events).to.be.like({ @@ -204,7 +204,7 @@ const {collectionId, tokenId} = helper.ethAddress.extractTokenId(rftTokenAddress); const refungibleAddress = helper.ethAddress.fromCollectionId(collectionId); expect(rftCollectionAddress).to.be.equal(refungibleAddress); - const refungibleTokenContract = helper.ethNativeContract.rftToken(rftTokenAddress, owner); + const refungibleTokenContract = await helper.ethNativeContract.rftToken(rftTokenAddress, owner); await refungibleTokenContract.methods.approve(fractionalizer.options.address, 100).send({from: owner}); const rft2nft = await fractionalizer.methods.rft2nftMapping(rftTokenAddress).call(); @@ -233,7 +233,7 @@ itEth('call setRFTCollection twice', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor, 20n); const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT'); - const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); + const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); const fractionalizer = await deployContract(helper, owner); const fractionalizerAddressCross = helper.ethCrossAccount.fromAddress(fractionalizer.options.address); @@ -247,7 +247,7 @@ itEth('call setRFTCollection with NFT collection', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor, 20n); const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT'); - const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); + const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); const fractionalizer = await deployContract(helper, owner); const fractionalizerAddressCross = helper.ethCrossAccount.fromAddress(fractionalizer.options.address); @@ -282,7 +282,7 @@ const owner = await helper.eth.createAccountWithBalance(donor, 20n); const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT'); - const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); + const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); const mintResult = await nftContract.methods.mint(owner).send({from: owner}); const nftTokenId = mintResult.events.Transfer.returnValues.tokenId; @@ -297,7 +297,7 @@ const nftOwner = await helper.eth.createAccountWithBalance(donor, 10n); const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT'); - const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); + const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); const mintResult = await nftContract.methods.mint(owner).send({from: owner}); const nftTokenId = mintResult.events.Transfer.returnValues.tokenId; await nftContract.methods.transfer(nftOwner, 1).send({from: owner}); @@ -314,7 +314,7 @@ const owner = await helper.eth.createAccountWithBalance(donor, 20n); const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT'); - const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); + const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); const mintResult = await nftContract.methods.mint(owner).send({from: owner}); const nftTokenId = mintResult.events.Transfer.returnValues.tokenId; @@ -329,7 +329,7 @@ const owner = await helper.eth.createAccountWithBalance(donor, 20n); const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT'); - const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); + const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); const mintResult = await nftContract.methods.mint(owner).send({from: owner}); const nftTokenId = mintResult.events.Transfer.returnValues.tokenId; @@ -345,7 +345,7 @@ const fractionalizer = await deployContract(helper, owner); const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT'); - const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); + const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); const mintResult = await refungibleContract.methods.mint(owner).send({from: owner}); const rftTokenId = mintResult.events.Transfer.returnValues.tokenId; @@ -358,7 +358,7 @@ const {contract: fractionalizer} = await initContract(helper, owner); const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT'); - const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); + const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); const mintResult = await refungibleContract.methods.mint(owner).send({from: owner}); const rftTokenId = mintResult.events.Transfer.returnValues.tokenId; @@ -369,7 +369,7 @@ itEth('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor, 20n); const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT'); - const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); + const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner); const fractionalizer = await deployContract(helper, owner); @@ -392,7 +392,7 @@ const {rftTokenAddress} = await mintRFTToken(helper, owner, fractionalizer, 100n); const {tokenId} = helper.ethAddress.extractTokenId(rftTokenAddress); - const refungibleTokenContract = helper.ethNativeContract.rftToken(rftTokenAddress, owner); + const refungibleTokenContract = await helper.ethNativeContract.rftToken(rftTokenAddress, owner); await refungibleTokenContract.methods.transfer(receiver, 50).send({from: owner}); await refungibleTokenContract.methods.approve(fractionalizer.options.address, 50).send({from: receiver}); await expect(fractionalizer.methods.rft2nft(rftCollectionAddress, tokenId).call({from: receiver})) @@ -419,7 +419,7 @@ const {contract: fractionalizer} = await initContract(helper, owner); await fractionalizer.methods.setNftCollectionIsAllowed(nftCollectionAddress, true).send({from: owner}); - const nftContract = helper.ethNativeContract.collection(nftCollectionAddress, 'nft', owner); + const nftContract = await helper.ethNativeContract.collection(nftCollectionAddress, 'nft', owner); await nftContract.methods.approve(fractionalizer.options.address, nftToken.tokenId).send({from: owner}); await expect(fractionalizer.methods.nft2rft(nftCollectionAddress, nftToken.tokenId, 100).call()) .to.be.rejectedWith(/TransferNotAllowed$/g); @@ -437,7 +437,7 @@ await helper.executeExtrinsic(donor, 'api.tx.unique.setTransfersEnabledFlag', [rftCollection.collectionId, false], true); const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT'); - const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); + const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner); const mintResult = await nftContract.methods.mint(owner).send({from: owner}); const nftTokenId = mintResult.events.Transfer.returnValues.tokenId; --- a/tests/src/eth/fungible.test.ts +++ b/tests/src/eth/fungible.test.ts @@ -33,7 +33,7 @@ const collection = await helper.ft.mintCollection(alice); await collection.mint(alice, 200n); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller); const totalSupply = await contract.methods.totalSupply().call(); expect(totalSupply).to.equal('200'); }); @@ -43,7 +43,7 @@ const collection = await helper.ft.mintCollection(alice); await collection.mint(alice, 200n, {Ethereum: caller}); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'ft', caller); const balance = await contract.methods.balanceOf(caller).call(); expect(balance).to.equal('200'); }); @@ -68,17 +68,17 @@ await collection.addAdmin(alice, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); const result = await contract.methods.mint(receiver, 100).send(); - + const event = result.events.Transfer; expect(event.address).to.equal(collectionAddress); expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000'); expect(event.returnValues.to).to.equal(receiver); expect(event.returnValues.value).to.equal('100'); }); - + [ 'substrate' as const, 'ethereum' as const, @@ -93,13 +93,13 @@ const ethOwner = await helper.eth.createAccountWithBalance(donor); const collection = await helper.ft.mintCollection(alice); await collection.addAdmin(alice, {Ethereum: ethOwner}); - + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', ethOwner); - + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', ethOwner); + // 2. Mint tokens: const result = await collectionEvm.methods.mintCross(testCase === 'ethereum' ? receiverCrossEth : receiverCrossSub, 100).send(); - + const event = result.events.Transfer; expect(event.address).to.equal(collectionAddress); expect(event.returnValues.from).to.equal('0x0000000000000000000000000000000000000000'); @@ -123,7 +123,7 @@ await collection.addAdmin(alice, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); const result = await contract.methods.mintBulk(Array.from({length: bulkSize}, (_, i) => ( [receivers[i], (i + 1) * 10] @@ -146,11 +146,11 @@ await collection.addAdmin(alice, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true); await contract.methods.mint(receiver, 100).send(); const result = await contract.methods.burnFrom(receiver, 49).send({from: receiver}); - + const event = result.events.Transfer; expect(event.address).to.equal(collectionAddress); expect(event.returnValues.from).to.equal(receiver); @@ -168,7 +168,7 @@ await collection.mint(alice, 200n, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); { const result = await contract.methods.approve(spender, 100).send({from: owner}); @@ -192,13 +192,13 @@ const spenderSub = (await helper.arrange.createAccounts([1n], donor))[0]; const spenderCrossEth = helper.ethCrossAccount.fromAddress(spender); const spenderCrossSub = helper.ethCrossAccount.fromKeyringPair(spenderSub); - + const collection = await helper.ft.mintCollection(alice); await collection.mint(alice, 200n, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); { const result = await contract.methods.approveCross(spenderCrossEth, 100).send({from: owner}); @@ -213,8 +213,8 @@ const allowance = await contract.methods.allowance(owner, spender).call(); expect(+allowance).to.equal(100); } - - + + { const result = await contract.methods.approveCross(spenderCrossSub, 100).send({from: owner}); const event = result.events.Approval; @@ -228,7 +228,7 @@ const allowance = await collection.getApprovedTokens({Ethereum: owner}, {Substrate: spenderSub.address}); expect(allowance).to.equal(100n); } - + { //TO-DO expect with future allowanceCross(owner, spenderCrossEth).call() } @@ -242,7 +242,7 @@ await collection.mint(alice, 100n, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); await expect(collectionEvm.methods.approveCross(nonOwnerCross, 20).call({from: nonOwner})).to.be.rejectedWith('CantApproveMoreThanOwned'); }); @@ -257,10 +257,10 @@ await collection.approveTokens(owner, {Ethereum: sender}, 100n); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'ft'); + const contract = await helper.ethNativeContract.collection(address, 'ft'); const fromBalanceBefore = await collection.getBalance({Substrate: owner.address}); - + const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner); const result = await contract.methods.burnFromCross(ownerCross, 49).send({from: sender}); const events = result.events; @@ -298,13 +298,13 @@ await collection.mint(alice, 200n, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); await contract.methods.approve(spender, 100).send(); { const result = await contract.methods.transferFrom(owner, receiver, 49).send({from: spender}); - + let event = result.events.Transfer; expect(event.address).to.be.equal(collectionAddress); expect(event.returnValues.from).to.be.equal(owner); @@ -338,7 +338,7 @@ await collection.mint(alice, 200n, {Ethereum: sender}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', sender); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', sender); { // Can transferCross to ethereum address: @@ -356,7 +356,7 @@ const receiverBalance = await collectionEvm.methods.balanceOf(receiverEth).call(); expect(+receiverBalance).to.equal(50); } - + { // Can transferCross to substrate address: const result = await collectionEvm.methods.transferCross(receiverCrossSub, 50).send({from: sender}); @@ -385,7 +385,7 @@ const collection = await helper.ft.mintCollection(alice); await collection.mint(alice, BALANCE, {Ethereum: sender}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', sender); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', sender); // 1. Cannot transfer more than have const receiver = testCase === 'transfer' ? receiverEth : receiverCrossEth; @@ -393,8 +393,8 @@ // 2. Zero transfer allowed (EIP-20): await collectionEvm.methods[testCase](receiver, 0n).send({from: sender}); })); - - + + itEth('Can perform transfer()', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const receiver = await helper.eth.createAccountWithBalance(donor); @@ -402,11 +402,11 @@ await collection.mint(alice, 200n, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); { const result = await contract.methods.transfer(receiver, 50).send({from: owner}); - + const event = result.events.Transfer; expect(event.address).to.be.equal(collectionAddress); expect(event.returnValues.from).to.be.equal(owner); @@ -436,14 +436,14 @@ await collection.approveTokens(owner, {Ethereum: sender}, 100n); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'ft'); + const contract = await helper.ethNativeContract.collection(address, 'ft'); const from = helper.ethCrossAccount.fromKeyringPair(owner); const to = helper.ethCrossAccount.fromAddress(receiver); const fromBalanceBefore = await collection.getBalance({Substrate: owner.address}); const toBalanceBefore = await collection.getBalance({Ethereum: receiver}); - + const result = await contract.methods.transferFromCross(from, to, 51).send({from: sender}); expect(result.events).to.be.like({ @@ -483,7 +483,7 @@ [alice] = await helper.arrange.createAccounts([20n], donor); }); }); - + itEth('approve() call fee is less than 0.2UNQ', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const spender = helper.eth.createAccount(); @@ -491,7 +491,7 @@ await collection.mint(alice, 200n, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, 100).send({from: owner})); expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); @@ -504,7 +504,7 @@ await collection.mint(alice, 200n, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); await contract.methods.approve(spender, 100).send({from: owner}); @@ -519,7 +519,7 @@ await collection.mint(alice, 200n, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner); const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, 100).send({from: owner})); expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); @@ -544,13 +544,13 @@ await collection.mint(alice, 200n); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft'); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft'); const events: any = []; contract.events.allEvents((_: any, event: any) => { events.push(event); }); - + await collection.approveTokens(alice, {Ethereum: receiver}, 100n); if (events.length == 0) await helper.wait.newBlocks(1); const event = events[0]; @@ -570,7 +570,7 @@ await collection.approveTokens(alice, {Substrate: bob.address}, 100n); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft'); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft'); const events: any = []; contract.events.allEvents((_: any, event: any) => { @@ -601,13 +601,13 @@ await collection.mint(alice, 200n); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'ft'); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'ft'); const events: any = []; contract.events.allEvents((_: any, event: any) => { events.push(event); }); - + await collection.transfer(alice, {Ethereum:receiver}, 51n); if (events.length == 0) await helper.wait.newBlocks(1); const event = events[0]; @@ -630,11 +630,11 @@ await collection.approveTokens(owner, {Ethereum: sender}, 100n); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'ft'); + const contract = await helper.ethNativeContract.collection(address, 'ft'); const from = helper.ethCrossAccount.fromKeyringPair(owner); const to = helper.ethCrossAccount.fromAddress(receiver); - + const result = await contract.methods.transferFromCross(from, to, 51).send({from: sender}); expect(result.events).to.be.like({ --- a/tests/src/eth/helpersSmoke.test.ts +++ b/tests/src/eth/helpersSmoke.test.ts @@ -25,13 +25,13 @@ donor = await privateKey({filename: __filename}); }); }); - + itEth('Contract owner is recorded', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const flipper = await helper.eth.deployFlipper(owner); - expect(await helper.ethNativeContract.contractHelpers(owner).methods.contractOwner(flipper.options.address).call()).to.be.equal(owner); + expect(await (await helper.ethNativeContract.contractHelpers(owner)).methods.contractOwner(flipper.options.address).call()).to.be.equal(owner); }); itEth('Flipper is working', async ({helper}) => { --- a/tests/src/eth/marketplace/marketplace.test.ts +++ b/tests/src/eth/marketplace/marketplace.test.ts @@ -30,7 +30,7 @@ before(async () => { await usingEthPlaygrounds(async (_helper, privateKey) => { donor = await privateKey({filename: __filename}); - }); + }); }); beforeEach(async () => { @@ -50,17 +50,17 @@ const matcher = await helper.ethContract.deployByCode(matcherOwner, 'MarketPlace', (await readFile(`${__dirname}/MarketPlace.sol`)).toString(), [{solPath: 'api/UniqueNFT.sol', fsPath: `${__dirname}/../api/UniqueNFT.sol`}], helper.eth.DEFAULT_GAS * 2); const sponsor = await helper.eth.createAccountWithBalance(donor); - const helpers = helper.ethNativeContract.contractHelpers(matcherOwner); + const helpers = await helper.ethNativeContract.contractHelpers(matcherOwner); await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner}); await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner}); - + await helpers.methods.setSponsor(matcher.options.address, sponsor).send({from: matcherOwner}); await helpers.methods.confirmSponsorship(matcher.options.address).send({from: sponsor}); const collection = await helper.nft.mintCollection(alice, {limits: {sponsorApproveTimeout: 1}, pendingSponsor: alice.address}); await collection.confirmSponsorship(alice); await collection.addToAllowList(alice, {Substrate: aliceDoubleMirror}); - const evmCollection = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); + const evmCollection = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); await helper.eth.transferBalanceFromSubstrate(donor, aliceMirror); await helpers.methods.toggleAllowed(matcher.options.address, aliceMirror, true).send({from: matcherOwner}); @@ -104,17 +104,17 @@ const sponsor = await helper.eth.createAccountWithBalance(donor); const escrow = await helper.eth.createAccountWithBalance(donor); await matcher.methods.setEscrow(escrow, true).send({from: matcherOwner}); - const helpers = helper.ethNativeContract.contractHelpers(matcherOwner); + const helpers = await helper.ethNativeContract.contractHelpers(matcherOwner); await helpers.methods.setSponsoringMode(matcher.options.address, SponsoringMode.Allowlisted).send({from: matcherOwner}); await helpers.methods.setSponsoringRateLimit(matcher.options.address, 1).send({from: matcherOwner}); - + await helpers.methods.setSponsor(matcher.options.address, sponsor).send({from: matcherOwner}); await helpers.methods.confirmSponsorship(matcher.options.address).send({from: sponsor}); const collection = await helper.nft.mintCollection(alice, {limits: {sponsorApproveTimeout: 1}, pendingSponsor: alice.address}); await collection.confirmSponsorship(alice); await collection.addToAllowList(alice, {Substrate: aliceDoubleMirror}); - const evmCollection = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); + const evmCollection = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); await helper.eth.transferBalanceFromSubstrate(donor, aliceMirror); @@ -168,10 +168,10 @@ await helper.eth.transferBalanceFromSubstrate(donor, matcher.options.address); const collection = await helper.nft.mintCollection(alice, {limits: {sponsorApproveTimeout: 1}}); - const evmCollection = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); + const evmCollection = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); await helper.balance.transferToSubstrate(donor, seller.address, 100_000_000_000_000_000_000n); - + const token = await collection.mintToken(alice, {Ethereum: sellerMirror}); // Token is owned by seller initially --- a/tests/src/eth/migration.seqtest.ts +++ b/tests/src/eth/migration.seqtest.ts @@ -165,7 +165,7 @@ const collection = await helper.nft.mintCollection(superuser); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); const caller = await helper.eth.createAccountWithBalance(superuser); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', caller); const events: any = []; contract.events.allEvents((_: any, event: any) => { --- a/tests/src/eth/nesting/nest.test.ts +++ b/tests/src/eth/nesting/nest.test.ts @@ -9,7 +9,7 @@ ): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => { const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); await contract.methods.setCollectionNesting(true).send({from: owner}); return {collectionId, collectionAddress, contract}; @@ -51,13 +51,13 @@ await contract.methods.transferFrom(targetNftTokenAddress, owner, secondTokenId).send({from: owner}); expect(await contract.methods.ownerOf(secondTokenId).call()).to.be.equal(owner); }); - + itEth('NFT: collectionNestingRestrictedCollectionIds() & collectionNestingPermissions', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const {collectionId: unnestedCollsectionId, collectionAddress: unnsetedCollectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C'); - const unnestedContract = helper.ethNativeContract.collection(unnsetedCollectionAddress, 'nft', owner); + const unnestedContract = await helper.ethNativeContract.collection(unnsetedCollectionAddress, 'nft', owner); expect(await unnestedContract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([false, []]); - + const {contract} = await createNestingCollection(helper, owner); expect(await contract.methods.collectionNestingRestrictedCollectionIds().call({from: owner})).to.be.like([true, []]); await contract.methods.setCollectionNesting(true, [unnsetedCollectionAddress]).send({from: owner}); @@ -66,7 +66,7 @@ await contract.methods.setCollectionNesting(false).send({from: owner}); expect(await contract.methods.collectionNestingPermissions().call({from: owner})).to.be.like([['1', false], ['0', false]]); }); - + itEth('NFT: allows an Owner to nest/unnest their token (Restricted nesting)', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); --- a/tests/src/eth/nonFungible.test.ts +++ b/tests/src/eth/nonFungible.test.ts @@ -37,7 +37,7 @@ const caller = await helper.eth.createAccountWithBalance(donor); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); const totalSupply = await contract.methods.totalSupply().call(); expect(totalSupply).to.equal('1'); @@ -51,7 +51,7 @@ await collection.mintToken(alice, {Ethereum: caller}); await collection.mintToken(alice, {Ethereum: caller}); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); const balance = await contract.methods.balanceOf(caller).call(); expect(balance).to.equal('3'); @@ -63,7 +63,7 @@ const token = await collection.mintToken(alice, {Ethereum: caller}); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); const owner = await contract.methods.ownerOf(token.tokenId).call(); @@ -74,7 +74,7 @@ const collection = await helper.nft.mintCollection(alice, {name: 'test', tokenPrefix: 'TEST'}); const caller = helper.eth.createAccount(); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); expect(await contract.methods.name().call()).to.equal('test'); expect(await contract.methods.symbol().call()).to.equal('TEST'); @@ -95,7 +95,7 @@ const receiver = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Mint collection', 'a', 'b', baseUri); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const result = await contract.methods.mint(receiver).send(); const tokenId = result.events.Transfer.returnValues.tokenId; @@ -155,7 +155,7 @@ const receiver = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'Mint collection', '6', '6', ''); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const result = await contract.methods.mintWithTokenURI(receiver, 'Test URI').send(); const tokenId = result.events.Transfer.returnValues.tokenId; @@ -174,7 +174,7 @@ // const tokenUri = await contract.methods.tokenURI(nextTokenId).call(); // expect(tokenUri).to.be.equal(`https://offchain-service.local/token-info/${nextTokenId}`); }); - + // TODO combine all minting tests in one place [ 'substrate' as const, @@ -200,16 +200,16 @@ }, }; }); - - + + const collection = await helper.nft.mintCollection(minter, { tokenPrefix: 'ethp', tokenPropertyPermissions: permissions, }); await collection.addAdmin(minter, {Ethereum: collectionAdmin}); - + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', collectionAdmin, true); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', collectionAdmin, true); let expectedTokenId = await contract.methods.nextTokenId().call(); let result = await contract.methods.mintCross(testCase === 'ethereum' ? receiverCrossEth : receiverCrossSub, []).send(); let tokenId = result.events.Transfer.returnValues.tokenId; @@ -220,7 +220,7 @@ expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000'); expect(event.returnValues.to).to.be.equal(testCase === 'ethereum' ? receiverEth : helper.address.substrateToEth(bob.address)); expect(await contract.methods.properties(tokenId, []).call()).to.be.like([]); - + expectedTokenId = await contract.methods.nextTokenId().call(); result = await contract.methods.mintCross(testCase === 'ethereum' ? receiverCrossEth : receiverCrossSub, properties).send(); event = result.events.Transfer; @@ -228,14 +228,14 @@ expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000'); expect(event.returnValues.to).to.be.equal(testCase === 'ethereum' ? receiverEth : helper.address.substrateToEth(bob.address)); expect(await contract.methods.properties(tokenId, []).call()).to.be.like([]); - + tokenId = result.events.Transfer.returnValues.tokenId; - + expect(tokenId).to.be.equal(expectedTokenId); expect(await contract.methods.properties(tokenId, []).call()).to.be.like(properties .map(p => { return helper.ethProperty.property(p.key, p.value.toString()); })); - + expect(await helper.nft.getTokenOwner(collection.collectionId, tokenId)) .to.deep.eq(testCase === 'ethereum' ? {Ethereum: receiverEth.toLowerCase()} : {Substrate: receiverSub.address}); }); @@ -247,12 +247,12 @@ const collection = await helper.nft.mintCollection(minter); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft'); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft'); await expect(collectionEvm.methods.mintCross(nonOwnerCross, []).call({from: nonOwner})) .to.be.rejectedWith('PublicMintingNotAllowed'); }); - + //TODO: CORE-302 add eth methods itEth.skip('Can perform mintBulk()', async ({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); @@ -262,7 +262,7 @@ await collection.addAdmin(minter, {Ethereum: caller}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', caller); { const bulkSize = 3; const nextTokenId = await contract.methods.nextTokenId().call(); @@ -294,7 +294,7 @@ const {tokenId} = await collection.mintToken(minter, {Ethereum: caller}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', caller); { const result = await contract.methods.burn(tokenId).send({from: caller}); @@ -315,7 +315,7 @@ const {tokenId} = await collection.mintToken(minter, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); { const result = await contract.methods.approve(spender, tokenId).send({from: owner}); @@ -335,7 +335,7 @@ const collection = await helper.nft.mintCollection(minter, {}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const approvedBefore = await contract.methods.isApprovedForAll(owner, operator).call(); expect(approvedBefore).to.be.equal(false); @@ -384,7 +384,7 @@ const token = await collection.mintToken(minter, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft'); + const contract = await helper.ethNativeContract.collection(address, 'nft'); { await contract.methods.setApprovalForAll(operator, true).send({from: owner}); @@ -405,7 +405,7 @@ expect(await helper.nft.doesTokenExist(collection.collectionId, token.tokenId)).to.be.false; }); - + itEth('Can perform transfer with ApprovalForAll', async ({helper}) => { const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); @@ -416,7 +416,7 @@ const token = await collection.mintToken(minter, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft'); + const contract = await helper.ethNativeContract.collection(address, 'nft'); { await contract.methods.setApprovalForAll(operator, true).send({from: owner}); @@ -452,7 +452,7 @@ const token2 = await collection.mintToken(minter, {Ethereum: ownerEth}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft'); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft'); // Approve tokens from substrate and ethereum: await token1.approve(ownerSub, {Ethereum: burnerEth}); @@ -466,7 +466,7 @@ // Check events for burnFromCross (substrate and ethereum): [ - [events1, token1, helper.address.substrateToEth(ownerSub.address)], + [events1, token1, helper.address.substrateToEth(ownerSub.address)], [events2, token2, ownerEth], ].map(burnData => { expect(burnData[0]).to.be.like({ @@ -499,7 +499,7 @@ const token1 = await collection.mintToken(minter, {Ethereum: owner}); const token2 = await collection.mintToken(minter, {Ethereum: owner}); - const collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); + const collectionEvm = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); // Can approveCross substrate and ethereum address: const resultSub = await collectionEvm.methods.approveCross(recieverCrossSub, token1.tokenId).send({from: owner}); @@ -538,7 +538,7 @@ const nonOwnerCross = helper.ethCrossAccount.fromAddress(nonOwner); const owner = await helper.eth.createAccountWithBalance(donor); const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); - const collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); + const collectionEvm = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); const token = await collection.mintToken(minter, {Ethereum: owner}); await expect(collectionEvm.methods.approveCross(nonOwnerCross, token.tokenId).call({from: nonOwner})).to.be.rejectedWith('CantApproveMoreThanOwned'); @@ -553,7 +553,7 @@ const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); const token1 = await collection.mintToken(minter, {Ethereum: owner}); const token2 = await collection.mintToken(minter, {Ethereum: owner}); - const collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); + const collectionEvm = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft'); // Can approve and reaffirm approved address: await collectionEvm.methods.approveCross(receiver1Cross, token1.tokenId).send({from: owner}); @@ -581,7 +581,7 @@ const {tokenId} = await collection.mintToken(minter, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); await contract.methods.approve(spender, tokenId).send({from: owner}); @@ -615,7 +615,7 @@ const token = await collection.mintToken(minter, {Substrate: owner.address}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft'); + const contract = await helper.ethNativeContract.collection(address, 'nft'); await token.approve(owner, {Ethereum: spender}); @@ -646,7 +646,7 @@ const {tokenId} = await collection.mintToken(minter, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); { const result = await contract.methods.transfer(receiver, tokenId).send({from: owner}); @@ -668,18 +668,18 @@ expect(+balance).to.equal(1); } }); - + itEth('Can perform transferCross()', async ({helper}) => { const collection = await helper.nft.mintCollection(minter, {}); const owner = await helper.eth.createAccountWithBalance(donor); const receiverEth = await helper.eth.createAccountWithBalance(donor); const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth); const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter); - + const {tokenId} = await collection.mintToken(minter, {Ethereum: owner}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); { // Can transferCross to ethereum address: @@ -690,7 +690,7 @@ expect(event.returnValues.from).to.be.equal(owner); expect(event.returnValues.to).to.be.equal(receiverEth); expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`); - + // owner has balance = 0: const ownerBalance = await collectionEvm.methods.balanceOf(owner).call(); expect(+ownerBalance).to.equal(0); @@ -699,7 +699,7 @@ expect(+receiverBalance).to.equal(1); expect(await helper.nft.getTokenOwner(collection.collectionId, tokenId)).to.deep.eq({Ethereum: receiverEth.toLowerCase()}); } - + { // Can transferCross to substrate address: const substrateResult = await collectionEvm.methods.transferCross(receiverCrossSub, tokenId).send({from: receiverEth}); @@ -709,7 +709,7 @@ expect(event.returnValues.from).to.be.equal(receiverEth); expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address)); expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`); - + // owner has balance = 0: const ownerBalance = await collectionEvm.methods.balanceOf(receiverEth).call(); expect(+ownerBalance).to.equal(0); @@ -727,7 +727,7 @@ const collection = await helper.nft.mintCollection(minter, {}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', sender); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', sender); await collection.mintToken(minter, {Ethereum: sender}); const nonSendersToken = await collection.mintToken(minter, {Ethereum: tokenOwner}); @@ -760,7 +760,7 @@ const collection = await helper.nft.mintCollection(alice, {}); const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner); const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, tokenId).send({from: owner})); expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); @@ -773,7 +773,7 @@ const collection = await helper.nft.mintCollection(alice, {}); const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner); await contract.methods.approve(spender, tokenId).send({from: owner}); @@ -792,7 +792,7 @@ const token = await collection.mintToken(collectionMinter, {Substrate: owner.address}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft'); + const contract = await helper.ethNativeContract.collection(address, 'nft'); await token.approve(owner, {Ethereum: spender}); @@ -822,7 +822,7 @@ const collection = await helper.nft.mintCollection(alice, {}); const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', owner); const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, tokenId).send({from: owner})); expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); @@ -843,7 +843,7 @@ itEth('Events emitted for mint()', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft'); const events: any = []; contract.events.allEvents((_: any, event: any) => { @@ -866,7 +866,7 @@ const token = await collection.mintToken(alice); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft'); const events: any = []; contract.events.allEvents((_: any, event: any) => { @@ -891,7 +891,7 @@ const token = await collection.mintToken(alice); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft'); const events: any = []; contract.events.allEvents((_: any, event: any) => { @@ -918,7 +918,7 @@ await token.approve(alice, {Substrate: bob.address}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft'); const events: any = []; contract.events.allEvents((_: any, event: any) => { @@ -943,7 +943,7 @@ const token = await collection.mintToken(alice); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft'); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft'); const events: any = []; contract.events.allEvents((_: any, event: any) => { @@ -993,7 +993,7 @@ }, ); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); const name = await contract.methods.name().call(); expect(name).to.equal('oh River'); }); @@ -1018,7 +1018,7 @@ }, ); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller); const symbol = await contract.methods.symbol().call(); expect(symbol).to.equal('CHANGE'); }); @@ -1045,7 +1045,7 @@ const token = await collection.mintToken(minter, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft'); + const contract = await helper.ethNativeContract.collection(address, 'nft'); const ownerCross = helper.ethCrossAccount.fromAddress(owner); await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected; @@ -1066,7 +1066,7 @@ const token = await collection.mintToken(minter, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft'); + const contract = await helper.ethNativeContract.collection(address, 'nft'); const ownerCross = helper.ethCrossAccount.fromAddress(owner); const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver); @@ -1075,7 +1075,7 @@ await contract.methods.setApprovalForAll(spender, true).send({from: owner}); await contract.methods.setApprovalForAll(spender, false).send({from: owner}); - + await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected; }); }); --- a/tests/src/eth/payable.test.ts +++ b/tests/src/eth/payable.test.ts @@ -175,7 +175,7 @@ const SMALL_FEE = 1n * helper.balance.getOneTokenNominal(); const BIG_FEE = 3n * helper.balance.getOneTokenNominal(); const caller = await helper.eth.createAccountWithBalance(donor); - const collectionHelper = helper.ethNativeContract.collectionHelpers(caller); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(caller); await expect(collectionHelper.methods.createNFTCollection('A', 'B', 'C').call({value: Number(SMALL_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); await expect(collectionHelper.methods.createNFTCollection('A', 'B', 'C').call({value: Number(BIG_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); @@ -185,7 +185,7 @@ const SMALL_FEE = 1n * helper.balance.getOneTokenNominal(); const BIG_FEE = 3n * helper.balance.getOneTokenNominal(); const caller = await helper.eth.createAccountWithBalance(donor); - const collectionHelper = helper.ethNativeContract.collectionHelpers(caller); + const collectionHelper = await helper.ethNativeContract.collectionHelpers(caller); await expect(collectionHelper.methods.createRFTCollection('A', 'B', 'C').call({value: Number(SMALL_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); await expect(collectionHelper.methods.createRFTCollection('A', 'B', 'C').call({value: Number(BIG_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)'); --- a/tests/src/eth/proxy/fungibleProxy.test.ts +++ b/tests/src/eth/proxy/fungibleProxy.test.ts @@ -48,7 +48,7 @@ await collection.mint(alice, 200n, {Substrate: alice.address}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'ft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'ft', caller); const contract = await proxyWrap(helper, evmCollection, donor); const totalSupply = await contract.methods.totalSupply().call(); @@ -62,7 +62,7 @@ await collection.mint(alice, 200n, {Ethereum: caller}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'ft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'ft', caller); const contract = await proxyWrap(helper, evmCollection, donor); const balance = await contract.methods.balanceOf(caller).call(); @@ -87,7 +87,7 @@ const spender = helper.eth.createAccount(); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'ft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'ft', caller); const contract = await proxyWrap(helper, evmCollection, donor); await collection.mint(alice, 200n, {Ethereum: contract.options.address}); @@ -123,7 +123,7 @@ const receiver = helper.eth.createAccount(); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'ft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'ft', caller); const contract = await proxyWrap(helper, evmCollection, donor); await evmCollection.methods.approve(contract.options.address, 100).send({from: owner}); @@ -170,7 +170,7 @@ const receiver = await helper.eth.createAccountWithBalance(donor); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'ft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'ft', caller); const contract = await proxyWrap(helper, evmCollection, donor); await collection.mint(alice, 200n, {Ethereum: contract.options.address}); --- a/tests/src/eth/proxy/nonFungibleProxy.test.ts +++ b/tests/src/eth/proxy/nonFungibleProxy.test.ts @@ -48,7 +48,7 @@ await collection.mintToken(alice, {Substrate: alice.address}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'nft', caller); const contract = await proxyWrap(helper, evmCollection, donor); const totalSupply = await contract.methods.totalSupply().call(); @@ -66,7 +66,7 @@ ]); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'nft', caller); const contract = await proxyWrap(helper, evmCollection, donor); const balance = await contract.methods.balanceOf(caller).call(); @@ -80,7 +80,7 @@ const {tokenId} = await collection.mintToken(alice, {Ethereum: caller}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'nft', caller); const contract = await proxyWrap(helper, evmCollection, donor); const owner = await contract.methods.ownerOf(tokenId).call(); @@ -106,8 +106,8 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); - const collectionEvmOwned = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', caller, true); + const collectionEvmOwned = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', caller, true); const contract = await proxyWrap(helper, collectionEvm, donor); await collectionEvmOwned.methods.addCollectionAdmin(contract.options.address).send(); @@ -141,8 +141,8 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); - const collectionEvmOwned = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', caller); + const collectionEvmOwned = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', caller); const contract = await proxyWrap(helper, collectionEvm, donor); const contractAddressCross = helper.ethCrossAccount.fromAddress(contract.options.address); await collectionEvmOwned.methods.addCollectionAdminCross(contractAddressCross).send(); @@ -179,7 +179,7 @@ const receiver = helper.eth.createAccount(); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'nft', caller); const contract = await proxyWrap(helper, evmCollection, donor); await collection.addAdmin(donor, {Ethereum: contract.options.address}); @@ -237,7 +237,7 @@ const caller = await helper.eth.createAccountWithBalance(donor); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'nft', caller); const contract = await proxyWrap(helper, evmCollection, donor); const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address}); await collection.addAdmin(alice, {Ethereum: contract.options.address}); @@ -266,7 +266,7 @@ const spender = helper.eth.createAccount(); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'nft', caller); const contract = await proxyWrap(helper, evmCollection, donor); const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address}); @@ -296,7 +296,7 @@ const receiver = helper.eth.createAccount(); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'nft', caller); const contract = await proxyWrap(helper, evmCollection, donor); const {tokenId} = await collection.mintToken(alice, {Ethereum: owner}); @@ -335,7 +335,7 @@ const receiver = helper.eth.createAccount(); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const evmCollection = helper.ethNativeContract.collection(address, 'nft', caller); + const evmCollection = await helper.ethNativeContract.collection(address, 'nft', caller); const contract = await proxyWrap(helper, evmCollection, donor); const {tokenId} = await collection.mintToken(alice, {Ethereum: contract.options.address}); --- a/tests/src/eth/reFungible.test.ts +++ b/tests/src/eth/reFungible.test.ts @@ -33,7 +33,7 @@ itEth('totalSupply', async ({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'TotalSupply', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); await contract.methods.mint(caller).send(); @@ -44,7 +44,7 @@ itEth('balanceOf', async ({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'BalanceOf', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); await contract.methods.mint(caller).send(); await contract.methods.mint(caller).send(); @@ -57,7 +57,7 @@ itEth('ownerOf', async ({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; @@ -70,11 +70,11 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf-AfterBurn', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; - const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); + const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); await tokenContract.methods.repartition(2).send(); await tokenContract.methods.transfer(receiver, 1).send(); @@ -89,11 +89,11 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Partial-OwnerOf', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; - const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); + const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); await tokenContract.methods.repartition(2).send(); await tokenContract.methods.transfer(receiver, 1).send(); @@ -122,7 +122,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Minty', '6', '6', ''); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner); const result = await contract.methods.mintWithTokenURI(receiver, 'Test URI').send(); @@ -136,7 +136,7 @@ expect(await contract.methods.crossOwnerOf(tokenId).call()).to.be.like([receiver, '0']); expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI'); }); - + [ 'substrate' as const, 'ethereum' as const, @@ -155,16 +155,16 @@ collectionAdmin: true, mutable: false}}; }); - - + + const collection = await helper.rft.mintCollection(minter, { tokenPrefix: 'ethp', tokenPropertyPermissions: permissions, }); await collection.addAdmin(minter, {Ethereum: collectionAdmin}); - + const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', collectionAdmin, true); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', collectionAdmin, true); let expectedTokenId = await contract.methods.nextTokenId().call(); let result = await contract.methods.mintCross(testCase === 'ethereum' ? receiverCrossEth : receiverCrossSub, []).send(); let tokenId = result.events.Transfer.returnValues.tokenId; @@ -175,7 +175,7 @@ expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000'); expect(event.returnValues.to).to.be.equal(testCase === 'ethereum' ? receiverEth : helper.address.substrateToEth(bob.address)); expect(await contract.methods.properties(tokenId, []).call()).to.be.like([]); - + expectedTokenId = await contract.methods.nextTokenId().call(); result = await contract.methods.mintCross(testCase === 'ethereum' ? receiverCrossEth : receiverCrossSub, properties).send(); event = result.events.Transfer; @@ -183,11 +183,11 @@ expect(event.returnValues.from).to.be.equal('0x0000000000000000000000000000000000000000'); expect(event.returnValues.to).to.be.equal(testCase === 'ethereum' ? receiverEth : helper.address.substrateToEth(bob.address)); expect(await contract.methods.properties(tokenId, []).call()).to.be.like([]); - + tokenId = result.events.Transfer.returnValues.tokenId; expect(tokenId).to.be.equal(expectedTokenId); - + expect(await contract.methods.properties(tokenId, []).call()).to.be.like(properties .map(p => { return helper.ethProperty.property(p.key, p.value.toString()); })); @@ -200,7 +200,7 @@ const owner = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'MintBulky', '6', '6', ''); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner); { const nextTokenId = await contract.methods.nextTokenId().call(); @@ -236,7 +236,7 @@ const collection = await helper.rft.mintCollection(minter, {}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner); const approvedBefore = await contract.methods.isApprovedForAll(owner, operator).call(); expect(approvedBefore).to.be.equal(false); @@ -285,7 +285,7 @@ const token = await collection.mintToken(minter, 100n, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'rft'); + const contract = await helper.ethNativeContract.collection(address, 'rft'); { await contract.methods.setApprovalForAll(operator, true).send({from: owner}); @@ -314,9 +314,9 @@ const token = await collection.mintToken(minter, 100n, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'rft'); + const contract = await helper.ethNativeContract.collection(address, 'rft'); - const rftToken = helper.ethNativeContract.rftTokenById(token.collectionId, token.tokenId, owner); + const rftToken = await helper.ethNativeContract.rftTokenById(token.collectionId, token.tokenId, owner); { await rftToken.methods.approve(operator, 15n).send({from: owner}); @@ -326,7 +326,7 @@ expect(allowance).to.be.equal('5'); } }); - + itEth('Can perform transfer with ApprovalForAll', async ({helper}) => { const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); @@ -337,7 +337,7 @@ const token = await collection.mintToken(minter, 100n, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'rft'); + const contract = await helper.ethNativeContract.collection(address, 'rft'); { await contract.methods.setApprovalForAll(operator, true).send({from: owner}); @@ -362,7 +362,7 @@ itEth('Can perform burn()', async ({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Burny', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; @@ -380,14 +380,14 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'TransferFromy', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId); - const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, caller); + const tokenContract = await helper.ethNativeContract.rftToken(tokenAddress, caller); await tokenContract.methods.repartition(15).send(); { @@ -432,10 +432,10 @@ const token = await collection.mintToken(minter, 100n, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'rft', spender, true); + const contract = await helper.ethNativeContract.collection(address, 'rft', spender, true); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId); - const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const tokenContract = await helper.ethNativeContract.rftToken(tokenAddress, owner); await tokenContract.methods.repartition(15).send(); await tokenContract.methods.approve(spender, 15).send(); @@ -458,14 +458,14 @@ itEth('Can perform burnFromCross()', async ({helper}) => { const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); - + const owner = bob; const spender = await helper.eth.createAccountWithBalance(donor, 100n); const token = await collection.mintToken(minter, 100n, {Substrate: owner.address}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'rft'); + const contract = await helper.ethNativeContract.collection(address, 'rft'); await token.repartition(owner, 15n); await token.approve(owner, {Ethereum: spender}, 15n); @@ -498,7 +498,7 @@ const token = await collection.mintToken(minter, 100n, {Substrate: owner.address}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'rft'); + const contract = await helper.ethNativeContract.collection(address, 'rft'); await token.repartition(owner, 15n); await token.approve(owner, {Ethereum: spender}, 15n); @@ -526,7 +526,7 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; @@ -551,7 +551,7 @@ expect(+balance).to.equal(1); } }); - + itEth('Can perform transferCross()', async ({helper}) => { const sender = await helper.eth.createAccountWithBalance(donor); const receiverEth = await helper.eth.createAccountWithBalance(donor); @@ -560,7 +560,7 @@ const collection = await helper.rft.mintCollection(minter, {}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', sender); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', sender); const token = await collection.mintToken(minter, 50n, {Ethereum: sender}); @@ -582,7 +582,7 @@ expect(+receiverBalance).to.equal(1); expect(await token.getBalance({Ethereum: receiverEth})).to.eq(50n); } - + { // Can transferCross to substrate address: const substrateResult = await collectionEvm.methods.transferCross(receiverCrossSub, token.tokenId).send({from: receiverEth}); @@ -611,7 +611,7 @@ const collection = await helper.rft.mintCollection(minter, {}); const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId); - const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', sender); + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', sender); await collection.mintToken(minter, 50n, {Ethereum: sender}); const nonSendersToken = await collection.mintToken(minter, 50n, {Ethereum: tokenOwner}); @@ -627,12 +627,12 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry-Partial-to-Full', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; - const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); + const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); await tokenContract.methods.repartition(2).send(); await tokenContract.methods.transfer(receiver, 1).send(); @@ -656,12 +656,12 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry-Full-to-Partial', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; - const tokenContract = helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); + const tokenContract = await helper.ethNativeContract.rftTokenById(collectionId, tokenId, caller); await tokenContract.methods.repartition(2).send(); @@ -696,7 +696,7 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Feeful-Transfer-From', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; @@ -710,7 +710,7 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Feeful-Transfer', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; @@ -754,7 +754,7 @@ }, ); - const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'rft', caller); + const contract = await helper.ethNativeContract.collectionById(collection.collectionId, 'rft', caller); const name = await contract.methods.name().call(); expect(name).to.equal('Leviathan'); }); @@ -779,7 +779,7 @@ }, ); - const contract = helper.ethNativeContract.collectionById(collectionId, 'rft', caller); + const contract = await helper.ethNativeContract.collectionById(collectionId, 'rft', caller); const symbol = await contract.methods.symbol().call(); expect(symbol).to.equal('12'); }); @@ -793,7 +793,7 @@ before(async function() { await usingEthPlaygrounds(async (helper, privateKey) => { requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); - + donor = await privateKey({filename: __filename}); [minter, alice] = await helper.arrange.createAccounts([100n, 100n], donor); }); @@ -808,7 +808,7 @@ const token = await collection.mintToken(minter, 100n, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'rft'); + const contract = await helper.ethNativeContract.collection(address, 'rft'); const ownerCross = helper.ethCrossAccount.fromAddress(owner); @@ -830,16 +830,16 @@ const token = await collection.mintToken(minter, 100n, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'rft'); + const contract = await helper.ethNativeContract.collection(address, 'rft'); const ownerCross = helper.ethCrossAccount.fromAddress(owner); const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver); - + await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected; await contract.methods.setApprovalForAll(spender, true).send({from: owner}); await contract.methods.setApprovalForAll(spender, false).send({from: owner}); - + await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected; }); }); --- a/tests/src/eth/reFungibleToken.test.ts +++ b/tests/src/eth/reFungibleToken.test.ts @@ -38,7 +38,7 @@ const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'}); const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller}); - const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); + const contract = await helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); const totalSupply = await contract.methods.totalSupply().call(); expect(totalSupply).to.equal('200'); }); @@ -48,7 +48,7 @@ const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'}); const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller}); - const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); + const contract = await helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); const balance = await contract.methods.balanceOf(caller).call(); expect(balance).to.equal('200'); }); @@ -58,7 +58,7 @@ const collection = await helper.rft.mintCollection(alice, {tokenPrefix: 'MUON'}); const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: caller}); - const contract = helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); + const contract = await helper.ethNativeContract.rftTokenById(collection.collectionId, tokenId, caller); const decimals = await contract.methods.decimals().call(); expect(decimals).to.equal('0'); }); @@ -81,7 +81,7 @@ const receiver = helper.eth.createAccount(); const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Mint collection', 'a', 'b', baseUri); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner); const result = await contract.methods.mint(receiver).send(); @@ -143,7 +143,7 @@ const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); { const result = await contract.methods.approve(spender, 100).send({from: owner}); @@ -159,20 +159,20 @@ expect(+allowance).to.equal(100); } }); - + itEth('Can perform approveCross()', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const spender = helper.eth.createAccount(); const spenderSub = (await helper.arrange.createAccounts([1n], donor))[0]; const spenderCrossEth = helper.ethCrossAccount.fromAddress(spender); const spenderCrossSub = helper.ethCrossAccount.fromKeyringPair(spenderSub); - + const collection = await helper.rft.mintCollection(alice); const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); { const result = await contract.methods.approveCross(spenderCrossEth, 100).send({from: owner}); @@ -187,8 +187,8 @@ const allowance = await contract.methods.allowance(owner, spender).call(); expect(+allowance).to.equal(100); } - - + + { const result = await contract.methods.approveCross(spenderCrossSub, 100).send({from: owner}); const event = result.events.Approval; @@ -202,7 +202,7 @@ const allowance = await collection.getTokenApprovedPieces(tokenId, {Ethereum: owner}, {Substrate: spenderSub.address}); expect(allowance).to.equal(100n); } - + { //TO-DO expect with future allowanceCross(owner, spenderCrossEth).call() } @@ -216,7 +216,7 @@ const token = await collection.mintToken(alice, 100n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId); - const tokenEvm = helper.ethNativeContract.rftToken(tokenAddress, owner); + const tokenEvm = await helper.ethNativeContract.rftToken(tokenAddress, owner); await expect(tokenEvm.methods.approveCross(nonOwnerCross, 20).call({from: nonOwner})).to.be.rejectedWith('CantApproveMoreThanOwned'); }); @@ -224,7 +224,7 @@ [ 'transferFrom', 'transferFromCross', - ].map(testCase => + ].map(testCase => itEth(`Can perform ${testCase}`, async ({helper}) => { const isCross = testCase === 'transferFromCross'; const owner = await helper.eth.createAccountWithBalance(donor); @@ -234,21 +234,21 @@ const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth); const [receiverSub] = await helper.arrange.createAccounts([1n], donor); const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(receiverSub); - + const collection = await helper.rft.mintCollection(alice); const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); await contract.methods.approve(spender, 100).send({from: owner}); - + // 1. Can transfer from // 1.1 Plain ethereum or cross address: { const result = await contract.methods[testCase]( isCross ? ownerCross : owner, - isCross ? receiverCrossEth : receiverEth, + isCross ? receiverCrossEth : receiverEth, 49, ).send({from: spender}); @@ -272,7 +272,7 @@ expect(+receiverBalance).to.equal(49); expect(+ownerBalance).to.equal(151); } - + // 1.2 Cross substrate address: if (testCase === 'transferFromCross') { const result = await contract.methods.transferFromCross(ownerCross, receiverCrossSub, 51).send({from: spender}); @@ -300,7 +300,7 @@ [ 'transfer', 'transferCross', - ].map(testCase => + ].map(testCase => itEth(`Can perform ${testCase}()`, async ({helper}) => { const isCross = testCase === 'transferCross'; const owner = await helper.eth.createAccountWithBalance(donor); @@ -312,7 +312,7 @@ const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); // 1. Can transfer to plain ethereum or cross-ethereum account: { @@ -329,8 +329,8 @@ expect(+ownerBalance).to.equal(150); expect(+receiverBalance).to.equal(50); } - - // 2. Can transfer to cross-substrate account: + + // 2. Can transfer to cross-substrate account: if(isCross) { const result = await contract.methods.transferCross(receiverCrossSub, 50).send({from: owner}); // Check events: @@ -350,7 +350,7 @@ [ 'transfer', 'transferCross', - ].map(testCase => + ].map(testCase => itEth(`Cannot ${testCase}() non-owned token`, async ({helper}) => { const isCross = testCase === 'transferCross'; const owner = await helper.eth.createAccountWithBalance(donor); @@ -361,14 +361,14 @@ const rftOwner = await collection.mintToken(alice, 10n, {Ethereum: owner}); const rftReceiver = await collection.mintToken(alice, 10n, {Ethereum: receiverEth}); const tokenIdNonExist = 9999999; - + const tokenAddress1 = helper.ethAddress.fromTokenId(collection.collectionId, rftOwner.tokenId); const tokenAddress2 = helper.ethAddress.fromTokenId(collection.collectionId, rftReceiver.tokenId); const tokenAddressNonExist = helper.ethAddress.fromTokenId(collection.collectionId, tokenIdNonExist); - const tokenEvmOwner = helper.ethNativeContract.rftToken(tokenAddress1, owner); - const tokenEvmReceiver = helper.ethNativeContract.rftToken(tokenAddress2, owner); - const tokenEvmNonExist = helper.ethNativeContract.rftToken(tokenAddressNonExist, owner); - + const tokenEvmOwner = await helper.ethNativeContract.rftToken(tokenAddress1, owner); + const tokenEvmReceiver = await helper.ethNativeContract.rftToken(tokenAddress2, owner); + const tokenEvmNonExist = await helper.ethNativeContract.rftToken(tokenAddressNonExist, owner); + // 1. Can transfer zero amount (EIP-20): await tokenEvmOwner.methods[testCase](isCross ? receiverCrossEth : receiverEth, 0).send({from: owner}); // 2. Cannot transfer non-owned token: @@ -397,7 +397,7 @@ const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); await contract.methods.repartition(200).send({from: owner}); expect(+await contract.methods.balanceOf(owner).call()).to.be.equal(200); @@ -422,7 +422,7 @@ const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); const result = await contract.methods.repartition(200).send(); @@ -439,7 +439,7 @@ const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); const result = await contract.methods.repartition(50).send(); const event = result.events.Transfer; @@ -453,12 +453,12 @@ const caller = await helper.eth.createAccountWithBalance(donor); const receiver = await helper.eth.createAccountWithBalance(donor); const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Devastation', '6', '6'); - const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'rft', caller); const result = await contract.methods.mint(caller).send(); const tokenId = result.events.Transfer.returnValues.tokenId; const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId); - const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, caller); + const tokenContract = await helper.ethNativeContract.rftToken(tokenAddress, caller); await tokenContract.methods.repartition(2).send(); await tokenContract.methods.transfer(receiver, 1).send(); @@ -476,26 +476,26 @@ expect(event.returnValues.to).to.be.equal(receiver); expect(event.returnValues.tokenId).to.be.equal(tokenId); }); - + itEth('Can perform burnFromCross()', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const ownerSub = (await helper.arrange.createAccounts([10n], donor))[0]; const ownerCross = helper.ethCrossAccount.fromAddress(owner); const spender = await helper.eth.createAccountWithBalance(donor); - + const spenderCrossEth = helper.ethCrossAccount.fromAddress(spender); const ownerSubCross = helper.ethCrossAccount.fromKeyringPair(ownerSub); const collection = await helper.rft.mintCollection(alice); const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); - + const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); { await contract.methods.approveCross(spenderCrossEth, 100).send({from: owner}); - + await expect(contract.methods.burnFromCross(ownerCross, 50).send({from: spender})).to.be.fulfilled; await expect(contract.methods.burnFromCross(ownerCross, 100).send({from: spender})).to.be.rejected; expect(await contract.methods.balanceOf(owner).call({from: owner})).to.be.equal('150'); @@ -504,8 +504,8 @@ const {tokenId} = await collection.mintToken(alice, 200n, {Substrate: ownerSub.address}); await collection.approveToken(ownerSub, tokenId, {Ethereum: spender}, 100n); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); - + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); + await expect(contract.methods.burnFromCross(ownerSubCross, 50).send({from: spender})).to.be.fulfilled; await expect(contract.methods.burnFromCross(ownerSubCross, 100).send({from: spender})).to.be.rejected; expect(await collection.getTokenBalance(tokenId, {Substrate: ownerSub.address})).to.be.equal(150n); @@ -533,7 +533,7 @@ const {tokenId} = await collection.mintToken(alice, 100n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); const cost = await helper.eth.recordCallFee(owner, () => contract.methods.approve(spender, 100).send({from: owner})); expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); @@ -546,7 +546,7 @@ const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); await contract.methods.approve(spender, 100).send({from: owner}); @@ -561,7 +561,7 @@ const {tokenId} = await collection.mintToken(alice, 200n, {Ethereum: owner}); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const contract = await helper.ethNativeContract.rftToken(tokenAddress, owner); const cost = await helper.eth.recordCallFee(owner, () => contract.methods.transfer(receiver, 100).send({from: owner})); expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal()))); @@ -587,7 +587,7 @@ const token = await collection.mintToken(alice, 200n); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress); + const contract = await helper.ethNativeContract.rftToken(tokenAddress); const events: any = []; contract.events.allEvents((_: any, event: any) => { @@ -613,7 +613,7 @@ await token.approve(alice, {Substrate: bob.address}, 100n); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress); + const contract = await helper.ethNativeContract.rftToken(tokenAddress); const events: any = []; contract.events.allEvents((_: any, event: any) => { @@ -644,7 +644,7 @@ const token = await collection.mintToken(alice, 200n); const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId); - const contract = helper.ethNativeContract.rftToken(tokenAddress); + const contract = await helper.ethNativeContract.rftToken(tokenAddress); const events: any = []; contract.events.allEvents((_: any, event: any) => { @@ -678,13 +678,13 @@ const owner = await helper.eth.createAccountWithBalance(donor); const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sands', '', 'GRAIN'); - const collectionContract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner); + const collectionContract = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner); const result = await collectionContract.methods.mint(owner).send(); const tokenId = result.events.Transfer.returnValues.tokenId; const tokenAddress = helper.ethAddress.fromTokenId(collectionId, tokenId); - const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, owner); + const tokenContract = await helper.ethNativeContract.rftToken(tokenAddress, owner); expect(await tokenContract.methods.parentToken().call()).to.be.equal(collectionAddress); expect(await tokenContract.methods.parentTokenId().call()).to.be.equal(tokenId); --- a/tests/src/eth/sponsoring.test.ts +++ b/tests/src/eth/sponsoring.test.ts @@ -37,11 +37,11 @@ const flipper = await helper.eth.deployFlipper(owner); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner}); await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner}); - + await helpers.methods.setSponsor(flipper.options.address, sponsor).send({from: owner}); await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor}); @@ -71,7 +71,7 @@ const collector = await helper.eth.deployCollectorContract(owner); - const helpers = helper.ethNativeContract.contractHelpers(owner); + const helpers = await helper.ethNativeContract.contractHelpers(owner); await helpers.methods.toggleAllowlist(collector.options.address, true).send({from: owner}); await helpers.methods.toggleAllowed(collector.options.address, caller, true).send({from: owner}); --- a/tests/src/eth/tokenProperties.test.ts +++ b/tests/src/eth/tokenProperties.test.ts @@ -47,12 +47,12 @@ await collection.methods.setTokenPropertyPermissions([ ['testKey', [ - [EthTokenPermissions.Mutable, mutable], - [EthTokenPermissions.TokenOwner, tokenOwner], + [EthTokenPermissions.Mutable, mutable], + [EthTokenPermissions.TokenOwner, tokenOwner], [EthTokenPermissions.CollectionAdmin, collectionAdmin]], ], ]).send({from: caller.eth}); - + expect(await helper[testCase.mode].getPropertyPermissions(collectionId)).to.be.deep.equal([{ key: 'testKey', permission: {mutable, collectionAdmin, tokenOwner}, @@ -60,8 +60,8 @@ expect(await collection.methods.tokenPropertyPermissions().call({from: caller.eth})).to.be.like([ ['testKey', [ - [EthTokenPermissions.Mutable.toString(), mutable], - [EthTokenPermissions.TokenOwner.toString(), tokenOwner], + [EthTokenPermissions.Mutable.toString(), mutable], + [EthTokenPermissions.TokenOwner.toString(), tokenOwner], [EthTokenPermissions.CollectionAdmin.toString(), collectionAdmin]], ], ]); @@ -74,28 +74,28 @@ ].map(testCase => itEth.ifWithPallets(`[${testCase.mode}] Can set multiple token property permissions as owner`, testCase.requiredPallets, async({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - + const {collectionId, collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); await collection.methods.setTokenPropertyPermissions([ ['testKey_0', [ - [EthTokenPermissions.Mutable, true], - [EthTokenPermissions.TokenOwner, true], + [EthTokenPermissions.Mutable, true], + [EthTokenPermissions.TokenOwner, true], [EthTokenPermissions.CollectionAdmin, true]], ], ['testKey_1', [ - [EthTokenPermissions.Mutable, true], - [EthTokenPermissions.TokenOwner, false], + [EthTokenPermissions.Mutable, true], + [EthTokenPermissions.TokenOwner, false], [EthTokenPermissions.CollectionAdmin, true]], ], ['testKey_2', [ - [EthTokenPermissions.Mutable, false], - [EthTokenPermissions.TokenOwner, true], + [EthTokenPermissions.Mutable, false], + [EthTokenPermissions.TokenOwner, true], [EthTokenPermissions.CollectionAdmin, false]], ], ]).send({from: owner}); - + expect(await helper[testCase.mode].getPropertyPermissions(collectionId)).to.be.deep.equal([ { key: 'testKey_0', @@ -113,18 +113,18 @@ expect(await collection.methods.tokenPropertyPermissions().call({from: owner})).to.be.like([ ['testKey_0', [ - [EthTokenPermissions.Mutable.toString(), true], - [EthTokenPermissions.TokenOwner.toString(), true], + [EthTokenPermissions.Mutable.toString(), true], + [EthTokenPermissions.TokenOwner.toString(), true], [EthTokenPermissions.CollectionAdmin.toString(), true]], ], ['testKey_1', [ - [EthTokenPermissions.Mutable.toString(), true], - [EthTokenPermissions.TokenOwner.toString(), false], + [EthTokenPermissions.Mutable.toString(), true], + [EthTokenPermissions.TokenOwner.toString(), false], [EthTokenPermissions.CollectionAdmin.toString(), true]], ], ['testKey_2', [ - [EthTokenPermissions.Mutable.toString(), false], - [EthTokenPermissions.TokenOwner.toString(), true], + [EthTokenPermissions.Mutable.toString(), false], + [EthTokenPermissions.TokenOwner.toString(), true], [EthTokenPermissions.CollectionAdmin.toString(), false]], ], ]); @@ -137,29 +137,29 @@ itEth.ifWithPallets(`[${testCase.mode}] Can set multiple token property permissions as admin`, testCase.requiredPallets, async({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const caller = await helper.ethCrossAccount.createAccountWithBalance(donor); - + const {collectionId, collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); + const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); await collection.methods.addCollectionAdminCross(caller).send({from: owner}); await collection.methods.setTokenPropertyPermissions([ ['testKey_0', [ - [EthTokenPermissions.Mutable, true], - [EthTokenPermissions.TokenOwner, true], + [EthTokenPermissions.Mutable, true], + [EthTokenPermissions.TokenOwner, true], [EthTokenPermissions.CollectionAdmin, true]], ], ['testKey_1', [ - [EthTokenPermissions.Mutable, true], - [EthTokenPermissions.TokenOwner, false], + [EthTokenPermissions.Mutable, true], + [EthTokenPermissions.TokenOwner, false], [EthTokenPermissions.CollectionAdmin, true]], ], ['testKey_2', [ - [EthTokenPermissions.Mutable, false], - [EthTokenPermissions.TokenOwner, true], + [EthTokenPermissions.Mutable, false], + [EthTokenPermissions.TokenOwner, true], [EthTokenPermissions.CollectionAdmin, false]], ], ]).send({from: caller.eth}); - + expect(await helper[testCase.mode].getPropertyPermissions(collectionId)).to.be.deep.equal([ { key: 'testKey_0', @@ -177,22 +177,22 @@ expect(await collection.methods.tokenPropertyPermissions().call({from: caller.eth})).to.be.like([ ['testKey_0', [ - [EthTokenPermissions.Mutable.toString(), true], - [EthTokenPermissions.TokenOwner.toString(), true], + [EthTokenPermissions.Mutable.toString(), true], + [EthTokenPermissions.TokenOwner.toString(), true], [EthTokenPermissions.CollectionAdmin.toString(), true]], ], ['testKey_1', [ - [EthTokenPermissions.Mutable.toString(), true], - [EthTokenPermissions.TokenOwner.toString(), false], + [EthTokenPermissions.Mutable.toString(), true], + [EthTokenPermissions.TokenOwner.toString(), false], [EthTokenPermissions.CollectionAdmin.toString(), true]], ], ['testKey_2', [ - [EthTokenPermissions.Mutable.toString(), false], - [EthTokenPermissions.TokenOwner.toString(), true], + [EthTokenPermissions.Mutable.toString(), false], + [EthTokenPermissions.TokenOwner.toString(), true], [EthTokenPermissions.CollectionAdmin.toString(), false]], ], ]); - + })); [ @@ -202,11 +202,11 @@ expectedProps: [{key: 'testKey1', value: 'testValue1'}, {key: 'testKey2', value: 'testValue2'}], }, { - method: 'setProperty' /*Soft-deprecated*/, + method: 'setProperty' /*Soft-deprecated*/, methodParams: ['testKey1', Buffer.from('testValue1')], expectedProps: [{key: 'testKey1', value: 'testValue1'}], }, - ].map(testCase => + ].map(testCase => itEth(`[${testCase.method}] Can be set`, async({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); const collection = await helper.nft.mintCollection(alice, { @@ -225,61 +225,61 @@ await collection.addAdmin(alice, {Ethereum: caller}); const token = await collection.mintToken(alice); - - const collectionEvm = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller, testCase.method === 'setProperty'); - + + const collectionEvm = await helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller, testCase.method === 'setProperty'); + await collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).send({from: caller}); - + const properties = await token.getProperties(); expect(properties).to.deep.equal(testCase.expectedProps); })); - + [ {mode: 'nft' as const, requiredPallets: []}, {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, - ].map(testCase => + ].map(testCase => itEth.ifWithPallets(`Can be multiple set/read for ${testCase.mode}`, testCase.requiredPallets, async({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); - + const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; }); const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {tokenOwner: true, collectionAdmin: true, mutable: true}}; }); - + const collection = await helper[testCase.mode].mintCollection(alice, { tokenPrefix: 'ethp', tokenPropertyPermissions: permissions, }) as UniqueNFTCollection | UniqueRFTCollection; - + const token = await collection.mintToken(alice); - + const valuesBefore = await token.getProperties(properties.map(p => p.key)); expect(valuesBefore).to.be.deep.equal([]); - - + + await collection.addAdmin(alice, {Ethereum: caller}); - + const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, testCase.mode, caller); - + const contract = await helper.ethNativeContract.collection(address, testCase.mode, caller); + expect(await contract.methods.properties(token.tokenId, []).call()).to.be.deep.equal([]); - + await contract.methods.setProperties(token.tokenId, properties).send({from: caller}); - + const values = await token.getProperties(properties.map(p => p.key)); expect(values).to.be.deep.equal(properties.map(p => { return {key: p.key, value: p.value.toString()}; })); - + expect(await contract.methods.properties(token.tokenId, []).call()).to.be.like(properties .map(p => { return helper.ethProperty.property(p.key, p.value.toString()); })); - + expect(await contract.methods.properties(token.tokenId, [properties[0].key]).call()) .to.be.like([helper.ethProperty.property(properties[0].key, properties[0].value.toString())]); })); - + [ {mode: 'nft' as const, requiredPallets: []}, {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, - ].map(testCase => + ].map(testCase => itEth.ifWithPallets(`Can be deleted for ${testCase.mode}`, testCase.requiredPallets, async({helper}) => { const caller = await helper.eth.createAccountWithBalance(donor); const collection = await helper[testCase.mode].mintCollection(alice, { @@ -298,7 +298,7 @@ }, }], }); - + const token = await collection.mintToken(alice); await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}, {key: 'testKey_1', value: 'testValue_1'}]); expect(await token.getProperties()).to.has.length(2); @@ -306,7 +306,7 @@ await collection.addAdmin(alice, {Ethereum: caller}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, testCase.mode, caller); + const contract = await helper.ethNativeContract.collection(address, testCase.mode, caller); await contract.methods.deleteProperties(token.tokenId, ['testKey', 'testKey_1']).send({from: caller}); @@ -324,12 +324,12 @@ }, }], }); - + const token = await collection.mintToken(alice); await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]); const address = helper.ethAddress.fromCollectionId(collection.collectionId); - const contract = helper.ethNativeContract.collection(address, 'nft', caller); + const contract = await helper.ethNativeContract.collection(address, 'nft', caller); const value = await contract.methods.property(token.tokenId, 'testKey').call(); expect(value).to.equal(helper.getWeb3().utils.toHex('testValue')); @@ -371,10 +371,10 @@ collectionAdmin: true, }, }], - }); + }); token = await aliceCollection.mintToken(alice); await token.setProperties(alice, tokenProps); - collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, true); + collectionEvm = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, true); }); }); @@ -384,7 +384,7 @@ ].map(testCase => itEth(`[${testCase.method}] Cannot set properties of non-owned collection`, async ({helper}) => { caller = await helper.eth.createAccountWithBalance(donor); - collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, true); + collectionEvm = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, true); // Caller not an owner and not an admin, so he cannot set properties: await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).call({from: caller})).to.be.rejectedWith('NoPermission'); await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).send({from: caller})).to.be.rejected; @@ -401,7 +401,7 @@ ].map(testCase => itEth(`[${testCase.method}] Cannot set non-existing properties`, async ({helper}) => { caller = await helper.eth.createAccountWithBalance(donor); - collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, true); + collectionEvm = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, true); await helper.collection.addAdmin(alice, aliceCollection.collectionId, {Ethereum: caller}); await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).call({from: caller})).to.be.rejectedWith('NoPermission'); @@ -416,10 +416,10 @@ [ {method: 'deleteProperty', methodParams: ['testKey_2']}, {method: 'deleteProperties', methodParams: [['testKey_2']]}, - ].map(testCase => + ].map(testCase => itEth(`[${testCase.method}] Cannot delete properties of non-owned collection`, async ({helper}) => { caller = await helper.eth.createAccountWithBalance(donor); - collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, testCase.method == 'deleteProperty'); + collectionEvm = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, testCase.method == 'deleteProperty'); // Caller not an owner and not an admin, so he cannot set properties: await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).call({from: caller})).to.be.rejectedWith('NoPermission'); await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).send({from: caller})).to.be.rejected; @@ -429,14 +429,14 @@ const actualProps = await collectionEvm.methods.properties(token.tokenId, []).call(); expect(actualProps).to.deep.eq(expectedProps); })); - + [ {method: 'deleteProperty', methodParams: ['testKey_3']}, {method: 'deleteProperties', methodParams: [['testKey_3']]}, - ].map(testCase => + ].map(testCase => itEth(`[${testCase.method}] Cannot delete non-existing properties`, async ({helper}) => { caller = await helper.eth.createAccountWithBalance(donor); - collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, testCase.method == 'deleteProperty'); + collectionEvm = await helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(aliceCollection.collectionId), 'nft', caller, testCase.method == 'deleteProperty'); await helper.collection.addAdmin(alice, aliceCollection.collectionId, {Ethereum: caller}); // Caller cannot delete non-existing properties: await expect(collectionEvm.methods[testCase.method](token.tokenId, ...testCase.methodParams).call({from: caller})).to.be.rejectedWith('NoPermission'); @@ -454,17 +454,17 @@ itEth.ifWithPallets(`[${testCase.mode}] Cannot set token property permissions as non owner or admin`, testCase.requiredPallets, async({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const caller = await helper.eth.createAccountWithBalance(donor); - + const {collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); - + const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); + await expect(collection.methods.setTokenPropertyPermissions([ ['testKey_0', [ - [EthTokenPermissions.Mutable, true], - [EthTokenPermissions.TokenOwner, true], + [EthTokenPermissions.Mutable, true], + [EthTokenPermissions.TokenOwner, true], [EthTokenPermissions.CollectionAdmin, true]], ], - ]).call({from: caller})).to.be.rejectedWith('NoPermission'); + ]).call({from: caller})).to.be.rejectedWith('NoPermission'); })); [ @@ -473,18 +473,18 @@ ].map(testCase => itEth.ifWithPallets(`[${testCase.mode}] Cannot set token property permissions with invalid character`, testCase.requiredPallets, async({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - + const {collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); - + const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); + await expect(collection.methods.setTokenPropertyPermissions([ // "Space" is invalid character ['testKey 0', [ - [EthTokenPermissions.Mutable, true], - [EthTokenPermissions.TokenOwner, true], + [EthTokenPermissions.Mutable, true], + [EthTokenPermissions.TokenOwner, true], [EthTokenPermissions.CollectionAdmin, true]], ], - ]).call({from: owner})).to.be.rejectedWith('InvalidCharacterInPropertyKey'); + ]).call({from: owner})).to.be.rejectedWith('InvalidCharacterInPropertyKey'); })); [ @@ -493,25 +493,25 @@ ].map(testCase => itEth.ifWithPallets(`[${testCase.mode}] Can reconfigure token property permissions to stricter ones`, testCase.requiredPallets, async({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - + const {collectionAddress, collectionId} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); - + const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); + // 1. Owner sets strict property-permissions: await collection.methods.setTokenPropertyPermissions([ ['testKey', [ - [EthTokenPermissions.Mutable, true], - [EthTokenPermissions.TokenOwner, true], + [EthTokenPermissions.Mutable, true], + [EthTokenPermissions.TokenOwner, true], [EthTokenPermissions.CollectionAdmin, true]], ], ]).send({from: owner}); - + // 2. Owner can set stricter property-permissions: for(const values of [[true, true, false], [true, false, false], [false, false, false]]) { await collection.methods.setTokenPropertyPermissions([ ['testKey', [ - [EthTokenPermissions.Mutable, values[0]], - [EthTokenPermissions.TokenOwner, values[1]], + [EthTokenPermissions.Mutable, values[0]], + [EthTokenPermissions.TokenOwner, values[1]], [EthTokenPermissions.CollectionAdmin, values[2]]], ], ]).send({from: owner}); @@ -529,15 +529,15 @@ ].map(testCase => itEth.ifWithPallets(`[${testCase.mode}] Cannot reconfigure token property permissions to less strict ones`, testCase.requiredPallets, async({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); - + const {collectionAddress} = await helper.eth.createCollection(testCase.mode, owner, 'A', 'B', 'C'); - const collection = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); - + const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner); + // 1. Owner sets strict property-permissions: await collection.methods.setTokenPropertyPermissions([ ['testKey', [ - [EthTokenPermissions.Mutable, false], - [EthTokenPermissions.TokenOwner, false], + [EthTokenPermissions.Mutable, false], + [EthTokenPermissions.TokenOwner, false], [EthTokenPermissions.CollectionAdmin, false]], ], ]).send({from: owner}); @@ -546,8 +546,8 @@ for(const values of [[true, false, false], [false, true, false], [false, false, true]]) { await expect(collection.methods.setTokenPropertyPermissions([ ['testKey', [ - [EthTokenPermissions.Mutable, values[0]], - [EthTokenPermissions.TokenOwner, values[1]], + [EthTokenPermissions.Mutable, values[0]], + [EthTokenPermissions.TokenOwner, values[1]], [EthTokenPermissions.CollectionAdmin, values[2]]], ], ]).call({from: owner})).to.be.rejectedWith('NoPermission'); --- a/tests/src/eth/util/playgrounds/unique.dev.ts +++ b/tests/src/eth/util/playgrounds/unique.dev.ts @@ -35,12 +35,42 @@ class EthGroupBase { helper: EthUniqueHelper; + gasPrice?: string; constructor(helper: EthUniqueHelper) { this.helper = helper; } + async getGasPrice() { + if (this.gasPrice) + return this.gasPrice; + this.gasPrice = await this.helper.getWeb3().eth.getGasPrice(); + return this.gasPrice; + } } +function unlimitedMoneyHack(_contract: C): C { + const contract = _contract as any; + // Hack: fight against gasPrice override + for (const method in contract.methods) { + const _method = contract.methods[method]; + contract.methods[method] = function (...args: any) { + const encodedCall = _method.call(this, ...args); + const _call = encodedCall.call; + encodedCall.call = function (...args: any) { + if (args.length === 0) { + return _call.call(this, {gasPrice: '0'}); + } + // No support for callback/defaultBlock, they may be placed as first argument + if (typeof args[0] !== 'object') + throw new Error('only options are supported'); + args[0].gasPrice = '0'; + return _call.call(this, ...args); + }; + return encodedCall; + }; + } + return contract; +} class ContractGroup extends EthGroupBase { async findImports(imports?: ContractImports[]){ @@ -81,7 +111,7 @@ && compiled.errors.some(function(err: any) { return err.severity == 'error'; }); - + if (hasErrors) { throw compiled.errors; } @@ -104,25 +134,34 @@ data: object, from: signer, gas: gas ?? this.helper.eth.DEFAULT_GAS, + gasPrice: await this.getGasPrice(), }); - return await contract.deploy({data: object}).send({from: signer}); + return unlimitedMoneyHack(await contract.deploy({data: object}).send({from: signer})); } } class NativeContractGroup extends EthGroupBase { - contractHelpers(caller: string): Contract { + async contractHelpers(caller: string): Promise { const web3 = this.helper.getWeb3(); - return new web3.eth.Contract(contractHelpersAbi as any, this.helper.getApi().consts.evmContractHelpers.contractAddress.toString(), {from: caller, gas: this.helper.eth.DEFAULT_GAS}); + return unlimitedMoneyHack(new web3.eth.Contract(contractHelpersAbi as any, this.helper.getApi().consts.evmContractHelpers.contractAddress.toString(), { + from: caller, + gas: this.helper.eth.DEFAULT_GAS, + gasPrice: await this.getGasPrice(), + })); } - collectionHelpers(caller: string) { + async collectionHelpers(caller: string) { const web3 = this.helper.getWeb3(); - return new web3.eth.Contract(collectionHelpersAbi as any, this.helper.getApi().consts.common.contractAddress.toString(), {from: caller, gas: this.helper.eth.DEFAULT_GAS}); + return unlimitedMoneyHack(new web3.eth.Contract(collectionHelpersAbi as any, this.helper.getApi().consts.common.contractAddress.toString(), { + from: caller, + gas: this.helper.eth.DEFAULT_GAS, + gasPrice: await this.getGasPrice(), + })); } - collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated = false): Contract { + async collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated = false) { let abi = { 'nft': nonFungibleAbi, 'rft': refungibleAbi, @@ -137,19 +176,27 @@ abi = [...abi,...deprecated]; } const web3 = this.helper.getWeb3(); - return new web3.eth.Contract(abi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})}); + return unlimitedMoneyHack(new web3.eth.Contract(abi as any, address, { + gas: this.helper.eth.DEFAULT_GAS, + gasPrice: await this.getGasPrice(), + ...(caller ? {from: caller} : {}), + })); } - collectionById(collectionId: number, mode: 'nft' | 'rft' | 'ft', caller?: string, mergeDeprecated = false): Contract { + collectionById(collectionId: number, mode: 'nft' | 'rft' | 'ft', caller?: string, mergeDeprecated = false) { return this.collection(this.helper.ethAddress.fromCollectionId(collectionId), mode, caller, mergeDeprecated); } - rftToken(address: string, caller?: string): Contract { + async rftToken(address: string, caller?: string) { const web3 = this.helper.getWeb3(); - return new web3.eth.Contract(refungibleTokenAbi as any, address, {gas: this.helper.eth.DEFAULT_GAS, ...(caller ? {from: caller} : {})}); + return unlimitedMoneyHack(new web3.eth.Contract(refungibleTokenAbi as any, address, { + gas: this.helper.eth.DEFAULT_GAS, + gasPrice: await this.getGasPrice(), + ...(caller ? {from: caller} : {}), + })); } - rftTokenById(collectionId: number, tokenId: number, caller?: string): Contract { + rftTokenById(collectionId: number, tokenId: number, caller?: string) { return this.rftToken(this.helper.ethAddress.fromTokenId(collectionId, tokenId), caller); } } @@ -177,7 +224,7 @@ } async getCollectionCreationFee(signer: string) { - const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer); + const collectionHelper = await this.helper.ethNativeContract.collectionHelpers(signer); return await collectionHelper.methods.collectionCreationFee().call(); } @@ -210,7 +257,7 @@ async createCollection(mode: TCollectionMode, signer: string, name: string, description: string, tokenPrefix: string, decimals = 18): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> { const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice(); - const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer); + const collectionHelper = await this.helper.ethNativeContract.collectionHelpers(signer); const functionName: string = this.createCollectionMethodName(mode); const functionParams = mode === 'ft' ? [name, decimals, description, tokenPrefix] : [name, description, tokenPrefix]; @@ -228,7 +275,7 @@ } async createERC721MetadataCompatibleNFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> { - const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer); + const collectionHelper = await this.helper.ethNativeContract.collectionHelpers(signer); const {collectionId, collectionAddress, events} = await this.createCollection('nft', signer, name, description, tokenPrefix); @@ -246,7 +293,7 @@ } async createERC721MetadataCompatibleRFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> { - const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer); + const collectionHelper = await this.helper.ethNativeContract.collectionHelpers(signer); const {collectionId, collectionAddress, events} = await this.createCollection('rft', signer, name, description, tokenPrefix); --- a/tests/src/maintenanceMode.seqtest.ts +++ b/tests/src/maintenanceMode.seqtest.ts @@ -128,7 +128,7 @@ // Unable to mint an RFT when the MM is enabled await expect(rftCollection.mintToken(superuser)) .to.be.rejectedWith(/Invalid Transaction: Transaction call is not expected/); - + await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.disable', []); expect(await maintenanceEnabled(helper.getApi()), 'MM is ON when it should be OFF').to.be.false; @@ -191,7 +191,7 @@ // Schedule a transaction that should occur *during* the maintenance await nftDuringMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdDuringMM}) .transfer(bob, {Substrate: superuser.address}); - + // Schedule a transaction that should occur *after* the maintenance await nftDuringMM.scheduleAfter(blocksToWait * 2, {scheduledId: scheduledIdBunkerThroughMM}) .transfer(bob, {Substrate: superuser.address}); @@ -214,7 +214,7 @@ // Scheduling works after the maintenance await nftAfterMM.scheduleAfter(blocksToWait, {scheduledId: scheduledIdAfterMM}) .transfer(bob, {Substrate: superuser.address}); - + await helper.wait.newBlocks(blocksToWait + 1); expect(await nftAfterMM.getOwner()).to.be.deep.equal({Substrate: superuser.address}); @@ -225,14 +225,14 @@ itEth('Disallows Ethereum transactions to execute while in maintenance', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const receiver = helper.eth.createAccount(); - + const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, 'A', 'B', 'C', ''); // Set maintenance mode await helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.enable', []); expect(await maintenanceEnabled(helper.getApi()), 'MM is OFF when it should be ON').to.be.true; - const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner); + const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner); const tokenId = await contract.methods.nextTokenId().call(); expect(tokenId).to.be.equal('1');