git.delta.rocks / unique-network / refs/commits / dae8a5f4351f

difftreelog

Merge pull request #629 from UniqueNetwork/feature/eth-tests-playgrnds

ut-akuznetsov2022-10-05parents: #ab38216 #5721d4c.patch.diff
in: master
Feature/eth tests playgrnds

7 files changed

modifiedtests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/collectionSponsoring.test.ts
+++ b/tests/src/eth/collectionSponsoring.test.ts
@@ -1,33 +1,45 @@
-import {addToAllowListExpectSuccess, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, enablePublicMintingExpectSuccess, getDetailedCollectionInfo, setCollectionSponsorExpectSuccess, UNIQUE} from '../util/helpers';
-import {itWeb3, createEthAccount, collectionIdToAddress, GAS_ARGS, normalizeEvents, createEthAccountWithBalance, evmCollectionHelpers, getCollectionAddressFromResult, evmCollection, ethBalanceViaSub} from './util/helpers';
-import nonFungibleAbi from './nonFungibleAbi.json';
-import {expect} from 'chai';
-import {evmToAddress} from '@polkadot/util-crypto';
+import {IKeyringPair} from '@polkadot/types/types';
+import {usingPlaygrounds} from './../util/playgrounds/index';
+import {itEth, expect} from '../eth/util/playgrounds';
 
 describe('evm collection sponsoring', () => {
-  itWeb3('sponsors mint transactions', async ({web3, privateKeyWrapper}) => {
-    const alice = privateKeyWrapper('//Alice');
+  let donor: IKeyringPair;
+  let alice: IKeyringPair;
+  let nominal: bigint;
+
+  before(async () => {
+    await usingPlaygrounds(async (helper, privateKey) => {
+      donor = privateKey('//Alice');
+      nominal = helper.balance.getOneTokenNominal();
+    });
+  });
+
+  beforeEach(async () => {
+    await usingPlaygrounds(async (helper) => {
+      [alice] = await helper.arrange.createAccounts([1000n], donor);
+    });
+  });
 
-    const collection = await createCollectionExpectSuccess();
-    await setCollectionSponsorExpectSuccess(collection, alice.address);
-    await confirmSponsorshipExpectSuccess(collection);
+  itEth('sponsors mint transactions', async ({helper}) => {
+    const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'spnr', permissions: {mintMode: true}});
+    await collection.setSponsor(alice, alice.address);
+    await collection.confirmSponsorship(alice);
 
-    const minter = createEthAccount(web3);
-    expect(await web3.eth.getBalance(minter)).to.equal('0');
+    const minter = helper.eth.createAccount();
+    expect(await helper.balance.getEthereum(minter)).to.equal(0n);
 
-    const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collection), {from: minter, ...GAS_ARGS});
+    const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', minter);
 
-    await enablePublicMintingExpectSuccess(alice, collection);
-    await addToAllowListExpectSuccess(alice, collection, {Ethereum: minter});
+    await collection.addToAllowList(alice, {Ethereum: minter});
 
     const nextTokenId = await contract.methods.nextTokenId().call();
     expect(nextTokenId).to.equal('1');
     const result = await contract.methods.mint(minter, nextTokenId).send();
-    const events = normalizeEvents(result.events);
+    const events = helper.eth.normalizeEvents(result.events);
     expect(events).to.be.deep.equal([
       {
-        address,
+        address: collectionAddress,
         event: 'Transfer',
         args: {
           from: '0x0000000000000000000000000000000000000000',
@@ -59,13 +71,14 @@
   //   expect(bigIntToSub(api, BigInt(sponsorTuple[1]))).to.be.eq(sponsor.address);
   // });
 
-  itWeb3('Remove sponsor', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const collectionHelpers = evmCollectionHelpers(web3, owner);
-    let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * UNIQUE)});
-    const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
-    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+  itEth('Remove sponsor', async ({helper}) => {
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
+
+    let result = await collectionHelpers.methods.createNonfungibleCollection('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 collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);
 
     expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;
     result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});
@@ -80,30 +93,31 @@
     expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');
   });
 
-  itWeb3('Sponsoring collection from evm address via access list', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const collectionHelpers = evmCollectionHelpers(web3, owner);
-    let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * UNIQUE)});
-    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
-    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+  itEth('Sponsoring collection from evm address via access list', async ({helper}) => {
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
+
+    let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
+    const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
+    const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);
+    const collection = helper.nft.getCollectionObject(collectionId);
+    const sponsor = await helper.eth.createAccountWithBalance(donor);
+    const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);
+
     result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});
-    let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
-    const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
-    expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
+    let collectionData = (await collection.getData())!;
+    expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
     await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
 
     await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
-    collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
-    expect(collectionSub.sponsorship.isConfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
+    collectionData = (await collection.getData())!;
+    expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
 
-    const user = createEthAccount(web3);
+    const user = helper.eth.createAccount();
     const nextTokenId = await collectionEvm.methods.nextTokenId().call();
     expect(nextTokenId).to.be.equal('1');
 
-    const oldPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
+    const oldPermissions = (await collection.getData())!.raw.permissions; // (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
     expect(oldPermissions.mintMode).to.be.false;
     expect(oldPermissions.access).to.be.equal('Normal');
 
@@ -111,12 +125,12 @@
     await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
     await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});
 
-    const newPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
+    const newPermissions = (await collection.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 ethBalanceViaSub(api, owner);
-    const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);
+    const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+    const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
 
     {
       const nextTokenId = await collectionEvm.methods.nextTokenId().call();
@@ -126,7 +140,7 @@
         nextTokenId,
         'Test URI',
       ).send({from: user});
-      const events = normalizeEvents(result.events);
+      const events = helper.eth.normalizeEvents(result.events);
 
       expect(events).to.be.deep.equal([
         {
@@ -140,8 +154,8 @@
         },
       ]);
 
-      const ownerBalanceAfter = await ethBalanceViaSub(api, owner);
-      const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);
+      const ownerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(owner));
+      const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));
 
       expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
       expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);
@@ -205,33 +219,34 @@
   //   }
   // });
 
-  itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const collectionHelpers = evmCollectionHelpers(web3, owner);
-    let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * UNIQUE)});
-    const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
-    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+  itEth('Check that transaction via EVM spend money from sponsor address', async ({helper}) => {
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
+
+    let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
+    const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
+    const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);
+    const collection = helper.nft.getCollectionObject(collectionId);
+    const sponsor = await helper.eth.createAccountWithBalance(donor);
+    const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);
+
     result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();
-    let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
-    const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
-    expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
+    let collectionData = (await collection.getData())!;
+    expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
     await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
-    const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
+
+    const sponsorCollection = helper.ethNativeContract.collection(collectionIdAddress, 'nft', sponsor);
     await sponsorCollection.methods.confirmCollectionSponsorship().send();
-    collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
-    expect(collectionSub.sponsorship.isConfirmed).to.be.true;
-    expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
+    collectionData = (await collection.getData())!;
+    expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
 
-    const user = createEthAccount(web3);
+    const user = helper.eth.createAccount();
     await collectionEvm.methods.addCollectionAdmin(user).send();
     
