1234567891011121314151617import type {IKeyringPair} from '@polkadot/types/types';18import {EthUniqueHelper} from './util/playgrounds/unique.dev.js';19import {itEth, expect, SponsoringMode, usingEthPlaygrounds} from './util/index.js';20import {usingPlaygrounds} from '@unique/test-utils/util.js';21import type {CompiledContract} from './util/playgrounds/types.js';2223describe('Sponsoring EVM contracts', () => {24 let donor: IKeyringPair;25 let nominal: bigint;2627 before(async () => {28 await usingPlaygrounds(async (helper, privateKey) => {29 donor = await privateKey({url: import.meta.url});30 nominal = helper.balance.getOneTokenNominal();31 });32 });3334 itEth('Self sponsoring can be set by the address that deployed the contract', async ({helper}) => {35 const owner = await helper.eth.createAccountWithBalance(donor);36 const flipper = await helper.eth.deployFlipper(owner);37 const helpers = await helper.ethNativeContract.contractHelpers(owner);3839 40 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;41 const result = await helpers.methods.selfSponsoredEnable(flipper.options.address).send({from: owner});42 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;4344 45 const actualSponsorOpt = await helpers.methods.sponsor(flipper.options.address).call();46 expect(actualSponsorOpt.status).to.be.true;47 const actualSponsor = actualSponsorOpt.value;48 expect(actualSponsor.eth).to.eq(flipper.options.address);49 expect(actualSponsor.sub).to.eq('0');5051 52 const ethEvents = helper.eth.helper.eth.normalizeEvents(result.events);53 expect(ethEvents).to.be.deep.equal([54 {55 address: flipper.options.address,56 event: 'ContractSponsorSet',57 args: {58 contractAddress: flipper.options.address,59 sponsor: flipper.options.address,60 },61 },62 {63 address: flipper.options.address,64 event: 'ContractSponsorshipConfirmed',65 args: {66 contractAddress: flipper.options.address,67 sponsor: flipper.options.address,68 },69 },70 ]);71 });7273 itEth('Self sponsoring cannot be set by the address that did not deployed the contract', async ({helper}) => {74 const owner = await helper.eth.createAccountWithBalance(donor);75 const notOwner = await helper.eth.createAccountWithBalance(donor);76 const helpers = await helper.ethNativeContract.contractHelpers(owner);77 const flipper = await helper.eth.deployFlipper(owner);7879 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;80 await expect(helpers.methods.selfSponsoredEnable(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');81 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;82 });8384 itEth('Sponsoring can be set by the address that has deployed the contract', async ({helper}) => {85 const owner = await helper.eth.createAccountWithBalance(donor);86 const helpers = await helper.ethNativeContract.contractHelpers(owner);87 const flipper = await helper.eth.deployFlipper(owner);8889 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;90 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});91 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;92 });9394 itEth('Sponsoring cannot be set by the address that did not deployed the contract', async ({helper}) => {95 const owner = await helper.eth.createAccountWithBalance(donor);96 const notOwner = await helper.eth.createAccountWithBalance(donor);97 const helpers = await helper.ethNativeContract.contractHelpers(owner);98 const flipper = await helper.eth.deployFlipper(owner);99100 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;101 await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).call({from: notOwner})).to.be.rejectedWith('NoPermission');102 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;103 });104105 itEth('Sponsor can be set by the address that deployed the contract', async ({helper}) => {106 const owner = await helper.eth.createAccountWithBalance(donor);107 const sponsor = await helper.eth.createAccountWithBalance(donor);108 const helpers = await helper.ethNativeContract.contractHelpers(owner);109 const flipper = await helper.eth.deployFlipper(owner);110111 112 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;113 const result = await helpers.methods.setSponsor(flipper.options.address, sponsor).send();114 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true;115116 117 const events = helper.eth.normalizeEvents(result.events);118 expect(events).to.be.deep.equal([119 {120 address: flipper.options.address,121 event: 'ContractSponsorSet',122 args: {123 contractAddress: flipper.options.address,124 sponsor: sponsor,125 },126 },127 ]);128 });129130 itEth('Sponsor cannot be set by the address that did not deployed the contract', async ({helper}) => {131 const owner = await helper.eth.createAccountWithBalance(donor);132 const sponsor = await helper.eth.createAccountWithBalance(donor);133 const notOwner = await helper.eth.createAccountWithBalance(donor);134 const helpers = await helper.ethNativeContract.contractHelpers(owner);135 const flipper = await helper.eth.deployFlipper(owner);136137 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;138 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).call({from: notOwner})).to.be.rejectedWith('NoPermission');139 expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.false;140 });141142 itEth('Sponsorship can be confirmed by the address that pending as sponsor', async ({helper}) => {143 const owner = await helper.eth.createAccountWithBalance(donor);144 const sponsor = await helper.eth.createAccountWithBalance(donor);145 const helpers = await helper.ethNativeContract.contractHelpers(owner);146 const flipper = await helper.eth.deployFlipper(owner);147148 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;149 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();150151 152 const result = await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});153 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;154155 156 const actualSponsorOpt = await helpers.methods.sponsor(flipper.options.address).call();157 expect(actualSponsorOpt.status).to.be.true;158 const actualSponsor = actualSponsorOpt.value;159 expect(actualSponsor.eth).to.eq(sponsor);160 expect(actualSponsor.sub).to.eq('0');161162 163 const events = helper.eth.normalizeEvents(result.events);164 expect(events).to.be.deep.equal([165 {166 address: flipper.options.address,167 event: 'ContractSponsorshipConfirmed',168 args: {169 contractAddress: flipper.options.address,170 sponsor: sponsor,171 },172 },173 ]);174 });175176 itEth('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({helper}) => {177 const owner = await helper.eth.createAccountWithBalance(donor);178 const sponsor = await helper.eth.createAccountWithBalance(donor);179 const notSponsor = await helper.eth.createAccountWithBalance(donor);180 const helpers = await helper.ethNativeContract.contractHelpers(owner);181 const flipper = await helper.eth.deployFlipper(owner);182183 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;184 await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected;185 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPermission');186 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;187 });188189 itEth('Sponsorship can not be confirmed by the address that not set as sponsor', async ({helper}) => {190 const owner = await helper.eth.createAccountWithBalance(donor);191 const notSponsor = await helper.eth.createAccountWithBalance(donor);192 const helpers = await helper.ethNativeContract.contractHelpers(owner);193 const flipper = await helper.eth.deployFlipper(owner);194195 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;196 await expect(helpers.methods.confirmSponsorship(flipper.options.address).call({from: notSponsor})).to.be.rejectedWith('NoPendingSponsor');197 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;198 });199200 itEth('Sponsor can be removed by the address that deployed the contract', async ({helper}) => {201 const owner = await helper.eth.createAccountWithBalance(donor);202 const sponsor = await helper.eth.createAccountWithBalance(donor);203 const helpers = await helper.ethNativeContract.contractHelpers(owner);204 const flipper = await helper.eth.deployFlipper(owner);205206 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;207 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();208 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});209 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;210 211 const result = await helpers.methods.removeSponsor(flipper.options.address).send();212 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;213214 215 const events = helper.eth.normalizeEvents(result.events);216 expect(events).to.be.deep.equal([217 {218 address: flipper.options.address,219 event: 'ContractSponsorRemoved',220 args: {221 contractAddress: flipper.options.address,222 },223 },224 ]);225226 227 228 229 230 });231232 itEth('Sponsor can not be removed by the address that did not deployed the contract', async ({helper}) => {233 const owner = await helper.eth.createAccountWithBalance(donor);234 const notOwner = await helper.eth.createAccountWithBalance(donor);235 const sponsor = await helper.eth.createAccountWithBalance(donor);236 const helpers = await helper.ethNativeContract.contractHelpers(owner);237 const flipper = await helper.eth.deployFlipper(owner);238239 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false;240 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();241 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});242 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;243244 await expect(helpers.methods.removeSponsor(flipper.options.address).call({from: notOwner})).to.be.rejectedWith('NoPermission');245 await expect(helpers.methods.removeSponsor(flipper.options.address).send({from: notOwner})).to.be.rejected;246 expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true;247 });248249 itEth('In generous mode, non-allowlisted user transaction will be sponsored', async ({helper}) => {250 const owner = await helper.eth.createAccountWithBalance(donor);251 const sponsor = await helper.eth.createAccountWithBalance(donor);252 const caller = await helper.eth.createAccountWithBalance(donor);253 const helpers = await helper.ethNativeContract.contractHelpers(owner);254 const flipper = await helper.eth.deployFlipper(owner);255256 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();257 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});258259 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});260 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});261262 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));263 const callerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(caller));264265 await flipper.methods.flip().send({from: caller});266 expect(await flipper.methods.getValue().call()).to.be.true;267268 269 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));270 const callerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(caller));271 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;272 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);273 });274275 itEth('In generous mode, non-allowlisted user transaction will be self sponsored', async ({helper}) => {276 const owner = await helper.eth.createAccountWithBalance(donor);277 const caller = await helper.eth.createAccountWithBalance(donor);278 const helpers = await helper.ethNativeContract.contractHelpers(owner);279 const flipper = await helper.eth.deployFlipper(owner);280281 await helpers.methods.selfSponsoredEnable(flipper.options.address).send();282283 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});284 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});285286 await helper.eth.transferBalanceFromSubstrate(donor, flipper.options.address);287288 const contractBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(flipper.options.address));289 const callerBalanceBefore = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));290291 await flipper.methods.flip().send({from: caller});292 expect(await flipper.methods.getValue().call()).to.be.true;293294 295 const contractBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(flipper.options.address));296 const callerBalanceAfter = await helper.balance.getSubstrate(await helper.address.ethToSubstrate(caller));297 expect(contractBalanceAfter < contractBalanceBefore).to.be.true;298 expect(callerBalanceAfter).to.be.eq(callerBalanceBefore);299 });300301 [302 {balance: 0n, label: '0'},303 {balance: 10n, label: '10'},304 ].map(testCase => {305 itEth(`Allow-listed address that has ${testCase.label} UNQ can call a contract. Sponsor balance should decrease`, async ({helper}) => {306 const owner = await helper.eth.createAccountWithBalance(donor);307 const sponsor = await helper.eth.createAccountWithBalance(donor);308 const caller = helper.eth.createAccount();309 await helper.eth.transferBalanceFromSubstrate(donor, caller, testCase.balance);310 const helpers = await helper.ethNativeContract.contractHelpers(owner);311 const flipper = await helper.eth.deployFlipper(owner);312313 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});314 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});315316 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});317 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});318319 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();320 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});321322 const sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));323 expect(sponsorBalanceBefore > 0n).to.be.true;324325 await flipper.methods.flip().send({from: caller});326 expect(await flipper.methods.getValue().call()).to.be.true;327328 329 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));330 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;331 332 const callerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(caller));333 expect(callerBalanceAfter).to.eq(testCase.balance * nominal);334 });335 });336337 itEth('Non-allow-listed address can call a contract. Sponsor balance should not decrease', async ({helper}) => {338 const owner = await helper.eth.createAccountWithBalance(donor);339 const caller = helper.eth.createAccount();340 const contractHelpers = await helper.ethNativeContract.contractHelpers(owner);341342 343 const flipper = await helper.eth.deployFlipper(owner);344 await helper.eth.transferBalanceFromSubstrate(donor, flipper.options.address);345 expect(await flipper.methods.getValue().call()).to.be.false;346 347 const originalFlipperBalance = await helper.balance.getEthereum(flipper.options.address);348 expect(originalFlipperBalance > 0n).to.be.true;349350 351 await contractHelpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});352 await contractHelpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});353 await contractHelpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});354355 356 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/Returned error: insufficient funds for gas \* price \+ value/);357 expect(await flipper.methods.getValue().call()).to.be.false;358359 360 const balanceAfter = await helper.balance.getEthereum(flipper.options.address);361 expect(balanceAfter).to.be.equal(originalFlipperBalance);362 });363364 itEth('Sponsoring is limited, with setContractRateLimit. The limitation is working if transactions are sent more often, the sender pays the commission.', async ({helper}) => {365 const owner = await helper.eth.createAccountWithBalance(donor);366 const sponsor = await helper.eth.createAccountWithBalance(donor);367 const caller = await helper.eth.createAccountWithBalance(donor);368 const helpers = await helper.ethNativeContract.contractHelpers(owner);369 const flipper = await helper.eth.deployFlipper(owner);370371 const originalCallerBalance = await helper.balance.getEthereum(caller);372 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});373 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});374375 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});376 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 10).send({from: owner});377378 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();379 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});380381 const originalFlipperBalance = await helper.balance.getEthereum(sponsor);382 expect(originalFlipperBalance > 0n).to.be.true;383384 await flipper.methods.flip().send({from: caller});385 expect(await flipper.methods.getValue().call()).to.be.true;386 expect(await helper.balance.getEthereum(caller)).to.be.equal(originalCallerBalance);387388 const newFlipperBalance = await helper.balance.getEthereum(sponsor);389 expect(newFlipperBalance).to.be.not.equal(originalFlipperBalance);390391 await flipper.methods.flip().send({from: caller});392 393 expect(await helper.balance.getEthereum(sponsor)).to.be.equal(newFlipperBalance);394 expect(await helper.balance.getEthereum(caller)).to.be.not.equal(originalCallerBalance);395 });396397 398 itEth('Default rate limit equal 7200', async ({helper}) => {399 const owner = await helper.eth.createAccountWithBalance(donor);400 const helpers = await helper.ethNativeContract.contractHelpers(owner);401 const flipper = await helper.eth.deployFlipper(owner);402403 expect(await helpers.methods.sponsoringRateLimit(flipper.options.address).call()).to.be.equal('7200');404 });405406 itEth('Gas price boundaries', async ({helper}) => {407 const owner = await helper.eth.createAccountWithBalance(donor);408 const sponsor = await helper.eth.createAccountWithBalance(donor);409 const caller = await helper.eth.createAccountWithBalance(donor);410 const helpers = await helper.ethNativeContract.contractHelpers(owner);411 const flipper = await helper.eth.deployFlipper(owner);412413 await helpers.methods.setSponsor(flipper.options.address, sponsor).send();414 await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor});415416 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});417 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});418419 let sponsorBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));420 let callerBalanceBefore = await helper.balance.getSubstrate(helper.address.ethToSubstrate(caller));421422 let expectValue = await flipper.methods.getValue().call();423424 const flip = async (gasPrice: bigint, shouldPass = true) => {425 await flipper.methods.flip().send({from: caller, gasPrice: gasPrice});426 expectValue = !expectValue;427 expect(await flipper.methods.getValue().call()).to.be.eq(expectValue);428 const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));429 const callerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(caller));430 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.eq(shouldPass);431 expect(callerBalanceAfter === callerBalanceBefore).to.be.eq(shouldPass);432 sponsorBalanceBefore = sponsorBalanceAfter;433 callerBalanceBefore = callerBalanceAfter;434 };435436 const gasPrice = BigInt((await helper.eth.getGasPrice())!);437 await flip(gasPrice);438 await flip(gasPrice * 2n);439 await flip(gasPrice * 21n / 10n);440 await flip(gasPrice * 22n / 10n, false);441 });442});443444describe('Sponsoring Fee Limit', () => {445 let donor: IKeyringPair;446 let alice: IKeyringPair;447 let testContract: CompiledContract;448449 async function compileTestContract(helper: EthUniqueHelper) {450 if(!testContract) {451 testContract = await helper.ethContract.compile(452 'TestContract',453 `454 // SPDX-License-Identifier: MIT455 pragma solidity ^0.8.0;456457 contract TestContract {458 event Result(bool);459460 function test(uint32 cycles) public {461 uint256 counter = 0;462 while(true) {463 counter ++;464 if (counter > cycles){465 break;466 }467 }468 emit Result(true);469 }470 }471 `,472 );473 }474 return testContract;475 }476477 async function deployTestContract(helper: EthUniqueHelper, owner: string) {478 const compiled = await compileTestContract(helper);479 return await helper.ethContract.deployByAbi(owner, compiled.abi, compiled.object);480 }481482 before(async () => {483 await usingEthPlaygrounds(async (helper, privateKey) => {484 donor = await privateKey({url: import.meta.url});485 [alice] = await helper.arrange.createAccounts([100n], donor);486 });487 });488489 itEth('Default fee limit', async ({helper}) => {490 const owner = await helper.eth.createAccountWithBalance(donor);491 const helpers = await helper.ethNativeContract.contractHelpers(owner);492 const flipper = await helper.eth.deployFlipper(owner);493494 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equal('115792089237316195423570985008687907853269984665640564039457584007913129639935');495 });496497 itEth('Set fee limit', async ({helper}) => {498 const owner = await helper.eth.createAccountWithBalance(donor);499 const helpers = await helper.ethNativeContract.contractHelpers(owner);500 const flipper = await helper.eth.deployFlipper(owner);501502 await helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send();503 expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equal('100');504 });505506 itEth('Negative test - set fee limit by non-owner', async ({helper}) => {507 const owner = await helper.eth.createAccountWithBalance(donor);508 const stranger = await helper.eth.createAccountWithBalance(donor);509 const helpers = await helper.ethNativeContract.contractHelpers(owner);510 const flipper = await helper.eth.deployFlipper(owner);511512 await expect(helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send({from: stranger})).to.be.rejected;513 });514515 itEth('Negative test - check that eth transactions exceeding fee limit are not executed', async ({helper}) => {516 const owner = await helper.eth.createAccountWithBalance(donor);517 const sponsor = await helper.eth.createAccountWithBalance(donor);518 const user = await helper.eth.createAccountWithBalance(donor);519 const helpers = helper.ethNativeContract.contractHelpers(owner);520521 const testContract = await deployTestContract(helper, owner);522523 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});524 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});525526 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();527 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});528529 const gasPrice = BigInt(await helper.getWeb3().eth.getGasPrice());530531 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();532533 const originalUserBalance = await helper.balance.getEthereum(user);534 await testContract.methods.test(100).send({from: user, gas: 2_000_000, maxFeePerGas: gasPrice.toString()});535 expect(await helper.balance.getEthereum(user)).to.be.equal(originalUserBalance);536537 await testContract.methods.test(100).send({from: user, gas: 2_100_000, maxFeePerGas: gasPrice.toString()});538 expect(await helper.balance.getEthereum(user)).to.not.be.equal(originalUserBalance);539 });540541 itEth('Negative test - check that evm.call transactions exceeding fee limit are not executed', async ({helper}) => {542 const owner = await helper.eth.createAccountWithBalance(donor);543 const sponsor = await helper.eth.createAccountWithBalance(donor);544 const helpers = await helper.ethNativeContract.contractHelpers(owner);545546 const testContract = await deployTestContract(helper, owner);547548 await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});549 await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});550551 await helpers.methods.setSponsor(testContract.options.address, sponsor).send();552 await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});553554 const gasPrice = BigInt(await helper.getWeb3().eth.getGasPrice());555556 await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();557558 const originalAliceBalance = await helper.balance.getSubstrate(alice.address);559560 await helper.eth.sendEVM(561 alice,562 testContract.options.address,563 testContract.methods.test(100).encodeABI(),564 '0',565 2_000_000,566 );567 568 expect(await helper.balance.getSubstrate(alice.address)).to.be.equal(originalAliceBalance);569570 await helper.eth.sendEVM(571 alice,572 testContract.options.address,573 testContract.methods.test(100).encodeABI(),574 '0',575 2_100_000,576 );577 expect(await helper.balance.getSubstrate(alice.address)).to.not.be.equal(originalAliceBalance);578 });579});