git.delta.rocks / unique-network / refs/commits / 9f2f03a30137

difftreelog

source

tests/src/eth/contractSponsoring.test.ts28.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({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    // 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  });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    // expect((await api.query.system.account(alice.address)).data.free.toBigInt()).to.be.equal(originalAliceBalance);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});