-    const ownerBalanceBefore = await ethBalanceViaSub(api, owner);
-    const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);
-    
-  
-    const userCollectionEvm = evmCollection(web3, user, collectionIdAddress);
+    const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
+    const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
+
+    const userCollectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', user);
     const nextTokenId = await userCollectionEvm.methods.nextTokenId().call();
     expect(nextTokenId).to.be.equal('1');
     result = await userCollectionEvm.methods.mintWithTokenURI(
@@ -240,8 +255,8 @@
       'Test URI',
     ).send();
 
-    const events = normalizeEvents(result.events);
-    const address = collectionIdToAddress(collectionId);
+    const events = helper.eth.normalizeEvents(result.events);
+    const address = helper.ethAddress.fromCollectionId(collectionId);
 
     expect(events).to.be.deep.equal([
       {
@@ -256,9 +271,9 @@
     ]);
     expect(await userCollectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
   
-    const ownerBalanceAfter = await ethBalanceViaSub(api, owner);
+    const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
     expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);
-    const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);
+    const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
     expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
   });
 });
modifiedtests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {IKeyringPair} from '@polkadot/types/types';
17import * as solc from 'solc';18import * as solc from 'solc';
18import {expect} from 'chai';19import {EthUniqueHelper} from './util/playgrounds/unique.dev';
20import {itEth, expect, SponsoringMode, usingEthPlaygrounds} from '../eth/util/playgrounds';
19import {expectSubstrateEventsAtBlock} from '../util/helpers';21import {usingPlaygrounds} from '../util/playgrounds';
20import Web3 from 'web3';22import {CompiledContract} from './util/playgrounds/types';
2123
22import {24describe('Sponsoring EVM contracts', () => {
23 contractHelpers,
24 createEthAccountWithBalance,
25 transferBalanceToEth,
26 deployFlipper,25 let donor: IKeyringPair;
27 itWeb3,
28 SponsoringMode,
29 createEthAccount,
30 ethBalanceViaSub,
31 normalizeEvents,
32 CompiledContract,
33 GAS_ARGS,
34 subToEth,
35} from './util/helpers';
36import {submitTransactionAsync} from '../substrate/substrate-api';
3726
38describe('Sponsoring EVM contracts', () => {27 before(async () => {
28 await usingPlaygrounds(async (_helper, privateKey) => {
39 itWeb3('Self sponsored can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {29 donor = privateKey('//Alice');
30 });
31 });
32
33 itEth('Self sponsored can be set by the address that deployed the contract', async ({helper, privateKey}) => {
40 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);34 const owner = await helper.eth.createAccountWithBalance(donor);
41 const flipper = await deployFlipper(web3, owner);35 const flipper = await helper.eth.deployFlipper(owner);
42 const helpers = contractHelpers(web3, owner);36 const helpers = helper.ethNativeContract.contractHelpers(owner);
37
43 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;38 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
44 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;39 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;
45 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;40 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;
46 });41 });
4742
48 itWeb3('Set self sponsored events', async ({api, web3, privateKeyWrapper}) => {43 itEth('Set self sponsored events', async ({helper}) => {
49 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);44 const owner = await helper.eth.createAccountWithBalance(donor);
50 const flipper = await deployFlipper(web3, owner);45 const flipper = await helper.eth.deployFlipper(owner);
51 const helpers = contractHelpers(web3, owner);46 const helpers = helper.ethNativeContract.contractHelpers(owner);
52 47
53 const result = await helpers.methods.selfSponsoredEnable(flipper.options.address).send();48 const result = await helpers.methods.selfSponsoredEnable(flipper.options.address).send();
54 // console.log(result);49 const ethEvents = helper.eth.helper.eth.normalizeEvents(result.events);
55 const ethEvents = normalizeEvents(result.events);
56 expect(ethEvents).to.be.deep.equal([50 expect(ethEvents).to.be.deep.equal([
57 {51 {
58 address: flipper.options.address,52 address: flipper.options.address,
71 },65 },
72 },66 },
73 ]);67 ]);
74
75 await expectSubstrateEventsAtBlock(
76 api,
77 result.blockNumber,
78 'evmContractHelpers',
79 ['ContractSponsorSet','ContractSponsorshipConfirmed'],
80 );
81 });68 });
8269
83 itWeb3('Self sponsored can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {70 itEth('Self sponsored can not be set by the address that did not deployed the contract', async ({helper}) => {
84 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);71 const owner = await helper.eth.createAccountWithBalance(donor);
85 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);72 const notOwner = await helper.eth.createAccountWithBalance(donor);
86 const flipper = await deployFlipper(web3, owner);73 const helpers = helper.ethNativeContract.contractHelpers(owner);
87 const helpers = contractHelpers(web3, owner);74 const flipper = await helper.eth.deployFlipper(owner);
75
88 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;76 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
89 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');77 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');
90 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;78 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
91 });79 });
9280
93 itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3, privateKeyWrapper}) => {81 itEth('Sponsoring can be set by the address that has deployed the contract', async ({helper}) => {
94 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);82 const owner = await helper.eth.createAccountWithBalance(donor);
95 const flipper = await deployFlipper(web3, owner);83 const helpers = helper.ethNativeContract.contractHelpers(owner);
96 const helpers = contractHelpers(web3, owner);84 const flipper = await helper.eth.deployFlipper(owner);
85
97 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;86 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
98 await expect(helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner})).to.be.not.rejected;87 await expect(helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner})).to.be.not.rejected;
99 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;88 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
100 });89 });
10190
102 itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {91 itEth('Sponsoring cannot be set by the address that did not deployed the contract', async ({helper}) => {
103 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);92 const owner = await helper.eth.createAccountWithBalance(donor);
104 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);93 const notOwner = await helper.eth.createAccountWithBalance(donor);
105 const flipper = await deployFlipper(web3, owner);94 const helpers = helper.ethNativeContract.contractHelpers(owner);
106 const helpers = contractHelpers(web3, owner);95 const flipper = await helper.eth.deployFlipper(owner);
96
107 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;97 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
108 await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).call({from: notOwner})).to.be.rejectedWith('NoPermission');98 await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).call({from: notOwner})).to.be.rejectedWith('NoPermission');
109 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;99 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;
110 });100 });
111 101
112 itWeb3('Sponsor can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {102 itEth('Sponsor can be set by the address that deployed the contract', async ({helper}) => {
113 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);103 const owner = await helper.eth.createAccountWithBalance(donor);
114 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);104 const sponsor = await helper.eth.createAccountWithBalance(donor);
115 const flipper = await deployFlipper(web3, owner);105 const helpers = helper.ethNativeContract.contractHelpers(owner);
116 const helpers = contractHelpers(web3, owner);106 const flipper = await helper.eth.deployFlipper(owner);
107
117 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;108 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;
118 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;109 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;
119 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;110 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;
120 });111 });
121 112
122 itWeb3('Set sponsor event', async ({api, web3, privateKeyWrapper}) => {113 itEth('Set sponsor event', async ({helper}) => {
123 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);114 const owner = await helper.eth.createAccountWithBalance(donor);
124 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);115 const sponsor = await helper.eth.createAccountWithBalance(donor);
125 const flipper = await deployFlipper(web3, owner);116 const helpers = helper.ethNativeContract.contractHelpers(owner);
126 const helpers = contractHelpers(web3, owner);117 const flipper = await helper.eth.deployFlipper(owner);
127 118
128 const result = await helpers.methods.setSponsor(flipper.options.address, sponsor).send();119 const result = await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
129 const events = normalizeEvents(result.events);120 const events = helper.eth.normalizeEvents(result.events);
130 expect(events).to.be.deep.equal([121 expect(events).to.be.deep.equal([
131 {122 {
132 address: flipper.options.address,123 address: flipper.options.address,
137 },128 },
138 },129 },
139 ]);130 ]);
140
141 await expectSubstrateEventsAtBlock(
142 api,
143 result.blockNumber,
144 'evmContractHelpers',
145 ['ContractSponsorSet'],
146 );
147 });131 });
148 132
149 itWeb3('Sponsor can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {133 itEth('Sponsor can not be set by the address that did not deployed the contract', async ({helper}) => {
150 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);134 const owner = await helper.eth.createAccountWithBalance(donor);
151 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);135 const sponsor = await helper.eth.createAccountWithBalance(donor);
152 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);136 const notOwner = await helper.eth.createAccountWithBalance(donor);
153 const flipper = await deployFlipper(web3, owner);137 const helpers = helper.ethNativeContract.contractHelpers(owner);
154 const helpers = contractHelpers(web3, owner);138 const flipper = await helper.eth.deployFlipper(owner);
139
155 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;140 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;
156 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).call({from: notOwner})).to.be.rejectedWith('NoPermission');141 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).call({from: notOwner})).to.be.rejectedWith('NoPermission');
157 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;142 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;
158 });143 });
159144
160 itWeb3('Sponsorship can be confirmed by the address that pending as sponsor', async ({api, web3, privateKeyWrapper}) => {145 itEth('Sponsorship can be confirmed by the address that pending as sponsor', async ({helper}) => {
161 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);146 const owner = await helper.eth.createAccountWithBalance(donor);
162 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);147 const sponsor = await helper.eth.createAccountWithBalance(donor);
163 const flipper = await deployFlipper(web3, owner);148 const helpers = helper.ethNativeContract.contractHelpers(owner);
164 const helpers = contractHelpers(web3, owner);149 const flipper = await helper.eth.deployFlipper(owner);
150
165 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;151 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
166 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;152 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;
167 await expect(helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor})).to.be.not.rejected;153 await expect(helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor})).to.be.not.rejected;
168 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;154 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;
169 });155 });
170156
171 itWeb3('Confirm sponsorship event', async ({api, web3, privateKeyWrapper}) => {157 itEth('Confirm sponsorship event', async ({helper}) => {
172 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);158 const owner = await helper.eth.createAccountWithBalance(donor);
173 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);159 const sponsor = await helper.eth.createAccountWithBalance(donor);
174 const flipper = await deployFlipper(web3, owner);160 const helpers = helper.ethNativeContract.contractHelpers(owner);
175 const helpers = contractHelpers(web3, owner);161 const flipper = await helper.eth.deployFlipper(owner);
162
176 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;163 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;
177 const result = await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});164 const result = await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});
178 const events = normalizeEvents(result.events);165 const events = helper.eth.normalizeEvents(result.events);
179 expect(events).to.be.deep.equal([166 expect(events).to.be.deep.equal([
180 {167 {
181 address: flipper.options.address,168 address: flipper.options.address,
186 },173 },
187 },174 },
188 ]);175 ]);
189
190 await expectSubstrateEventsAtBlock(
191 api,
192 result.blockNumber,
193 'evmContractHelpers',
194 ['ContractSponsorshipConfirmed'],
195 );
196 });176 });
197177
198 itWeb3('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({api, web3, privateKeyWrapper}) => {178 itEth('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({helper}) => {
199 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);179 const owner = await helper.eth.createAccountWithBalance(donor);
200 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);180 const sponsor = await helper.eth.createAccountWithBalance(donor);
201 const notSponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);181 const notSponsor = await helper.eth.createAccountWithBalance(donor);
202 const flipper = await deployFlipper(web3, owner);182 const helpers = helper.ethNativeContract.contractHelpers(owner);
203 const helpers = contractHelpers(web3, owner);183 const flipper = await helper.eth.deployFlipper(owner);
184
204 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;185 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
205 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;186 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;
206 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPermission');187 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPermission');
207 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;188 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
208 });189 });
209190
210 itWeb3('Sponsorship can not be confirmed by the address that not set as sponsor', async ({api, web3, privateKeyWrapper}) => {191 itEth('Sponsorship can not be confirmed by the address that not set as sponsor', async ({helper}) => {
211 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);192 const owner = await helper.eth.createAccountWithBalance(donor);
212 const notSponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);193 const notSponsor = await helper.eth.createAccountWithBalance(donor);
213 const flipper = await deployFlipper(web3, owner);194 const helpers = helper.ethNativeContract.contractHelpers(owner);
214 const helpers = contractHelpers(web3, owner);195 const flipper = await helper.eth.deployFlipper(owner);
196
215 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;197 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
216 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPendingSponsor');198 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPendingSponsor');
217 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;199 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
218 });200 });
219201
220 itWeb3('Get self sponsored sponsor', async ({api, web3, privateKeyWrapper}) => {202 itEth('Get self sponsored sponsor', async ({helper}) => {
221 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);203 const owner = await helper.eth.createAccountWithBalance(donor);
222 const flipper = await deployFlipper(web3, owner);204 const helpers = helper.ethNativeContract.contractHelpers(owner);
223 const helpers = contractHelpers(web3, owner);205 const flipper = await helper.eth.deployFlipper(owner);
206
224 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();207 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();
225 208
229 expect(result[1]).to.be.eq('0');212 expect(result[1]).to.be.eq('0');
230 });213 });
231214
232 itWeb3('Get confirmed sponsor', async ({api, web3, privateKeyWrapper}) => {215 itEth('Get confirmed sponsor', async ({helper}) => {
233 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);216 const owner = await helper.eth.createAccountWithBalance(donor);
234 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);217 const sponsor = await helper.eth.createAccountWithBalance(donor);
235 const flipper = await deployFlipper(web3, owner);218 const helpers = helper.ethNativeContract.contractHelpers(owner);
236 const helpers = contractHelpers(web3, owner);219 const flipper = await helper.eth.deployFlipper(owner);
220
237 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();221 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
238 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});222 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});
243 expect(result[1]).to.be.eq('0');227 expect(result[1]).to.be.eq('0');
244 });228 });
245229
246 itWeb3('Sponsor can be removed by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {230 itEth('Sponsor can be removed by the address that deployed the contract', async ({helper}) => {
247 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);231 const owner = await helper.eth.createAccountWithBalance(donor);
248 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);232 const sponsor = await helper.eth.createAccountWithBalance(donor);
249 const flipper = await deployFlipper(web3, owner);233 const helpers = helper.ethNativeContract.contractHelpers(owner);
250 const helpers = contractHelpers(web3, owner);234 const flipper = await helper.eth.deployFlipper(owner);
251235
252 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;236 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
253 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();237 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
258 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;242 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
259 });243 });
260244
261 itWeb3('Remove sponsor event', async ({api, web3, privateKeyWrapper}) => {245 itEth('Remove sponsor event', async ({helper}) => {
262 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);246 const owner = await helper.eth.createAccountWithBalance(donor);
263 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);247 const sponsor = await helper.eth.createAccountWithBalance(donor);
264 const flipper = await deployFlipper(web3, owner);248 const helpers = helper.ethNativeContract.contractHelpers(owner);
265 const helpers = contractHelpers(web3, owner);249 const flipper = await helper.eth.deployFlipper(owner);
266250
267 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();251 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
268 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});252 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});
269 253
270 const result = await helpers.methods.removeSponsor(flipper.options.address).send();254 const result = await helpers.methods.removeSponsor(flipper.options.address).send();
271 const events = normalizeEvents(result.events);255 const events = helper.eth.normalizeEvents(result.events);
272 expect(events).to.be.deep.equal([256 expect(events).to.be.deep.equal([
273 {257 {
274 address: flipper.options.address,258 address: flipper.options.address,
278 },262 },
279 },263 },
280 ]);264 ]);
281
282 await expectSubstrateEventsAtBlock(
283 api,
284 result.blockNumber,
285 'evmContractHelpers',
286 ['ContractSponsorRemoved'],
287 );
288 });265 });
289266
290 itWeb3('Sponsor can not be removed by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {267 itEth('Sponsor can not be removed by the address that did not deployed the contract', async ({helper}) => {
291 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);268 const owner = await helper.eth.createAccountWithBalance(donor);
292 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);269 const notOwner = await helper.eth.createAccountWithBalance(donor);
293 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);270 const sponsor = await helper.eth.createAccountWithBalance(donor);
294 const flipper = await deployFlipper(web3, owner);271 const helpers = helper.ethNativeContract.contractHelpers(owner);
295 const helpers = contractHelpers(web3, owner);272 const flipper = await helper.eth.deployFlipper(owner);
296273
297 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;274 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;
298 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();275 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
303 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;280 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;
304 });281 });
305282
306 itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3, privateKeyWrapper}) => {283 itEth('In generous mode, non-allowlisted user transaction will be sponsored', async ({helper}) => {
307 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);284 const owner = await helper.eth.createAccountWithBalance(donor);
285 const sponsor = await helper.eth.createAccountWithBalance(donor);
308 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);286 const caller = await helper.eth.createAccountWithBalance(donor);
287 const helpers = helper.ethNativeContract.contractHelpers(owner);
309 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);288 const flipper = await helper.eth.deployFlipper(owner);
310289
311 const flipper = await deployFlipper(web3, owner);
312
313 const helpers = contractHelpers(web3, owner);
314
315 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();290 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
316 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});291 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});
317292
318 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});293 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});
319 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});294 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
320295
321 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);296 const sponsorBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));
322 const callerBalanceBefore = await ethBalanceViaSub(api, caller);297 const callerBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));
323298
324 await flipper.methods.flip().send({from: caller});299 await flipper.methods.flip().send({from: caller});
325 expect(await flipper.methods.getValue().call()).to.be.true;300 expect(await flipper.methods.getValue().call()).to.be.true;
326301
327 // Balance should be taken from sponsor instead of caller302 // Balance should be taken from sponsor instead of caller
328 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);303 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));
329 const callerBalanceAfter = await ethBalanceViaSub(api, caller);304 const callerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));
330 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;305 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
331 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);306 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);
332 });307 });
333308
334 itWeb3('In generous mode, non-allowlisted user transaction will be self sponsored', async ({api, web3, privateKeyWrapper}) => {309 itEth('In generous mode, non-allowlisted user transaction will be self sponsored', async ({helper}) => {
335 const alice = privateKeyWrapper('//Alice');310 const owner = await helper.eth.createAccountWithBalance(donor);
311 const caller = await helper.eth.createAccountWithBalance(donor);
312 const helpers = helper.ethNativeContract.contractHelpers(owner);
313 const flipper = await helper.eth.deployFlipper(owner);
336314
337 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
338 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
339
340 const flipper = await deployFlipper(web3, owner);
341
342 const helpers = contractHelpers(web3, owner);
343
344 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();315 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();
345316
346 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});317 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});
347 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});318 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
348319
349 await transferBalanceToEth(api, alice, flipper.options.address);320 await helper.eth.transferBalanceFromSubstrate(donor, flipper.options.address);
350321
351 const contractBalanceBefore = await ethBalanceViaSub(api, flipper.options.address);322 const contractBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(flipper.options.address));
352 const callerBalanceBefore = await ethBalanceViaSub(api, caller);323 const callerBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));
353324
354 await flipper.methods.flip().send({from: caller});325 await flipper.methods.flip().send({from: caller});
355 expect(await flipper.methods.getValue().call()).to.be.true;326 expect(await flipper.methods.getValue().call()).to.be.true;
356327
357 // Balance should be taken from sponsor instead of caller328 // Balance should be taken from sponsor instead of caller
358 const contractBalanceAfter = await ethBalanceViaSub(api, flipper.options.address);329 const contractBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(flipper.options.address));
359 const callerBalanceAfter = await ethBalanceViaSub(api, caller);330 const callerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));
360 expect(contractBalanceAfter < contractBalanceBefore).to.be.true;331 expect(contractBalanceAfter < contractBalanceBefore).to.be.true;
361 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);332 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);
362 });333 });
363334
364 itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should decrease (allowlisted)', async ({api, web3, privateKeyWrapper}) => {335 itEth('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should decrease (allowlisted)', async ({helper}) => {
365 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);336 const owner = await helper.eth.createAccountWithBalance(donor);
366 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);337 const sponsor = await helper.eth.createAccountWithBalance(donor);
338 const caller = helper.eth.createAccount();
367 const caller = createEthAccount(web3);339 const helpers = helper.ethNativeContract.contractHelpers(owner);
340 const flipper = await helper.eth.deployFlipper(owner);
368341
369 const flipper = await deployFlipper(web3, owner);
370
371 const helpers = contractHelpers(web3, owner);
372 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});342 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});
373 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});343 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
374344
378 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();348 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
379 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});349 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});
380350
381 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);351 const sponsorBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));
382 expect(sponsorBalanceBefore).to.be.not.equal('0');352 expect(sponsorBalanceBefore).to.be.not.equal('0');
383353
384 await flipper.methods.flip().send({from: caller});354 await flipper.methods.flip().send({from: caller});
385 expect(await flipper.methods.getValue().call()).to.be.true;355 expect(await flipper.methods.getValue().call()).to.be.true;
386356
387 // Balance should be taken from flipper instead of caller357 // Balance should be taken from flipper instead of caller
388 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);358 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));
389 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;359 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
390 });360 });
391361
392 itWeb3('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should not decrease (non-allowlisted)', async ({api, web3, privateKeyWrapper}) => {362 itEth('Sponsoring is set, an address that has no UNQ can send a transaction and it works. Sponsor balance should not decrease (non-allowlisted)', async ({helper}) => {
393 const alice = privateKeyWrapper('//Alice');363 const owner = await helper.eth.createAccountWithBalance(donor);
364 const caller = await helper.eth.createAccount();
365 const helpers = helper.ethNativeContract.contractHelpers(owner);
366 const flipper = await helper.eth.deployFlipper(owner);
394367
395 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
396 const caller = createEthAccount(web3);
397
398 const flipper = await deployFlipper(web3, owner);
399
400 const helpers = contractHelpers(web3, owner);
401
402 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});368 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});
403 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});369 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
404370
405 await transferBalanceToEth(api, alice, flipper.options.address);371 await helper.eth.transferBalanceFromSubstrate(donor, flipper.options.address);
406372
407 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);373 const originalFlipperBalance = await helper.balance.getEthereum(flipper.options.address);
408 expect(originalFlipperBalance).to.be.not.equal('0');374 expect(originalFlipperBalance).to.be.not.equal('0');
409375
410 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);376 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);
411 expect(await flipper.methods.getValue().call()).to.be.false;377 expect(await flipper.methods.getValue().call()).to.be.false;
412378
413 // Balance should be taken from flipper instead of caller379 // Balance should be taken from flipper instead of caller
414 const balanceAfter = await web3.eth.getBalance(flipper.options.address);380 // FIXME the comment is wrong! What check should be here?
381 const balanceAfter = await helper.balance.getEthereum(flipper.options.address);
415 expect(+balanceAfter).to.be.equals(+originalFlipperBalance);382 expect(balanceAfter).to.be.equals(originalFlipperBalance);
416 });383 });
417384
418 itWeb3('Sponsoring is set, an address that has UNQ can send a transaction and it works. User balance should not change', async ({api, web3, privateKeyWrapper}) => {385 itEth('Sponsoring is set, an address that has UNQ can send a transaction and it works. User balance should not change', async ({helper}) => {
419 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);386 const owner = await helper.eth.createAccountWithBalance(donor);
387 const sponsor = await helper.eth.createAccountWithBalance(donor);
420 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);388 const caller = await helper.eth.createAccountWithBalance(donor);
389 const helpers = helper.ethNativeContract.contractHelpers(owner);
421 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);390 const flipper = await helper.eth.deployFlipper(owner);
422391
423 const flipper = await deployFlipper(web3, owner);
424
425 const helpers = contractHelpers(web3, owner);
426 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});392 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});
427 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});393 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
428394
432 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();398 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
433 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});399 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});
434400
435 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);401 const sponsorBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));
436 const callerBalanceBefore = await ethBalanceViaSub(api, caller);402 const callerBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));
437403
438 await flipper.methods.flip().send({from: caller});404 await flipper.methods.flip().send({from: caller});
439 expect(await flipper.methods.getValue().call()).to.be.true;405 expect(await flipper.methods.getValue().call()).to.be.true;
440406
441 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);407 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));
442 const callerBalanceAfter = await ethBalanceViaSub(api, caller);408 const callerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));
443 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;409 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
444 expect(callerBalanceAfter).to.be.equals(callerBalanceBefore);410 expect(callerBalanceAfter).to.be.equals(callerBalanceBefore);
445 });411 });
446412
447 itWeb3('Sponsoring is limited, with setContractRateLimit. The limitation is working if transactions are sent more often, the sender pays the commission.', async ({api, web3, privateKeyWrapper}) => {413 itEth('Sponsoring is limited, with setContractRateLimit. The limitation is working if transactions are sent more often, the sender pays the commission.', async ({helper}) => {
448 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);414 const owner = await helper.eth.createAccountWithBalance(donor);
449 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);415 const sponsor = await helper.eth.createAccountWithBalance(donor);
450 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);416 const caller = await helper.eth.createAccountWithBalance(donor);
451 const originalCallerBalance = await web3.eth.getBalance(caller);417 const helpers = helper.ethNativeContract.contractHelpers(owner);
452
453 const flipper = await deployFlipper(web3, owner);418 const flipper = await helper.eth.deployFlipper(owner);
454419
455 const helpers = contractHelpers(web3, owner);420 const originalCallerBalance = await helper.balance.getEthereum(caller);
456 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});421 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});
457 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});422 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
458423
462 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();427 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();
463 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});428 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});
464429
465 const originalFlipperBalance = await web3.eth.getBalance(sponsor);430 const originalFlipperBalance = await helper.balance.getEthereum(sponsor);
466 expect(originalFlipperBalance).to.be.not.equal('0');431 expect(originalFlipperBalance).to.be.not.equal('0');
467432
468 await flipper.methods.flip().send({from: caller});433 await flipper.methods.flip().send({from: caller});
469 expect(await flipper.methods.getValue().call()).to.be.true;434 expect(await flipper.methods.getValue().call()).to.be.true;
470 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);435 expect(await helper.balance.getEthereum(caller)).to.be.equals(originalCallerBalance);
471436
472 const newFlipperBalance = await web3.eth.getBalance(sponsor);437 const newFlipperBalance = await helper.balance.getEthereum(sponsor);
473 expect(newFlipperBalance).to.be.not.equals(originalFlipperBalance);438 expect(newFlipperBalance).to.be.not.equals(originalFlipperBalance);
474439
475 await flipper.methods.flip().send({from: caller});440 await flipper.methods.flip().send({from: caller});
476 expect(await web3.eth.getBalance(sponsor)).to.be.equal(newFlipperBalance);441 expect(await helper.balance.getEthereum(sponsor)).to.be.equal(newFlipperBalance);
477 expect(await web3.eth.getBalance(caller)).to.be.not.equals(originalCallerBalance);442 expect(await helper.balance.getEthereum(caller)).to.be.not.equals(originalCallerBalance);
478 });443 });
479444
480 // TODO: Find a way to calculate default rate limit445 // TODO: Find a way to calculate default rate limit
481 itWeb3('Default rate limit equals 7200', async ({api, web3, privateKeyWrapper}) => {446 itEth('Default rate limit equals 7200', async ({helper}) => {
482 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);447 const owner = await helper.eth.createAccountWithBalance(donor);
483 const flipper = await deployFlipper(web3, owner);448 const helpers = helper.ethNativeContract.contractHelpers(owner);
484 const helpers = contractHelpers(web3, owner);449 const flipper = await helper.eth.deployFlipper(owner);
450
485 expect(await helpers.methods.sponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');451 expect(await helpers.methods.sponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');
486 });452 });
487});453});
488454
489describe('Sponsoring Fee Limit', () => {455describe('Sponsoring Fee Limit', () => {
456 let donor: IKeyringPair;
457 let alice: IKeyringPair;
458 let DEFAULT_GAS: number;
490459
491 let testContract: CompiledContract;
492
493 function compileTestContract() {460 function compileTestContract() {
494 if (!testContract) {461 if (!testContract) {
495 const input = {462 const input = {
537 return testContract;504 return testContract;
538 }505 }
539 506
540 async function deployTestContract(web3: Web3, owner: string) {507 async function deployTestContract(helper: EthUniqueHelper, owner: string) {
508 const web3 = helper.getWeb3();
541 const compiled = compileTestContract();509 const compiled = compileTestContract();
542 const testContract = new web3.eth.Contract(compiled.abi, undefined, {510 const testContract = new web3.eth.Contract(compiled.abi, undefined, {
543 data: compiled.object,511 data: compiled.object,
544 from: owner,512 from: owner,
545 ...GAS_ARGS,513 gas: DEFAULT_GAS,
546 });514 });
547 return await testContract.deploy({data: compiled.object}).send({from: owner});515 return await testContract.deploy({data: compiled.object}).send({from: owner});
548 }516 }
549517
550 itWeb3('Default fee limit', async ({api, web3, privateKeyWrapper}) => {518 before(async () => {
519 await usingEthPlaygrounds(async (helper, privateKey) => {
520 donor = privateKey('//Alice');
521 DEFAULT_GAS = helper.eth.DEFAULT_GAS;
522 });
523 });
524
525 beforeEach(async () => {
551 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);526 await usingPlaygrounds(async (helper) => {
527 [alice] = await helper.arrange.createAccounts([1000n], donor);
528 });
552 const flipper = await deployFlipper(web3, owner);529 });
530
531 let testContract: CompiledContract;
532
533
534
535 itEth('Default fee limit', async ({helper}) => {
536 const owner = await helper.eth.createAccountWithBalance(donor);
553 const helpers = contractHelpers(web3, owner);537 const helpers = helper.ethNativeContract.contractHelpers(owner);
538 const flipper = await helper.eth.deployFlipper(owner);
539
554 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equals('115792089237316195423570985008687907853269984665640564039457584007913129639935');540 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equals('115792089237316195423570985008687907853269984665640564039457584007913129639935');
555 });541 });
556542
557 itWeb3('Set fee limit', async ({api, web3, privateKeyWrapper}) => {543 itEth('Set fee limit', async ({helper}) => {
558 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);544 const owner = await helper.eth.createAccountWithBalance(donor);
559 const flipper = await deployFlipper(web3, owner);545 const helpers = helper.ethNativeContract.contractHelpers(owner);
560 const helpers = contractHelpers(web3, owner);546 const flipper = await helper.eth.deployFlipper(owner);
547
561 await helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send();548 await helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send();
562 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equals('100');549 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equals('100');
563 });550 });
564551
565 itWeb3('Negative test - set fee limit by non-owner', async ({api, web3, privateKeyWrapper}) => {552 itEth('Negative test - set fee limit by non-owner', async ({helper}) => {
566 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);553 const owner = await helper.eth.createAccountWithBalance(donor);
567 const stranger = await createEthAccountWithBalance(api, web3, privateKeyWrapper);554 const stranger = await helper.eth.createAccountWithBalance(donor);
568 const flipper = await deployFlipper(web3, owner);555 const helpers = helper.ethNativeContract.contractHelpers(owner);
569 const helpers = contractHelpers(web3, owner);556 const flipper = await helper.eth.deployFlipper(owner);
557
570 await expect(helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send({from: stranger})).to.be.rejected;558 await expect(helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send({from: stranger})).to.be.rejected;
571 });559 });
572560
573 itWeb3('Negative test - check that eth transactions exceeding fee limit are not executed', async ({api, web3, privateKeyWrapper}) => {561 itEth('Negative test - check that eth transactions exceeding fee limit are not executed', async ({helper}) => {
574 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);562 const owner = await helper.eth.createAccountWithBalance(donor);
575 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);563 const sponsor = await helper.eth.createAccountWithBalance(donor);
576 const user = await createEthAccountWithBalance(api, web3, privateKeyWrapper);564 const user = await helper.eth.createAccountWithBalance(donor);
565 const helpers = helper.ethNativeContract.contractHelpers(owner);
577566
578 const testContract = await deployTestContract(web3, owner);567 const testContract = await deployTestContract(helper, owner);
579 const helpers = contractHelpers(web3, owner);
580 568
581 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});569 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});
582 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});570 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});
583 571
584 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();572 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();
585 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});573 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});
586574
587 const gasPrice = BigInt(await web3.eth.getGasPrice());575 const gasPrice = BigInt(await helper.getWeb3().eth.getGasPrice());
588576
589 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();577 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();
590578
591 const originalUserBalance = await web3.eth.getBalance(user);579 const originalUserBalance = await helper.balance.getEthereum(user);
592 await testContract.methods.test(100).send({from: user, gas: 2_000_000});580 await testContract.methods.test(100).send({from: user, gas: 2_000_000});
593 expect(await web3.eth.getBalance(user)).to.be.equal(originalUserBalance);581 expect(await helper.balance.getEthereum(user)).to.be.equal(originalUserBalance);
594582
595 await testContract.methods.test(100).send({from: user, gas: 2_100_000});583 await testContract.methods.test(100).send({from: user, gas: 2_100_000});
596 expect(await web3.eth.getBalance(user)).to.not.be.equal(originalUserBalance);584 expect(await helper.balance.getEthereum(user)).to.not.be.equal(originalUserBalance);
597 });585 });
598586
599 itWeb3('Negative test - check that evm.call transactions exceeding fee limit are not executed', async ({api, web3, privateKeyWrapper}) => {587 itEth('Negative test - check that evm.call transactions exceeding fee limit are not executed', async ({helper, privateKey}) => {
600 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);588 const owner = await helper.eth.createAccountWithBalance(donor);
601 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);589 const sponsor = await helper.eth.createAccountWithBalance(donor);
590 const helpers = helper.ethNativeContract.contractHelpers(owner);
602591
603 const testContract = await deployTestContract(web3, owner);592 const testContract = await deployTestContract(helper, owner);
604 const helpers = contractHelpers(web3, owner);
605 593
606 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});594 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});
607 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});595 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});
608 596
609 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();597 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();
610 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});598 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});
611599
612 const gasPrice = BigInt(await web3.eth.getGasPrice());600 const gasPrice = BigInt(await helper.getWeb3().eth.getGasPrice());
613601
614 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();602 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();
615603
616 const alice = privateKeyWrapper('//Alice');604 const originalAliceBalance = await helper.balance.getSubstrate(alice.address);
617 const originalAliceBalance = (await api.query.system.account(alice.address)).data.free.toBigInt();605
618
619 await submitTransactionAsync(606 await helper.eth.sendEVM(
620 alice,607 alice,
621 api.tx.evm.call(608 testContract.options.address,
622 subToEth(alice.address),
623 testContract.options.address,
624 testContract.methods.test(100).encodeABI(),609 testContract.methods.test(100).encodeABI(),
625 Uint8Array.from([]),610 '0',
626 2_000_000n,611 2_000_000,
627 gasPrice,
628 null,
629 null,
630 [],
631 ),
632 );612 );
633 expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.be.equal(originalAliceBalance);613 // expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.be.equal(originalAliceBalance);
614 expect(await helper.balance.getSubstrate(alice.address)).to.be.equal(originalAliceBalance);
634 615
635 await submitTransactionAsync(616 await helper.eth.sendEVM(
636 alice,617 alice,
637 api.tx.evm.call(618 testContract.options.address,
638 subToEth(alice.address),
639 testContract.options.address,
640 testContract.methods.test(100).encodeABI(),619 testContract.methods.test(100).encodeABI(),
641 Uint8Array.from([]),620 '0',
642 2_100_000n,621 2_100_000,
643 gasPrice,
644 null,
645 null,
646 [],
647 ),
648 );622 );
649 expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.not.be.equal(originalAliceBalance);623 expect(await helper.balance.getSubstrate(alice.address)).to.not.be.equal(originalAliceBalance);
650 });624 });
651});625});
652626
modifiedtests/src/eth/scheduling.test.tsdiffbeforeafterboth
--- a/tests/src/eth/scheduling.test.ts
+++ b/tests/src/eth/scheduling.test.ts
@@ -18,7 +18,8 @@
 import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';
 import {scheduleExpectSuccess, waitNewBlocks, requirePallets, Pallets} from '../util/helpers';
 
