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
1import {addToAllowListExpectSuccess, confirmSponsorshipExpectSuccess, createCollectionExpectSuccess, enablePublicMintingExpectSuccess, getDetailedCollectionInfo, setCollectionSponsorExpectSuccess, UNIQUE} from '../util/helpers';1import {IKeyringPair} from '@polkadot/types/types';
2import {itWeb3, createEthAccount, collectionIdToAddress, GAS_ARGS, normalizeEvents, createEthAccountWithBalance, evmCollectionHelpers, getCollectionAddressFromResult, evmCollection, ethBalanceViaSub} from './util/helpers';2import {usingPlaygrounds} from './../util/playgrounds/index';
3import nonFungibleAbi from './nonFungibleAbi.json';
4import {expect} from 'chai';3import {itEth, expect} from '../eth/util/playgrounds';
5import {evmToAddress} from '@polkadot/util-crypto';
64
7describe('evm collection sponsoring', () => {5describe('evm collection sponsoring', () => {
8 itWeb3('sponsors mint transactions', async ({web3, privateKeyWrapper}) => {6 let donor: IKeyringPair;
7 let alice: IKeyringPair;
9 const alice = privateKeyWrapper('//Alice');8 let nominal: bigint;
109
11 const collection = await createCollectionExpectSuccess();10 before(async () => {
11 await usingPlaygrounds(async (helper, privateKey) => {
12 await setCollectionSponsorExpectSuccess(collection, alice.address);12 donor = privateKey('//Alice');
13 nominal = helper.balance.getOneTokenNominal();
13 await confirmSponsorshipExpectSuccess(collection);14 });
15 });
1416
15 const minter = createEthAccount(web3);17 beforeEach(async () => {
18 await usingPlaygrounds(async (helper) => {
16 expect(await web3.eth.getBalance(minter)).to.equal('0');19 [alice] = await helper.arrange.createAccounts([1000n], donor);
20 });
21 });
1722
18 const address = collectionIdToAddress(collection);23 itEth('sponsors mint transactions', async ({helper}) => {
19 const contract = new web3.eth.Contract(nonFungibleAbi as any, collectionIdToAddress(collection), {from: minter, ...GAS_ARGS});24 const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'spnr', permissions: {mintMode: true}});
25 await collection.setSponsor(alice, alice.address);
26 await collection.confirmSponsorship(alice);
2027
21 await enablePublicMintingExpectSuccess(alice, collection);28 const minter = helper.eth.createAccount();
22 await addToAllowListExpectSuccess(alice, collection, {Ethereum: minter});29 expect(await helper.balance.getEthereum(minter)).to.equal(0n);
2330
31 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
32 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', minter);
33
34 await collection.addToAllowList(alice, {Ethereum: minter});
35
24 const nextTokenId = await contract.methods.nextTokenId().call();36 const nextTokenId = await contract.methods.nextTokenId().call();
25 expect(nextTokenId).to.equal('1');37 expect(nextTokenId).to.equal('1');
26 const result = await contract.methods.mint(minter, nextTokenId).send();38 const result = await contract.methods.mint(minter, nextTokenId).send();
27 const events = normalizeEvents(result.events);39 const events = helper.eth.normalizeEvents(result.events);
28 expect(events).to.be.deep.equal([40 expect(events).to.be.deep.equal([
29 {41 {
30 address,42 address: collectionAddress,
31 event: 'Transfer',43 event: 'Transfer',
32 args: {44 args: {
33 from: '0x0000000000000000000000000000000000000000',45 from: '0x0000000000000000000000000000000000000000',
59 // expect(bigIntToSub(api, BigInt(sponsorTuple[1]))).to.be.eq(sponsor.address);71 // expect(bigIntToSub(api, BigInt(sponsorTuple[1]))).to.be.eq(sponsor.address);
60 // });72 // });
6173
62 itWeb3('Remove sponsor', async ({api, web3, privateKeyWrapper}) => {74 itEth('Remove sponsor', async ({helper}) => {
63 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);75 const owner = await helper.eth.createAccountWithBalance(donor);
64 const collectionHelpers = evmCollectionHelpers(web3, owner);76 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
65 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * UNIQUE)});
66 const {collectionIdAddress} = await getCollectionAddressFromResult(api, result);
67 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
68 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
6977
78 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
79 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
80 const sponsor = await helper.eth.createAccountWithBalance(donor);
81 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);
82
70 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;83 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false;
71 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});84 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});
72 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;85 expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;
80 expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');93 expect(sponsorTuple.field_0).to.be.eq('0x0000000000000000000000000000000000000000');
81 });94 });
8295
83 itWeb3('Sponsoring collection from evm address via access list', async ({api, web3, privateKeyWrapper}) => {96 itEth('Sponsoring collection from evm address via access list', async ({helper}) => {
84 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);97 const owner = await helper.eth.createAccountWithBalance(donor);
85 const collectionHelpers = evmCollectionHelpers(web3, owner);98 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
99
86 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * UNIQUE)});100 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
87 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);101 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
102 const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);
103 const collection = helper.nft.getCollectionObject(collectionId);
88 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);104 const sponsor = await helper.eth.createAccountWithBalance(donor);
89 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);105 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);
106
90 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});107 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send({from: owner});
91 let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;108 let collectionData = (await collection.getData())!;
92 const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
93 expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;109 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
94 expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
95 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');110 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
96111
97 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});112 await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
98 collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;113 collectionData = (await collection.getData())!;
99 expect(collectionSub.sponsorship.isConfirmed).to.be.true;114 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
100 expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
101115
102 const user = createEthAccount(web3);116 const user = helper.eth.createAccount();
103 const nextTokenId = await collectionEvm.methods.nextTokenId().call();117 const nextTokenId = await collectionEvm.methods.nextTokenId().call();
104 expect(nextTokenId).to.be.equal('1');118 expect(nextTokenId).to.be.equal('1');
105119
106 const oldPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();120 const oldPermissions = (await collection.getData())!.raw.permissions; // (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
107 expect(oldPermissions.mintMode).to.be.false;121 expect(oldPermissions.mintMode).to.be.false;
108 expect(oldPermissions.access).to.be.equal('Normal');122 expect(oldPermissions.access).to.be.equal('Normal');
109123
110 await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});124 await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});
111 await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});125 await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
112 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});126 await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});
113127
114 const newPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();128 const newPermissions = (await collection.getData())!.raw.permissions; // (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
115 expect(newPermissions.mintMode).to.be.true;129 expect(newPermissions.mintMode).to.be.true;
116 expect(newPermissions.access).to.be.equal('AllowList');130 expect(newPermissions.access).to.be.equal('AllowList');
117131
118 const ownerBalanceBefore = await ethBalanceViaSub(api, owner);132 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
119 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);133 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
120134
121 {135 {
122 const nextTokenId = await collectionEvm.methods.nextTokenId().call();136 const nextTokenId = await collectionEvm.methods.nextTokenId().call();
126 nextTokenId,140 nextTokenId,
127 'Test URI',141 'Test URI',
128 ).send({from: user});142 ).send({from: user});
129 const events = normalizeEvents(result.events);143 const events = helper.eth.normalizeEvents(result.events);
130144
131 expect(events).to.be.deep.equal([145 expect(events).to.be.deep.equal([
132 {146 {
140 },154 },
141 ]);155 ]);
142156
143 const ownerBalanceAfter = await ethBalanceViaSub(api, owner);157 const ownerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(owner));
144 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);158 const sponsorBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(sponsor));
145159
146 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');160 expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
147 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);161 expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);
205 // }219 // }
206 // });220 // });
207221
208 itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3, privateKeyWrapper}) => {222 itEth('Check that transaction via EVM spend money from sponsor address', async ({helper}) => {
209 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);223 const owner = await helper.eth.createAccountWithBalance(donor);
210 const collectionHelpers = evmCollectionHelpers(web3, owner);224 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
225
211 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * UNIQUE)});226 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});
212 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);227 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
228 const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);
229 const collection = helper.nft.getCollectionObject(collectionId);
213 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);230 const sponsor = await helper.eth.createAccountWithBalance(donor);
214 const collectionEvm = evmCollection(web3, owner, collectionIdAddress);231 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);
232
215 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();233 result = await collectionEvm.methods.setCollectionSponsor(sponsor).send();
216 let collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;234 let collectionData = (await collection.getData())!;
217 const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
218 expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;235 expect(collectionData.raw.sponsorship.Unconfirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
219 expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
220 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');236 await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
237
221 const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);238 const sponsorCollection = helper.ethNativeContract.collection(collectionIdAddress, 'nft', sponsor);
222 await sponsorCollection.methods.confirmCollectionSponsorship().send();239 await sponsorCollection.methods.confirmCollectionSponsorship().send();
223 collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;240 collectionData = (await collection.getData())!;
224 expect(collectionSub.sponsorship.isConfirmed).to.be.true;241 expect(collectionData.raw.sponsorship.Confirmed).to.be.eq(helper.address.ethToSubstrate(sponsor, true));
225 expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
226242
227 const user = createEthAccount(web3);243 const user = helper.eth.createAccount();
228 await collectionEvm.methods.addCollectionAdmin(user).send();244 await collectionEvm.methods.addCollectionAdmin(user).send();
229 245
230 const ownerBalanceBefore = await ethBalanceViaSub(api, owner);246 const ownerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
231 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);247 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
232 248
233 249 const userCollectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', user);
234 const userCollectionEvm = evmCollection(web3, user, collectionIdAddress);
235 const nextTokenId = await userCollectionEvm.methods.nextTokenId().call();250 const nextTokenId = await userCollectionEvm.methods.nextTokenId().call();
236 expect(nextTokenId).to.be.equal('1');251 expect(nextTokenId).to.be.equal('1');
237 result = await userCollectionEvm.methods.mintWithTokenURI(252 result = await userCollectionEvm.methods.mintWithTokenURI(
240 'Test URI',255 'Test URI',
241 ).send();256 ).send();
242257
243 const events = normalizeEvents(result.events);258 const events = helper.eth.normalizeEvents(result.events);
244 const address = collectionIdToAddress(collectionId);259 const address = helper.ethAddress.fromCollectionId(collectionId);
245260
246 expect(events).to.be.deep.equal([261 expect(events).to.be.deep.equal([
247 {262 {
256 ]);271 ]);
257 expect(await userCollectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');272 expect(await userCollectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
258 273
259 const ownerBalanceAfter = await ethBalanceViaSub(api, owner);274 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));
260 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);275 expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);
261 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);276 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));
262 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;277 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
263 });278 });
264});279});
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
18import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';18import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';
19import {scheduleExpectSuccess, waitNewBlocks, requirePallets, Pallets} from '../util/helpers';19import {scheduleExpectSuccess, waitNewBlocks, requirePallets, Pallets} from '../util/helpers';
2020
21// TODO mrshiposha update this test in #581
21describe('Scheduing EVM smart contracts', () => {22describe.skip('Scheduing EVM smart contracts', () => {
22 before(async function() {23 before(async function() {
23 await requirePallets(this, [Pallets.Scheduler]);24 await requirePallets(this, [Pallets.Scheduler]);
24 });25 });
modifiedtests/src/eth/sponsoring.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 {expect} from 'chai';17import {IKeyringPair} from '@polkadot/types/types';
18import {contractHelpers, createEthAccount, createEthAccountWithBalance, deployCollector, deployFlipper, itWeb3, SponsoringMode} from './util/helpers';18import {itEth, expect, SponsoringMode} from '../eth/util/playgrounds';
19import {usingPlaygrounds} from './../util/playgrounds/index';
1920
20describe('EVM sponsoring', () => {21describe('EVM sponsoring', () => {
22 let donor: IKeyringPair;
23
24 before(async () => {
25 await usingPlaygrounds(async (helper, privateKey) => {
26 donor = privateKey('//Alice');
27 });
28 });
29
21 itWeb3('Fee is deducted from contract if sponsoring is enabled', async ({api, web3, privateKeyWrapper}) => {30 itEth('Fee is deducted from contract if sponsoring is enabled', async ({helper}) => {
22 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);31 const owner = await helper.eth.createAccountWithBalance(donor);
23 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);32 const sponsor = await helper.eth.createAccountWithBalance(donor);
24 const caller = createEthAccount(web3);33 const caller = helper.eth.createAccount();
25 const originalCallerBalance = await web3.eth.getBalance(caller);34 const originalCallerBalance = await helper.balance.getEthereum(caller);
35
26 expect(originalCallerBalance).to.be.equal('0');36 expect(originalCallerBalance).to.be.equal(0n);
2737
28 const flipper = await deployFlipper(web3, owner);38 const flipper = await helper.eth.deployFlipper(owner);
2939
30 const helpers = contractHelpers(web3, owner);40 const helpers = helper.ethNativeContract.contractHelpers(owner);
41
31 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});42 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});
32 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});43 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});
39 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});50 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});
40 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;51 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;
4152
42 const originalSponsorBalance = await web3.eth.getBalance(sponsor);53 const originalSponsorBalance = await helper.balance.getEthereum(sponsor);
43 expect(originalSponsorBalance).to.be.not.equal('0');54 expect(originalSponsorBalance).to.be.not.equal(0n);
4455
45 await flipper.methods.flip().send({from: caller});56 await flipper.methods.flip().send({from: caller});
46 expect(await flipper.methods.getValue().call()).to.be.true;57 expect(await flipper.methods.getValue().call()).to.be.true;
4758
48 // Balance should be taken from flipper instead of caller59 // Balance should be taken from flipper instead of caller
49 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);60 expect(await helper.balance.getEthereum(caller)).to.be.equal(originalCallerBalance);
50 expect(await web3.eth.getBalance(sponsor)).to.be.not.equals(originalSponsorBalance);61 expect(await helper.balance.getEthereum(sponsor)).to.be.not.equal(originalSponsorBalance);
51 });62 });
5263
53 itWeb3('...but this doesn\'t applies to payable value', async ({api, web3, privateKeyWrapper}) => {64 itEth('...but this doesn\'t applies to payable value', async ({helper}) => {
54 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);65 const owner = await helper.eth.createAccountWithBalance(donor);
55 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);66 const sponsor = await helper.eth.createAccountWithBalance(donor);
56 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);67 const caller = await helper.eth.createAccountWithBalance(donor);
57 const originalCallerBalance = await web3.eth.getBalance(caller);68 const originalCallerBalance = await helper.balance.getEthereum(caller);
69
58 expect(originalCallerBalance).to.be.not.equal('0');70 expect(originalCallerBalance).to.be.not.equal(0n);
5971
60 const collector = await deployCollector(web3, owner);72 const collector = await helper.eth.deployCollectorContract(owner);
6173
62 const helpers = contractHelpers(web3, owner);74 const helpers = helper.ethNativeContract.contractHelpers(owner);
75
63 await helpers.methods.toggleAllowlist(collector.options.address, true).send({from: owner});76 await helpers.methods.toggleAllowlist(collector.options.address, true).send({from: owner});
64 await helpers.methods.toggleAllowed(collector.options.address, caller, true).send({from: owner});77 await helpers.methods.toggleAllowed(collector.options.address, caller, true).send({from: owner});
71 await helpers.methods.setSponsor(collector.options.address, sponsor).send({from: owner});84 await helpers.methods.setSponsor(collector.options.address, sponsor).send({from: owner});
72 await helpers.methods.confirmSponsorship(collector.options.address).send({from: sponsor});85 await helpers.methods.confirmSponsorship(collector.options.address).send({from: sponsor});
7386
74 const originalSponsorBalance = await web3.eth.getBalance(sponsor);87 const originalSponsorBalance = await helper.balance.getEthereum(sponsor);
75 expect(originalSponsorBalance).to.be.not.equal('0');88 expect(originalSponsorBalance).to.be.not.equal(0n);
7689
77 await collector.methods.giveMoney().send({from: caller, value: '10000'});90 await collector.methods.giveMoney().send({from: caller, value: '10000'});
7891
79 // Balance will be taken from both caller (value) and from collector (fee)92 // Balance will be taken from both caller (value) and from collector (fee)
80 expect(await web3.eth.getBalance(caller)).to.be.equals((BigInt(originalCallerBalance) - 10000n).toString());93 expect(await helper.balance.getEthereum(caller)).to.be.equals((originalCallerBalance - 10000n));
81 expect(await web3.eth.getBalance(sponsor)).to.be.not.equals(originalSponsorBalance);94 expect(await helper.balance.getEthereum(sponsor)).to.be.not.equals(originalSponsorBalance);
82 expect(await collector.methods.getCollected().call()).to.be.equal('10000');95 expect(await collector.methods.getCollected().call()).to.be.equal('10000');
83 });96 });
84});97});
modifiedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
1import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess} from '../util/helpers';1import {IKeyringPair} from '@polkadot/types/types';
2import {cartesian, collectionIdToAddress, createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3} from './util/helpers';2import {usingPlaygrounds} from './../util/playgrounds/index';
3import nonFungibleAbi from './nonFungibleAbi.json';
4import {expect} from 'chai';3import {itEth, expect} from '../eth/util/playgrounds';
5import {executeTransaction} from '../substrate/substrate-api';
64
7describe('EVM token properties', () => {5describe('EVM token properties', () => {
6 let donor: IKeyringPair;
7 let alice: IKeyringPair;
8
9 before(async () => {
10 await usingPlaygrounds(async (helper, privateKey) => {
11 donor = privateKey('//Alice');
12 [alice] = await helper.arrange.createAccounts([1000n], donor);
13 });
14 });
15
8 itWeb3('Can be reconfigured', async({web3, api, privateKeyWrapper}) => {16 itEth('Can be reconfigured', async({helper}) => {
9 const alice = privateKeyWrapper('//Alice');
10 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);17 const caller = await helper.eth.createAccountWithBalance(donor);
18
11 for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {19 for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {
12 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});20 const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'ethp'});
13 await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});21 await collection.addAdmin(alice, {Ethereum: caller});
14 22
15 const address = collectionIdToAddress(collection);23 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
16 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});24 const contract = helper.ethNativeContract.collection(address, 'nft', caller);
17 25
18 await contract.methods.setTokenPropertyPermission('testKey', mutable, collectionAdmin, tokenOwner).send({from: caller});26 await contract.methods.setTokenPropertyPermission('testKey', mutable, collectionAdmin, tokenOwner).send({from: caller});
19 27
20 const state = (await api.query.common.collectionPropertyPermissions(collection)).toJSON();28 const state = await collection.getPropertyPermissions();
21 expect(state).to.be.deep.equal({29 expect(state).to.be.deep.equal([{
22 [web3.utils.toHex('testKey')]: {mutable, collectionAdmin, tokenOwner},30 key: 'testKey',
31 permission: {mutable, collectionAdmin, tokenOwner},
23 });32 }]);
24 }33 }
25 });34 });
35
26 itWeb3('Can be set', async({web3, api, privateKeyWrapper}) => {36 itEth('Can be set', async({helper}) => {
27 const alice = privateKeyWrapper('//Alice');
28 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);37 const caller = await helper.eth.createAccountWithBalance(donor);
29 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});38 const collection = await helper.nft.mintCollection(alice, {
30 const token = await createItemExpectSuccess(alice, collection, 'NFT');
31
32 await executeTransaction(api, alice, api.tx.unique.setTokenPropertyPermissions(collection, [{39 tokenPrefix: 'ethp',
40 tokenPropertyPermissions: [{
33 key: 'testKey',41 key: 'testKey',
34 permission: {42 permission: {
35 collectionAdmin: true,43 collectionAdmin: true,
36 },44 },
37 }]));45 }],
46 });
47 const token = await collection.mintToken(alice);
3848
39 await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});49 await collection.addAdmin(alice, {Ethereum: caller});
4050
41 const address = collectionIdToAddress(collection);51 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
42 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});52 const contract = helper.ethNativeContract.collection(address, 'nft', caller);
4353
44 await contract.methods.setProperty(token, 'testKey', Buffer.from('testValue')).send({from: caller});54 await contract.methods.setProperty(token.tokenId, 'testKey', Buffer.from('testValue')).send({from: caller});
4555
46 const [{value}] = (await api.rpc.unique.tokenProperties(collection, token, ['testKey'])).toHuman()! as any;56 const [{value}] = await token.getProperties(['testKey']);
47 expect(value).to.equal('testValue');57 expect(value).to.equal('testValue');
48 });58 });
59
49 itWeb3('Can be deleted', async({web3, api, privateKeyWrapper}) => {60 itEth('Can be deleted', async({helper}) => {
50 const alice = privateKeyWrapper('//Alice');
51 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);61 const caller = await helper.eth.createAccountWithBalance(donor);
52 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});62 const collection = await helper.nft.mintCollection(alice, {
53 const token = await createItemExpectSuccess(alice, collection, 'NFT');
54
55 await executeTransaction(api, alice, api.tx.unique.setTokenPropertyPermissions(collection, [{63 tokenPrefix: 'ethp',
64 tokenPropertyPermissions: [{
56 key: 'testKey',65 key: 'testKey',
57 permission: {66 permission: {
58 mutable: true,67 mutable: true,
59 collectionAdmin: true,68 collectionAdmin: true,
60 },69 },
61 }]));70 }],
71 });
72
62 await executeTransaction(api, alice, api.tx.unique.setTokenProperties(collection, token, [{key: 'testKey', value: 'testValue'}]));73 await collection.addAdmin(alice, {Ethereum: caller});
6374
75 const token = await collection.mintToken(alice);
64 await addCollectionAdminExpectSuccess(alice, collection, {Ethereum: caller});76 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]);
6577
66 const address = collectionIdToAddress(collection);78 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
67 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});79 const contract = helper.ethNativeContract.collection(address, 'nft', caller);
6880
69 await contract.methods.deleteProperty(token, 'testKey').send({from: caller});81 await contract.methods.deleteProperty(token.tokenId, 'testKey').send({from: caller});
7082
71 const result = (await api.rpc.unique.tokenProperties(collection, token, ['testKey'])).toJSON()! as any;83 const result = await token.getProperties(['testKey']);
72 expect(result.length).to.equal(0);84 expect(result.length).to.equal(0);
73 });85 });
86
74 itWeb3('Can be read', async({web3, api, privateKeyWrapper}) => {87 itEth('Can be read', async({helper}) => {
75 const alice = privateKeyWrapper('//Alice');
76 const caller = createEthAccount(web3);
77 const collection = await createCollectionExpectSuccess({mode: {type:'NFT'}});88 const caller = await helper.eth.createAccountWithBalance(donor);
78 const token = await createItemExpectSuccess(alice, collection, 'NFT');89 const collection = await helper.nft.mintCollection(alice, {
79
80 await executeTransaction(api, alice, api.tx.unique.setTokenPropertyPermissions(collection, [{90 tokenPrefix: 'ethp',
91 tokenPropertyPermissions: [{
81 key: 'testKey',92 key: 'testKey',
82 permission: {93 permission: {
83 collectionAdmin: true,94 collectionAdmin: true,
84 },95 },
85 }]));96 }],
97 });
98 const token = await collection.mintToken(alice);
86 await executeTransaction(api, alice, api.tx.unique.setTokenProperties(collection, token, [{key: 'testKey', value: 'testValue'}]));99 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]);
87100
88 const address = collectionIdToAddress(collection);101 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
89 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: caller, ...GAS_ARGS});102 const contract = helper.ethNativeContract.collection(address, 'nft', caller);
90103
91 const value = await contract.methods.property(token, 'testKey').call();104 const value = await contract.methods.property(token.tokenId, 'testKey').call();
92 expect(value).to.equal(web3.utils.toHex('testValue'));105 expect(value).to.equal(helper.getWeb3().utils.toHex('testValue'));
93 });106 });
94});107});
95108
109
110type ElementOf<A> = A extends readonly (infer T)[] ? T : never;
111function* cartesian<T extends Array<Array<any>>, R extends Array<any>>(internalRest: [...R], ...args: [...T]): Generator<[...R, ...{[K in keyof T]: ElementOf<T[K]>}]> {
112 if(args.length === 0) {
113 yield internalRest as any;
114 return;
115 }
116 for(const value of args[0]) {
117 yield* cartesian([...internalRest, value], ...args.slice(1)) as any;
118 }
119}
modifiedtests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth
8 object: string;8 object: string;
9}9}
10
11export type NormalizedEvent = {
12 address: string,
13 event: string,
14 args: { [key: string]: string }
15};
16
modifiedtests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth
1818
19import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';19import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';
2020
21import {ContractImports, CompiledContract} from './types';21import {ContractImports, CompiledContract, NormalizedEvent} from './types';
2222
23// Native contracts ABI23// Native contracts ABI
24import collectionHelpersAbi from '../../collectionHelpersAbi.json';24import collectionHelpersAbi from '../../collectionHelpersAbi.json';
253 return before - after;253 return before - after;
254 }254 }
255
256 normalizeEvents(events: any): NormalizedEvent[] {
257 const output = [];
258 for (const key of Object.keys(events)) {
259 if (key.match(/^[0-9]+$/)) {
260 output.push(events[key]);
261 } else if (Array.isArray(events[key])) {
262 output.push(...events[key]);
263 } else {
264 output.push(events[key]);
265 }
266 }
267 output.sort((a, b) => a.logIndex - b.logIndex);
268 return output.map(({address, event, returnValues}) => {
269 const args: { [key: string]: string } = {};
270 for (const key of Object.keys(returnValues)) {
271 if (!key.match(/^[0-9]+$/)) {
272 args[key] = returnValues[key];
273 }
274 }
275 return {
276 address,
277 event,
278 args,
279 };
280 });
281 }
255} 282}
256283
257class EthAddressGroup extends EthGroupBase {284class EthAddressGroup extends EthGroupBase {