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';2829describe('Sponsoring EVM contracts', () => {30 itWeb3('Self sponsored can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {31 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);32 const flipper = await deployFlipper(web3, owner);33 const helpers = contractHelpers(web3, owner);34 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;35 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;36 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;37 });3839 itWeb3('Self sponsored can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {40 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);41 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);42 const flipper = await deployFlipper(web3, owner);43 const helpers = contractHelpers(web3, owner);44 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;45 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');46 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;47 });4849 itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3, privateKeyWrapper}) => {50 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);51 const flipper = await deployFlipper(web3, owner);52 const helpers = contractHelpers(web3, owner);53 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;54 await expect(helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner})).to.be.not.rejected;55 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;56 });5758 itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {59 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);60 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);61 const flipper = await deployFlipper(web3, owner);62 const helpers = contractHelpers(web3, owner);63 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;64 await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).call({from: notOwner})).to.be.rejectedWith('NoPermission');65 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;66 });67 68 itWeb3('Sponsor can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {69 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);70 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);71 const flipper = await deployFlipper(web3, owner);72 const helpers = contractHelpers(web3, owner);73 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;74 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;75 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;76 });77 78 itWeb3('Sponsor can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {79 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);80 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);81 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);82 const flipper = await deployFlipper(web3, owner);83 const helpers = contractHelpers(web3, owner);84 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;85 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).call({from: notOwner})).to.be.rejectedWith('NoPermission');86 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;87 });8889 itWeb3('Sponsorship can be confirmed by the address that pending as sponsor', async ({api, web3, privateKeyWrapper}) => {90 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);91 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);92 const flipper = await deployFlipper(web3, owner);93 const helpers = contractHelpers(web3, owner);94 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;95 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;96 await expect(helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor})).to.be.not.rejected;97 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;98 });99100 itWeb3('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({api, web3, privateKeyWrapper}) => {101 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);102 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);103 const notSponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);104 const flipper = await deployFlipper(web3, owner);105 const helpers = contractHelpers(web3, owner);106 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;107 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;108 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPermission');109 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;110 });111112 itWeb3('Sponsorship can not be confirmed by the address that not set as sponsor', async ({api, web3, privateKeyWrapper}) => {113 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);114 const notSponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);115 const flipper = await deployFlipper(web3, owner);116 const helpers = contractHelpers(web3, owner);117 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;118 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPendingSponsor');119 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;120 });121122 itWeb3('Get self sponsored sponsor', async ({api, web3, privateKeyWrapper}) => {123 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);124 const flipper = await deployFlipper(web3, owner);125 const helpers = contractHelpers(web3, owner);126 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();127 128 const result = await helpers.methods.getSponsor(flipper.options.address).call();129130 expect(result[0]).to.be.eq(flipper.options.address);131 expect(result[1]).to.be.eq('0');132 });133134 itWeb3('Get confirmed sponsor', async ({api, web3, privateKeyWrapper}) => {135 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);136 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);137 const flipper = await deployFlipper(web3, owner);138 const helpers = contractHelpers(web3, owner);139 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();140 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});141 142 const result = await helpers.methods.getSponsor(flipper.options.address).call();143144 expect(result[0]).to.be.eq(sponsor);145 expect(result[1]).to.be.eq('0');146 });147148 itWeb3('Sponsor can be removed by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {149 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);150 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);151 const flipper = await deployFlipper(web3, owner);152 const helpers = contractHelpers(web3, owner);153154 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;155 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();156 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});157 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;158 159 await helpers.methods.removeSponsor(flipper.options.address).send();160 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;161 });162163 itWeb3('Sponsor can not be removed by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {164 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);165 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);166 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);167 const flipper = await deployFlipper(web3, owner);168 const helpers = contractHelpers(web3, owner);169170 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;171 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();172 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});173 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;174 175 await expect(helpers.methods.removeSponsor(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');176 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;177 });178179 itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3, privateKeyWrapper}) => {180 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);181 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);182 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);183184 const flipper = await deployFlipper(web3, owner);185186 const helpers = contractHelpers(web3, owner);187188 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();189 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});190191 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});192 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});193194 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);195 const callerBalanceBefore = await ethBalanceViaSub(api, caller);196197 await flipper.methods.flip().send({from: caller});198 expect(await flipper.methods.getValue().call()).to.be.true;199200 201 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);202 const callerBalanceAfter = await ethBalanceViaSub(api, caller);203 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;204 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);205 });206207 itWeb3('In generous mode, non-allowlisted user transaction will be self sponsored', async ({api, web3, privateKeyWrapper}) => {208 const alice = privateKeyWrapper('//Alice');209210 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);211 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);212213 const flipper = await deployFlipper(web3, owner);214215 const helpers = contractHelpers(web3, owner);216217 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();218219 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});220 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});221222 await transferBalanceToEth(api, alice, flipper.options.address);223224 const contractBalanceBefore = await ethBalanceViaSub(api, flipper.options.address);225 const callerBalanceBefore = await ethBalanceViaSub(api, caller);226227 await flipper.methods.flip().send({from: caller});228 expect(await flipper.methods.getValue().call()).to.be.true;229230 231 const contractBalanceAfter = await ethBalanceViaSub(api, flipper.options.address);232 const callerBalanceAfter = await ethBalanceViaSub(api, caller);233 expect(contractBalanceAfter < contractBalanceBefore).to.be.true;234 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);235 });236237 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}) => {238 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);239 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);240 const caller = createEthAccount(web3);241242 const flipper = await deployFlipper(web3, owner);243244 const helpers = contractHelpers(web3, owner);245 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});246 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});247248 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});249 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});250251 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();252 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});253254 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);255 expect(sponsorBalanceBefore).to.be.not.equal('0');256257 await flipper.methods.flip().send({from: caller});258 expect(await flipper.methods.getValue().call()).to.be.true;259260 261 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);262 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;263 });264265 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}) => {266 const alice = privateKeyWrapper('//Alice');267268 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);269 const caller = createEthAccount(web3);270271 const flipper = await deployFlipper(web3, owner);272273 const helpers = contractHelpers(web3, owner);274275 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});276 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});277278 await transferBalanceToEth(api, alice, flipper.options.address);279280 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);281 expect(originalFlipperBalance).to.be.not.equal('0');282283 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);284 expect(await flipper.methods.getValue().call()).to.be.false;285286 287 const balanceAfter = await web3.eth.getBalance(flipper.options.address);288 expect(+balanceAfter).to.be.equals(+originalFlipperBalance);289 });290291 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}) => {292 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);293 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);294 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);295296 const flipper = await deployFlipper(web3, owner);297298 const helpers = contractHelpers(web3, owner);299 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});300 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});301302 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});303 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});304305 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();306 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});307308 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);309 const callerBalanceBefore = await ethBalanceViaSub(api, caller);310311 await flipper.methods.flip().send({from: caller});312 expect(await flipper.methods.getValue().call()).to.be.true;313314 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);315 const callerBalanceAfter = await ethBalanceViaSub(api, caller);316 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;317 expect(callerBalanceAfter).to.be.equals(callerBalanceBefore);318 });319320 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}) => {321 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);322 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);323 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);324 const originalCallerBalance = await web3.eth.getBalance(caller);325326 const flipper = await deployFlipper(web3, owner);327328 const helpers = contractHelpers(web3, owner);329 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});330 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});331332 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});333 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 10).send({from: owner});334335 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();336 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});337338 const originalFlipperBalance = await web3.eth.getBalance(sponsor);339 expect(originalFlipperBalance).to.be.not.equal('0');340341 await flipper.methods.flip().send({from: caller});342 expect(await flipper.methods.getValue().call()).to.be.true;343 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);344345 const newFlipperBalance = await web3.eth.getBalance(sponsor);346 expect(newFlipperBalance).to.be.not.equals(originalFlipperBalance);347348 await flipper.methods.flip().send({from: caller});349 expect(await web3.eth.getBalance(sponsor)).to.be.equal(newFlipperBalance);350 expect(await web3.eth.getBalance(caller)).to.be.not.equals(originalCallerBalance);351 });352353 354 itWeb3('Default rate limit equals 7200', async ({api, web3, privateKeyWrapper}) => {355 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);356 const flipper = await deployFlipper(web3, owner);357 const helpers = contractHelpers(web3, owner);358 expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');359 });360});