-describe('Scheduing EVM smart contracts', () => {
+// TODO mrshiposha update this test in #581
+describe.skip('Scheduing EVM smart contracts', () => {
   before(async function() {
     await requirePallets(this, [Pallets.Scheduler]);
   });
modifiedtests/src/eth/sponsoring.test.tsdiffbeforeafterboth
--- a/tests/src/eth/sponsoring.test.ts
+++ b/tests/src/eth/sponsoring.test.ts
@@ -14,20 +14,31 @@
 // You should have received a copy of the GNU General Public License
 // along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
 
-import {expect} from 'chai';
-import {contractHelpers, createEthAccount, createEthAccountWithBalance, deployCollector, deployFlipper, itWeb3, SponsoringMode} from './util/helpers';
+import {IKeyringPair} from '@polkadot/types/types';
+import {itEth, expect, SponsoringMode} from '../eth/util/playgrounds';
+import {usingPlaygrounds} from './../util/playgrounds/index';
 
 describe('EVM sponsoring', () => {
-  itWeb3('Fee is deducted from contract if sponsoring is enabled', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const caller = createEthAccount(web3);
-    const originalCallerBalance = await web3.eth.getBalance(caller);
-    expect(originalCallerBalance).to.be.equal('0');
+  let donor: IKeyringPair;
 
-    const flipper = await deployFlipper(web3, owner);
+  before(async () => {
+    await usingPlaygrounds(async (helper, privateKey) => {
+      donor = privateKey('//Alice');
+    });
+  });
+
+  itEth('Fee is deducted from contract if sponsoring is enabled', async ({helper}) => {
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const sponsor = await helper.eth.createAccountWithBalance(donor);
+    const caller = helper.eth.createAccount();
+    const originalCallerBalance = await helper.balance.getEthereum(caller);
+
+    expect(originalCallerBalance).to.be.equal(0n);
+
+    const flipper = await helper.eth.deployFlipper(owner);
+
+    const helpers = helper.ethNativeContract.contractHelpers(owner);
 
-    const helpers = contractHelpers(web3, owner);
     await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});
     await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
     
@@ -39,27 +50,29 @@
     await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
     expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
 
-    const originalSponsorBalance = await web3.eth.getBalance(sponsor);
-    expect(originalSponsorBalance).to.be.not.equal('0');
+    const originalSponsorBalance = await helper.balance.getEthereum(sponsor);
+    expect(originalSponsorBalance).to.be.not.equal(0n);
 
     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
-    expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);
-    expect(await web3.eth.getBalance(sponsor)).to.be.not.equals(originalSponsorBalance);
+    expect(await helper.balance.getEthereum(caller)).to.be.equal(originalCallerBalance);
+    expect(await helper.balance.getEthereum(sponsor)).to.be.not.equal(originalSponsorBalance);
   });
 
-  itWeb3('...but this doesn\'t applies to payable value', async ({api, web3, privateKeyWrapper}) => {
-    const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const originalCallerBalance = await web3.eth.getBalance(caller);
-    expect(originalCallerBalance).to.be.not.equal('0');
+  itEth('...but this doesn\'t applies to payable value', async ({helper}) => {
+    const owner = await helper.eth.createAccountWithBalance(donor);
+    const sponsor = await helper.eth.createAccountWithBalance(donor);
+    const caller = await helper.eth.createAccountWithBalance(donor);
+    const originalCallerBalance = await helper.balance.getEthereum(caller);
+
+    expect(originalCallerBalance).to.be.not.equal(0n);
+
+    const collector = await helper.eth.deployCollectorContract(owner);
 
-    const collector = await deployCollector(web3, owner);
+    const helpers = helper.ethNativeContract.contractHelpers(owner);
 
-    const helpers = contractHelpers(web3, owner);
     await helpers.methods.toggleAllowlist(collector.options.address, true).send({from: owner});
     await helpers.methods.toggleAllowed(collector.options.address, caller, true).send({from: owner});
 
@@ -71,14 +84,14 @@
     await helpers.methods.setSponsor(collector.options.address, sponsor).send({from: owner});
     await helpers.methods.confirmSponsorship(collector.options.address).send({from: sponsor});
 
-    const originalSponsorBalance = await web3.eth.getBalance(sponsor);
-    expect(originalSponsorBalance).to.be.not.equal('0');
+    const originalSponsorBalance = await helper.balance.getEthereum(sponsor);
+    expect(originalSponsorBalance).to.be.not.equal(0n);
 
     await collector.methods.giveMoney().send({from: caller, value: '10000'});
 
     // Balance will be taken from both caller (value) and from collector (fee)
-    expect(await web3.eth.getBalance(caller)).to.be.equals((BigInt(originalCallerBalance) - 10000n).toString());
-    expect(await web3.eth.getBalance(sponsor)).to.be.not.equals(originalSponsorBalance);
+    expect(await helper.balance.getEthereum(caller)).to.be.equals((originalCallerBalance - 10000n));
+    expect(await helper.balance.getEthereum(sponsor)).to.be.not.equals(originalSponsorBalance);
     expect(await collector.methods.getCollected().call()).to.be.equal('10000');
   });
 });
modifiedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
--- a/tests/src/eth/tokenProperties.test.ts
+++ b/tests/src/eth/tokenProperties.test.ts
@@ -1,94 +1,119 @@
-import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess} from '../util/helpers';
-import {cartesian, collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3} from './util/helpers';
-import nonFungibleAbi from './nonFungibleAbi.json';
-import {expect} from 'chai';
-import {executeTransaction} from '../substrate/substrate-api';
+import {IKeyringPair} from '@polkadot/types/types';
+import {usingPlaygrounds} from './../util/playgrounds/index';
+import {itEth, expect} from '../eth/util/playgrounds';
 
 describe('EVM token properties', () => {
-  itWeb3('Can be reconfigured', async({web3, api, privateKeyWrapper}) => {
-    const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+  let donor: IKeyringPair;
+  let alice: IKeyringPair;
+
+  before(async () => {
+    await usingPlaygrounds(async (helper, privateKey) => {
+      donor = privateKey('//Alice');
+      [alice] = await helper.arrange.createAccounts([1000n], donor);
+    });
+  });
+
+  itEth('Can be reconfigured', async({helper}) => {
+    const caller = await helper.eth.createAccountWithBalance(donor);
+
     for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {
-      const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-      await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
-      
-      const address = collectionIdToAddress(collection);
-      const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
-  
+      const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'ethp'});
+      await collection.addAdmin(alice, {Ethereum: caller});
+
+      const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+      const contract = helper.ethNativeContract.collection(address, 'nft', caller);
+
       await contract.methods.setTokenPropertyPermission('testKey', mutable, collectionAdmin, tokenOwner).send({from: caller});
   
-      const state = (await api.query.common.collectionPropertyPermissions(collection)).toJSON();
-      expect(state).to.be.deep.equal({
-        [web3.utils.toHex('testKey')]: {mutable, collectionAdmin, tokenOwner},
-      });
+      const state = await collection.getPropertyPermissions();
+      expect(state).to.be.deep.equal([{
+        key: 'testKey',
+        permission: {mutable, collectionAdmin, tokenOwner},
+      }]);
     }
   });
-  itWeb3('Can be set', async({web3, api, privateKeyWrapper}) => {
-    const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-    const token = await createItemExpectSuccess(alice, collection, 'NFT');
 
-    await executeTransaction(api, alice, api.tx.unique.setTokenPropertyPermissions(collection, [{
-      key: 'testKey',
-      permission: {
-        collectionAdmin: true,
-      },
-    }]));
+  itEth('Can be set', async({helper}) => {
+    const caller = await helper.eth.createAccountWithBalance(donor);
+    const collection = await helper.nft.mintCollection(alice, {
+      tokenPrefix: 'ethp',
+      tokenPropertyPermissions: [{
+        key: 'testKey',
+        permission: {
+          collectionAdmin: true,
+        },
+      }],
+    });
+    const token = await collection.mintToken(alice);
 
-    await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
+    await collection.addAdmin(alice, {Ethereum: caller});
 
-    const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'nft', caller);
 
-    await contract.methods.setProperty(token, 'testKey', Buffer.from('testValue')).send({from: caller});
+    await contract.methods.setProperty(token.tokenId, 'testKey', Buffer.from('testValue')).send({from: caller});
 
-    const [{value}] = (await api.rpc.unique.tokenProperties(collection, token, ['testKey'])).toHuman()! as any;
+    const [{value}] = await token.getProperties(['testKey']);
     expect(value).to.equal('testValue');
   });
-  itWeb3('Can be deleted', async({web3, api, privateKeyWrapper}) => {
-    const alice = privateKeyWrapper('//Alice');
-    const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
-    const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
-    const token = await createItemExpectSuccess(alice, collection, 'NFT');
 
-    await executeTransaction(api, alice, api.tx.unique.setTokenPropertyPermissions(collection, [{
-      key: 'testKey',
-      permission: {
-        mutable: true,
-        collectionAdmin: true,
-      },
-    }]));
-    await executeTransaction(api, alice, api.tx.unique.setTokenProperties(collection, token, [{key: 'testKey', value: 'testValue'}]));
+  itEth('Can be deleted', async({helper}) => {
+    const caller = await helper.eth.createAccountWithBalance(donor);
+    const collection = await helper.nft.mintCollection(alice, {
+      tokenPrefix: 'ethp',
+      tokenPropertyPermissions: [{
+        key: 'testKey',
+        permission: {
+          mutable: true,
+          collectionAdmin: true,
+        },
+      }],
+    });
+
+    await collection.addAdmin(alice, {Ethereum: caller});
 
-    await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});
+    const token = await collection.mintToken(alice);
+    await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]);
 
-    const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'nft', caller);
 
-    await contract.methods.deleteProperty(token, 'testKey').send({from: caller});
+    await contract.methods.deleteProperty(token.tokenId, 'testKey').send({from: caller});
 
-    const result = (await api.rpc.unique.tokenProperties(collection, token, ['testKey'])).toJSON()! as any;
+    const result = await token.getProperties(['testKey']);
     expect(result.length).to.equal(0);
   });
-  itWeb3('Can be read', async({web3, api, privateKeyWrapper}) => {
-    const alice = privateKeyWrapper('//Alice');
-    const caller = createEthAccount(web3);
-    const collection = await createCollectionExpectSuccess({mode: {type:'NFT'}});
-    const token = await createItemExpectSuccess(alice, collection, 'NFT');
 
-    await executeTransaction(api, alice, api.tx.unique.setTokenPropertyPermissions(collection, [{
-      key: 'testKey',
-      permission: {
-        collectionAdmin: true,
-      },
-    }]));
-    await executeTransaction(api, alice, api.tx.unique.setTokenProperties(collection, token, [{key: 'testKey', value: 'testValue'}]));
+  itEth('Can be read', async({helper}) => {
+    const caller = await helper.eth.createAccountWithBalance(donor);
+    const collection = await helper.nft.mintCollection(alice, {
+      tokenPrefix: 'ethp',
+      tokenPropertyPermissions: [{
+        key: 'testKey',
+        permission: {
+          collectionAdmin: true,
+        },
+      }],
+    });
+    const token = await collection.mintToken(alice);
+    await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]);
 
-    const address = collectionIdToAddress(collection);
-    const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});
+    const address = helper.ethAddress.fromCollectionId(collection.collectionId);
+    const contract = helper.ethNativeContract.collection(address, 'nft', caller);
 
-    const value = await contract.methods.property(token, 'testKey').call();
-    expect(value).to.equal(web3.utils.toHex('testValue'));
+    const value = await contract.methods.property(token.tokenId, 'testKey').call();
+    expect(value).to.equal(helper.getWeb3().utils.toHex('testValue'));
   });
 });
