1234567891011121314151617import {expect} from 'chai';18import {19 contractHelpers,20 createEthAccountWithBalance,21 transferBalanceToEth,22 deployFlipper,23 itWeb3,24 SponsoringMode,25 createEthAccount,26 ethBalanceViaSub,27} from './util/helpers';28import {evmToAddress} from '@polkadot/util-crypto';2930describe('Sponsoring EVM contracts', () => {31 itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3, privateKeyWrapper}) => {32 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);33 const flipper = await deployFlipper(web3, owner);34 const helpers = contractHelpers(web3, owner);35 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;36 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});37 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;38 });3940 itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {41 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);42 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);43 const flipper = await deployFlipper(web3, owner);44 const helpers = contractHelpers(web3, owner);45 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;46 await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).send({from: notOwner})).to.rejected;47 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;48 });49 50 itWeb3('Sponsor can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {51 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);52 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);53 const flipper = await deployFlipper(web3, owner);54 const helpers = contractHelpers(web3, owner);55 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;56 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;57 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;58 });59 60 itWeb3('Sponsor can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {61 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);62 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);63 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);64 const flipper = await deployFlipper(web3, owner);65 const helpers = contractHelpers(web3, owner);66 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;67 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).call({from: notOwner})).to.be.rejectedWith('NoPermission');68 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;69 });7071 itWeb3('Sponsorship can be confirmed by the address that pending as sponsor', async ({api, web3, privateKeyWrapper}) => {72 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);73 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);74 const flipper = await deployFlipper(web3, owner);75 const helpers = contractHelpers(web3, owner);76 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;77 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;78 await expect(helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor})).to.be.not.rejected;79 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;80 });8182 itWeb3('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({api, web3, privateKeyWrapper}) => {83 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);84 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);85 const notSponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);86 const flipper = await deployFlipper(web3, owner);87 const helpers = contractHelpers(web3, owner);88 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;89 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;90 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPermission');91 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;92 });9394 itWeb3('Get confirmed sponsor', async ({api, web3, privateKeyWrapper}) => {95 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);96 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);97 const flipper = await deployFlipper(web3, owner);98 const helpers = contractHelpers(web3, owner);99 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();100 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});101 102 const result = await helpers.methods.getSponsor(flipper.options.address).call();103104 expect(result[0]).to.be.eq(sponsor);105 const sponsorSub = api.registry.createType('AccountId', '0x' + BigInt(result[1]).toString(16).padStart(64, '0')).toJSON();106 expect(sponsorSub).to.be.eq(evmToAddress(sponsor));107 });108109 itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3, privateKeyWrapper}) => {110 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);111 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);112 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);113114 const flipper = await deployFlipper(web3, owner);115116 const helpers = contractHelpers(web3, owner);117118 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;119 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();120 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});121 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;122123 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});124 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});125126 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);127 const callerBalanceBefore = await ethBalanceViaSub(api, caller);128129 await flipper.methods.flip().send({from: caller});130 expect(await flipper.methods.getValue().call()).to.be.true;131132 133 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);134 const callerBalanceAfter = await ethBalanceViaSub(api, caller);135 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;136 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);137 });138139 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}) => {140 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);141 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);142 const caller = createEthAccount(web3);143144 const flipper = await deployFlipper(web3, owner);145146 const helpers = contractHelpers(web3, owner);147 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});148 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});149150 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});151 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});152153 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();154 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});155156 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);157 expect(sponsorBalanceBefore).to.be.not.equal('0');158159 await flipper.methods.flip().send({from: caller});160 expect(await flipper.methods.getValue().call()).to.be.true;161162 163 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);164 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;165 });166167 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}) => {168 const alice = privateKeyWrapper('//Alice');169170 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);171 const caller = createEthAccount(web3);172173 const flipper = await deployFlipper(web3, owner);174175 const helpers = contractHelpers(web3, owner);176177 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});178 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});179180 await transferBalanceToEth(api, alice, flipper.options.address);181182 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);183 expect(originalFlipperBalance).to.be.not.equal('0');184185 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);186 expect(await flipper.methods.getValue().call()).to.be.false;187188 189 const balanceAfter = await web3.eth.getBalance(flipper.options.address);190 expect(+balanceAfter).to.be.equals(+originalFlipperBalance);191 });192193 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}) => {194 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);195 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);196 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);197198 const flipper = await deployFlipper(web3, owner);199200 const helpers = contractHelpers(web3, owner);201 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});202 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});203204 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});205 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});206207 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();208 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});209210 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);211 const callerBalanceBefore = await ethBalanceViaSub(api, caller);212213 await flipper.methods.flip().send({from: caller});214 expect(await flipper.methods.getValue().call()).to.be.true;215216 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);217 const callerBalanceAfter = await ethBalanceViaSub(api, caller);218 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;219 expect(callerBalanceAfter).to.be.equals(callerBalanceBefore);220 });221222 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}) => {223 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);224 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);225 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);226 const originalCallerBalance = await web3.eth.getBalance(caller);227228 const flipper = await deployFlipper(web3, owner);229230 const helpers = contractHelpers(web3, owner);231 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});232 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});233234 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});235 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 10).send({from: owner});236237 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();238 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});239240 const originalFlipperBalance = await web3.eth.getBalance(sponsor);241 expect(originalFlipperBalance).to.be.not.equal('0');242243 await flipper.methods.flip().send({from: caller});244 expect(await flipper.methods.getValue().call()).to.be.true;245 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);246247 const newFlipperBalance = await web3.eth.getBalance(sponsor);248 expect(newFlipperBalance).to.be.not.equals(originalFlipperBalance);249250 await flipper.methods.flip().send({from: caller});251 expect(await web3.eth.getBalance(sponsor)).to.be.equal(newFlipperBalance);252 expect(await web3.eth.getBalance(caller)).to.be.not.equals(originalCallerBalance);253 });254255 256 itWeb3('Default rate limit equals 7200', async ({api, web3, privateKeyWrapper}) => {257 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);258 const flipper = await deployFlipper(web3, owner);259 const helpers = contractHelpers(web3, owner);260 expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');261 });262});