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('Self sponsored can be set by the address that 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.hasSponsor(flipper.options.address).call()).to.be.false;36 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;37 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;38 });3940 itWeb3('Self sponsored can not 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.hasSponsor(flipper.options.address).call()).to.be.false;46 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');47 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;48 });4950 itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3, privateKeyWrapper}) => {51 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);52 const flipper = await deployFlipper(web3, owner);53 const helpers = contractHelpers(web3, owner);54 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;55 await expect(helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner})).to.be.not.rejected;56 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;57 });5859 itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {60 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);61 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);62 const flipper = await deployFlipper(web3, owner);63 const helpers = contractHelpers(web3, owner);64 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;65 await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).call({from: notOwner})).to.be.rejectedWith('NoPermission');66 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;67 });68 69 itWeb3('Sponsor can be set by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {70 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);71 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);72 const flipper = await deployFlipper(web3, owner);73 const helpers = contractHelpers(web3, owner);74 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;75 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;76 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;77 });78 79 itWeb3('Sponsor can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {80 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);81 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);82 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);83 const flipper = await deployFlipper(web3, owner);84 const helpers = contractHelpers(web3, owner);85 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;86 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).call({from: notOwner})).to.be.rejectedWith('NoPermission');87 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;88 });8990 itWeb3('Sponsorship can be confirmed by the address that pending as sponsor', async ({api, web3, privateKeyWrapper}) => {91 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);92 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);93 const flipper = await deployFlipper(web3, owner);94 const helpers = contractHelpers(web3, owner);95 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;96 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;97 await expect(helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor})).to.be.not.rejected;98 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;99 });100101 itWeb3('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({api, web3, privateKeyWrapper}) => {102 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);103 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);104 const notSponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);105 const flipper = await deployFlipper(web3, owner);106 const helpers = contractHelpers(web3, owner);107 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;108 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;109 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPermission');110 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;111 });112113 itWeb3('Sponsorship can not be confirmed by the address that not set as sponsor', async ({api, web3, privateKeyWrapper}) => {114 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);115 const notSponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);116 const flipper = await deployFlipper(web3, owner);117 const helpers = contractHelpers(web3, owner);118 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;119 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPendingSponsor');120 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;121 });122123 itWeb3('Get self sponsored sponsor', async ({api, web3, privateKeyWrapper}) => {124 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);125 const flipper = await deployFlipper(web3, owner);126 const helpers = contractHelpers(web3, owner);127 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();128 129 const result = await helpers.methods.getSponsor(flipper.options.address).call();130131 expect(result[0]).to.be.eq(flipper.options.address);132 expect(result[1]).to.be.eq('0');133 });134135 itWeb3('Get confirmed sponsor', async ({api, web3, privateKeyWrapper}) => {136 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);137 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);138 const flipper = await deployFlipper(web3, owner);139 const helpers = contractHelpers(web3, owner);140 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();141 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});142 143 const result = await helpers.methods.getSponsor(flipper.options.address).call();144145 expect(result[0]).to.be.eq(sponsor);146 expect(result[1]).to.be.eq('0');147 });148149 itWeb3('Sponsor can be removed by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {150 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);151 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);152 const flipper = await deployFlipper(web3, owner);153 const helpers = contractHelpers(web3, owner);154155 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;156 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();157 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});158 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;159 160 await helpers.methods.removeSponsor(flipper.options.address).send();161 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;162 });163164 itWeb3('Sponsor can not be removed by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {165 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);166 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);167 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);168 const flipper = await deployFlipper(web3, owner);169 const helpers = contractHelpers(web3, owner);170171 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;172 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();173 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});174 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;175 176 await expect(helpers.methods.removeSponsor(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');177 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;178 });179180 itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3, privateKeyWrapper}) => {181 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);182 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);183 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);184185 const flipper = await deployFlipper(web3, owner);186187 const helpers = contractHelpers(web3, owner);188189 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();190 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});191192 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});193 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});194195 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);196 const callerBalanceBefore = await ethBalanceViaSub(api, caller);197198 await flipper.methods.flip().send({from: caller});199 expect(await flipper.methods.getValue().call()).to.be.true;200201 202 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);203 const callerBalanceAfter = await ethBalanceViaSub(api, caller);204 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;205 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);206 });207208 itWeb3('In generous mode, non-allowlisted user transaction will be self sponsored', async ({api, web3, privateKeyWrapper}) => {209 const alice = privateKeyWrapper('//Alice');210211 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);212 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);213214 const flipper = await deployFlipper(web3, owner);215216 const helpers = contractHelpers(web3, owner);217218 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();219220 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});221 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});222223 await transferBalanceToEth(api, alice, flipper.options.address);224225 const contractBalanceBefore = await ethBalanceViaSub(api, flipper.options.address);226 const callerBalanceBefore = await ethBalanceViaSub(api, caller);227228 await flipper.methods.flip().send({from: caller});229 expect(await flipper.methods.getValue().call()).to.be.true;230231 232 const contractBalanceAfter = await ethBalanceViaSub(api, flipper.options.address);233 const callerBalanceAfter = await ethBalanceViaSub(api, caller);234 expect(contractBalanceAfter < contractBalanceBefore).to.be.true;235 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);236 });237238 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}) => {239 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);240 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);241 const caller = createEthAccount(web3);242243 const flipper = await deployFlipper(web3, owner);244245 const helpers = contractHelpers(web3, owner);246 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});247 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});248249 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});250 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});251252 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();253 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});254255 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);256 expect(sponsorBalanceBefore).to.be.not.equal('0');257258 await flipper.methods.flip().send({from: caller});259 expect(await flipper.methods.getValue().call()).to.be.true;260261 262 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);263 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;264 });265266 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}) => {267 const alice = privateKeyWrapper('//Alice');268269 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);270 const caller = createEthAccount(web3);271272 const flipper = await deployFlipper(web3, owner);273274 const helpers = contractHelpers(web3, owner);275276 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});277 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});278279 await transferBalanceToEth(api, alice, flipper.options.address);280281 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);282 expect(originalFlipperBalance).to.be.not.equal('0');283284 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);285 expect(await flipper.methods.getValue().call()).to.be.false;286287 288 const balanceAfter = await web3.eth.getBalance(flipper.options.address);289 expect(+balanceAfter).to.be.equals(+originalFlipperBalance);290 });291292 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}) => {293 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);294 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);295 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);296297 const flipper = await deployFlipper(web3, owner);298299 const helpers = contractHelpers(web3, owner);300 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});301 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});302303 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});304 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});305306 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();307 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});308309 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);310 const callerBalanceBefore = await ethBalanceViaSub(api, caller);311312 await flipper.methods.flip().send({from: caller});313 expect(await flipper.methods.getValue().call()).to.be.true;314315 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);316 const callerBalanceAfter = await ethBalanceViaSub(api, caller);317 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;318 expect(callerBalanceAfter).to.be.equals(callerBalanceBefore);319 });320321 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}) => {322 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);323 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);324 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);325 const originalCallerBalance = await web3.eth.getBalance(caller);326327 const flipper = await deployFlipper(web3, owner);328329 const helpers = contractHelpers(web3, owner);330 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});331 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});332333 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});334 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 10).send({from: owner});335336 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();337 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});338339 const originalFlipperBalance = await web3.eth.getBalance(sponsor);340 expect(originalFlipperBalance).to.be.not.equal('0');341342 await flipper.methods.flip().send({from: caller});343 expect(await flipper.methods.getValue().call()).to.be.true;344 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);345346 const newFlipperBalance = await web3.eth.getBalance(sponsor);347 expect(newFlipperBalance).to.be.not.equals(originalFlipperBalance);348349 await flipper.methods.flip().send({from: caller});350 expect(await web3.eth.getBalance(sponsor)).to.be.equal(newFlipperBalance);351 expect(await web3.eth.getBalance(caller)).to.be.not.equals(originalCallerBalance);352 });353354 355 itWeb3('Default rate limit equals 7200', async ({api, web3, privateKeyWrapper}) => {356 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);357 const flipper = await deployFlipper(web3, owner);358 const helpers = contractHelpers(web3, owner);359 expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');360 });361});