+
+
+type ElementOf<A> = A extends readonly (infer T)[] ? T : never;
+function* cartesian<T extends Array<Array<any>>, R extends Array<any>>(internalRest: [...R], ...args: [...T]): Generator<[...R, ...{[K in keyof T]: ElementOf<T[K]>}]> {
+  if(args.length === 0) {
+    yield internalRest as any;
+    return;
+  }
+  for(const value of args[0]) {
+    yield* cartesian([...internalRest, value], ...args.slice(1)) as any;
+  }
+}
\ No newline at end of file
modifiedtests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth
--- a/tests/src/eth/util/playgrounds/types.ts
+++ b/tests/src/eth/util/playgrounds/types.ts
@@ -6,4 +6,10 @@
 export interface CompiledContract {
   abi: any;
   object: string;
-}
\ No newline at end of file
+}
+
+export type NormalizedEvent = {
+  address: string,
+  event: string,
+  args: { [key: string]: string }
+};
modifiedtests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth
--- a/tests/src/eth/util/playgrounds/unique.dev.ts
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -18,7 +18,7 @@
 
 import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';
 
-import {ContractImports, CompiledContract} from './types';
+import {ContractImports, CompiledContract, NormalizedEvent} from './types';
 
 // Native contracts ABI
 import collectionHelpersAbi from '../../collectionHelpersAbi.json';
@@ -252,6 +252,33 @@
 
     return before - after;
   }
+
+  normalizeEvents(events: any): NormalizedEvent[] {
+    const output = [];
+    for (const key of Object.keys(events)) {
+      if (key.match(/^[0-9]+$/)) {
+        output.push(events[key]);
+      } else if (Array.isArray(events[key])) {
+        output.push(...events[key]);
+      } else {
+        output.push(events[key]);
+      }
+    }
+    output.sort((a, b) => a.logIndex - b.logIndex);
+    return output.map(({address, event, returnValues}) => {
+      const args: { [key: string]: string } = {};
+      for (const key of Object.keys(returnValues)) {
+        if (!key.match(/^[0-9]+$/)) {
+          args[key] = returnValues[key];
+        }
+      }
+      return {
+        address,
+        event,
+        args,
+      };
+    });
+  }
 }  
 
 class EthAddressGroup extends EthGroupBase {