git.delta.rocks / unique-network / refs/commits / c0e5e7725f2a

difftreelog

source

tests/src/eth/contractSponsoring.test.ts26.9 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {IKeyringPair} from '@polkadot/types/types';18import {EthUniqueHelper} from './util/playgrounds/unique.dev';19import {itEth, expect, SponsoringMode, usingEthPlaygrounds} from './util';20import {usingPlaygrounds} from '../util';21import {CompiledContract} from './util/playgrounds/types';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({filename: __filename});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    // 1. owner can set selfSponsoring: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    // 1.1 Can get sponsor using methods.sponsor: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    // 2. Events should be: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    // 1. owner can set a sponsor: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    // 2. Events should be: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    // 1. sponsor can confirm sponsorship: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    // 1.1 Can get sponsor using methods.sponsor: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    // 2. Events should be: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    // 1. Can remove sponsor: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    // 2. Events should be: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    // TODO: why call method reverts?227    // const actualSponsor = await helpers.methods.sponsor(flipper.options.address).call();228    // expect(actualSponsor.eth).to.eq(sponsor);229    // expect(actualSponsor.sub).to.eq('0');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    // Balance should be taken from sponsor instead of caller269    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    // Balance should be taken from sponsor instead of caller295    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      // Balance should be taken from flipper instead of caller329      const sponsorBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(sponsor));330      expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;331      // Caller's balance does not change: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    // Deploy flipper and send some tokens: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    // flipper address has some tokens:347    const originalFlipperBalance = await helper.balance.getEthereum(flipper.options.address);348    expect(originalFlipperBalance > 0n).to.be.true;349350    // Set Allowlisted sponsoring mode. caller is not in allow list: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    // 1. Caller has no UNQ and is not in allow list. So he cannot flip: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    // Flipper's balance does not change: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    // todo:playgrounds fails rarely (expected 99893341659775672580n to equal 99912598679356033129n) (again, 99893341659775672580n)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  // TODO: Find a way to calculate default rate limit398  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  });405});406407describe('Sponsoring Fee Limit', () => {408  let donor: IKeyringPair;409  let alice: IKeyringPair;410  let testContract: CompiledContract;411412  async function compileTestContract(helper: EthUniqueHelper) {413    if (!testContract) {414      testContract = await helper.ethContract.compile(415        'TestContract',416        `417        // SPDX-License-Identifier: MIT418        pragma solidity ^0.8.0;419420        contract TestContract {421          event Result(bool);422423          function test(uint32 cycles) public {424            uint256 counter = 0;425            while(true) {426              counter ++;427              if (counter > cycles){428                break;429              }430            }431            emit Result(true);432          }433        }434      `,435      );436    }437    return testContract;438  }439440  async function deployTestContract(helper: EthUniqueHelper, owner: string) {441    const compiled = await compileTestContract(helper);442    return await helper.ethContract.deployByAbi(owner, compiled.abi, compiled.object);443  }444445  before(async () => {446    await usingEthPlaygrounds(async (helper, privateKey) => {447      donor = await privateKey({filename: __filename});448      [alice] = await helper.arrange.createAccounts([100n], donor);449    });450  });451452  itEth('Default fee limit', async ({helper}) => {453    const owner = await helper.eth.createAccountWithBalance(donor);454    const helpers = await helper.ethNativeContract.contractHelpers(owner);455    const flipper = await helper.eth.deployFlipper(owner);456457    expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equal('115792089237316195423570985008687907853269984665640564039457584007913129639935');458  });459460  itEth('Set fee limit', async ({helper}) => {461    const owner = await helper.eth.createAccountWithBalance(donor);462    const helpers = await helper.ethNativeContract.contractHelpers(owner);463    const flipper = await helper.eth.deployFlipper(owner);464465    await helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send();466    expect(await helpers.methods.sponsoringFeeLimit(flipper.options.address).call()).to.be.equal('100');467  });468469  itEth('Negative test - set fee limit by non-owner', async ({helper}) => {470    const owner = await helper.eth.createAccountWithBalance(donor);471    const stranger = await helper.eth.createAccountWithBalance(donor);472    const helpers = await helper.ethNativeContract.contractHelpers(owner);473    const flipper = await helper.eth.deployFlipper(owner);474475    await expect(helpers.methods.setSponsoringFeeLimit(flipper.options.address, 100).send({from: stranger})).to.be.rejected;476  });477478  itEth('Negative test - check that eth transactions exceeding fee limit are not executed', async ({helper}) => {479    const owner = await helper.eth.createAccountWithBalance(donor);480    const sponsor = await helper.eth.createAccountWithBalance(donor);481    const user = await helper.eth.createAccountWithBalance(donor);482    const helpers = await helper.ethNativeContract.contractHelpers(owner);483484    const testContract = await deployTestContract(helper, owner);485486    await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});487    await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});488489    await helpers.methods.setSponsor(testContract.options.address, sponsor).send();490    await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});491492    const gasPrice = BigInt(await helper.getWeb3().eth.getGasPrice());493494    await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();495496    const originalUserBalance = await helper.balance.getEthereum(user);497    await testContract.methods.test(100).send({from: user, gas: 2_000_000});498    expect(await helper.balance.getEthereum(user)).to.be.equal(originalUserBalance);499500    await testContract.methods.test(100).send({from: user, gas: 2_100_000});501    expect(await helper.balance.getEthereum(user)).to.not.be.equal(originalUserBalance);502  });503504  itEth('Negative test - check that evm.call transactions exceeding fee limit are not executed', async ({helper}) => {505    const owner = await helper.eth.createAccountWithBalance(donor);506    const sponsor = await helper.eth.createAccountWithBalance(donor);507    const helpers = await helper.ethNativeContract.contractHelpers(owner);508509    const testContract = await deployTestContract(helper, owner);510511    await helpers.methods.setSponsoringMode(testContract.options.address, SponsoringMode.Generous).send({from: owner});512    await helpers.methods.setSponsoringRateLimit(testContract.options.address, 0).send({from: owner});513514    await helpers.methods.setSponsor(testContract.options.address, sponsor).send();515    await helpers.methods.confirmSponsorship(testContract.options.address).send({from: sponsor});516517    const gasPrice = BigInt(await helper.getWeb3().eth.getGasPrice());518519    await helpers.methods.setSponsoringFeeLimit(testContract.options.address, 2_000_000n * gasPrice).send();520521    const originalAliceBalance = await helper.balance.getSubstrate(alice.address);522523    await helper.eth.sendEVM(524      alice,525      testContract.options.address,526      testContract.methods.test(100).encodeABI(),527      '0',528      2_000_000,529    );530    // expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.be.equal(originalAliceBalance);531    expect(await helper.balance.getSubstrate(alice.address)).to.be.equal(originalAliceBalance);532533    await helper.eth.sendEVM(534      alice,535      testContract.options.address,536      testContract.methods.test(100).encodeABI(),537      '0',538      2_100_000,539    );540    expect(await helper.balance.getSubstrate(alice.address)).to.not.be.equal(originalAliceBalance);541  });542});