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('Get self sponsored sponsor', async ({api, web3, privateKeyWrapper}) => {114 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);115 const flipper = await deployFlipper(web3, owner);116 const helpers = contractHelpers(web3, owner);117 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();118 119 const result = await helpers.methods.getSponsor(flipper.options.address).call();120121 expect(result[0]).to.be.eq(flipper.options.address);122 const sponsorSub = api.registry.createType('AccountId', '0x' + BigInt(result[1]).toString(16).padStart(64, '0')).toJSON();123 expect(sponsorSub).to.be.eq(evmToAddress(flipper.options.address));124 });125126 itWeb3('Get confirmed sponsor', async ({api, web3, privateKeyWrapper}) => {127 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);128 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);129 const flipper = await deployFlipper(web3, owner);130 const helpers = contractHelpers(web3, owner);131 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();132 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});133 134 const result = await helpers.methods.getSponsor(flipper.options.address).call();135136 expect(result[0]).to.be.eq(sponsor);137 const sponsorSub = api.registry.createType('AccountId', '0x' + BigInt(result[1]).toString(16).padStart(64, '0')).toJSON();138 expect(sponsorSub).to.be.eq(evmToAddress(sponsor));139 });140141 itWeb3('Sponsor can be removed by the address that deployed the contract', async ({api, web3, privateKeyWrapper}) => {142 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);143 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);144 const flipper = await deployFlipper(web3, owner);145 const helpers = contractHelpers(web3, owner);146147 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;148 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();149 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});150 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;151 152 await helpers.methods.removeSponsor(flipper.options.address).send();153 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;154 });155156 itWeb3('Sponsor can not be removed by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => {157 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);158 const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);159 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);160 const flipper = await deployFlipper(web3, owner);161 const helpers = contractHelpers(web3, owner);162163 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;164 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();165 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});166 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;167 168 await expect(helpers.methods.removeSponsor(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');169 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;170 });171172 itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3, privateKeyWrapper}) => {173 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);174 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);175 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);176177 const flipper = await deployFlipper(web3, owner);178179 const helpers = contractHelpers(web3, owner);180181 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();182 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});183184 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});185 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});186187 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);188 const callerBalanceBefore = await ethBalanceViaSub(api, caller);189190 await flipper.methods.flip().send({from: caller});191 expect(await flipper.methods.getValue().call()).to.be.true;192193 194 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);195 const callerBalanceAfter = await ethBalanceViaSub(api, caller);196 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;197 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);198 });199200 itWeb3('In generous mode, non-allowlisted user transaction will be self sponsored', async ({api, web3, privateKeyWrapper}) => {201 const alice = privateKeyWrapper('//Alice');202203 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);204 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);205206 const flipper = await deployFlipper(web3, owner);207208 const helpers = contractHelpers(web3, owner);209210 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();211212 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});213 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});214215 await transferBalanceToEth(api, alice, flipper.options.address);216217 const contractBalanceBefore = await ethBalanceViaSub(api, flipper.options.address);218 const callerBalanceBefore = await ethBalanceViaSub(api, caller);219220 await flipper.methods.flip().send({from: caller});221 expect(await flipper.methods.getValue().call()).to.be.true;222223 224 const contractBalanceAfter = await ethBalanceViaSub(api, flipper.options.address);225 const callerBalanceAfter = await ethBalanceViaSub(api, caller);226 expect(contractBalanceAfter < contractBalanceBefore).to.be.true;227 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);228 });229230 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}) => {231 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);232 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);233 const caller = createEthAccount(web3);234235 const flipper = await deployFlipper(web3, owner);236237 const helpers = contractHelpers(web3, owner);238 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});239 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});240241 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});242 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});243244 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();245 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});246247 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);248 expect(sponsorBalanceBefore).to.be.not.equal('0');249250 await flipper.methods.flip().send({from: caller});251 expect(await flipper.methods.getValue().call()).to.be.true;252253 254 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);255 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;256 });257258 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}) => {259 const alice = privateKeyWrapper('//Alice');260261 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);262 const caller = createEthAccount(web3);263264 const flipper = await deployFlipper(web3, owner);265266 const helpers = contractHelpers(web3, owner);267268 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});269 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});270271 await transferBalanceToEth(api, alice, flipper.options.address);272273 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);274 expect(originalFlipperBalance).to.be.not.equal('0');275276 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);277 expect(await flipper.methods.getValue().call()).to.be.false;278279 280 const balanceAfter = await web3.eth.getBalance(flipper.options.address);281 expect(+balanceAfter).to.be.equals(+originalFlipperBalance);282 });283284 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}) => {285 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);286 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);287 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);288289 const flipper = await deployFlipper(web3, owner);290291 const helpers = contractHelpers(web3, owner);292 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});293 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});294295 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});296 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});297298 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();299 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});300301 const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);302 const callerBalanceBefore = await ethBalanceViaSub(api, caller);303304 await flipper.methods.flip().send({from: caller});305 expect(await flipper.methods.getValue().call()).to.be.true;306307 const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);308 const callerBalanceAfter = await ethBalanceViaSub(api, caller);309 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;310 expect(callerBalanceAfter).to.be.equals(callerBalanceBefore);311 });312313 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}) => {314 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);315 const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper);316 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);317 const originalCallerBalance = await web3.eth.getBalance(caller);318319 const flipper = await deployFlipper(web3, owner);320321 const helpers = contractHelpers(web3, owner);322 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});323 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});324325 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});326 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 10).send({from: owner});327328 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();329 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});330331 const originalFlipperBalance = await web3.eth.getBalance(sponsor);332 expect(originalFlipperBalance).to.be.not.equal('0');333334 await flipper.methods.flip().send({from: caller});335 expect(await flipper.methods.getValue().call()).to.be.true;336 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);337338 const newFlipperBalance = await web3.eth.getBalance(sponsor);339 expect(newFlipperBalance).to.be.not.equals(originalFlipperBalance);340341 await flipper.methods.flip().send({from: caller});342 expect(await web3.eth.getBalance(sponsor)).to.be.equal(newFlipperBalance);343 expect(await web3.eth.getBalance(caller)).to.be.not.equals(originalCallerBalance);344 });345346 347 itWeb3('Default rate limit equals 7200', async ({api, web3, privateKeyWrapper}) => {348 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);349 const flipper = await deployFlipper(web3, owner);350 const helpers = contractHelpers(web3, owner);351 expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');352 });353});