difftreelog
test also check flipper balance in sponsoring
in: master
1 file changed
tests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth1// 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 privateKey from '../substrate/privateKey';18import {expect} from 'chai';19import {20 contractHelpers,21 createEthAccountWithBalance,22 transferBalanceToEth,23 deployFlipper,24 itWeb3,25 SponsoringMode,26 createEthAccount,27 collectionIdToAddress,28 GAS_ARGS,29 normalizeEvents,30 subToEth,31 executeEthTxOnSub,32} from './util/helpers';33import {34 addCollectionAdminExpectSuccess,35 createCollectionExpectSuccess,36 getCreateCollectionResult,37 transferBalanceTo,38} from '../util/helpers';39import nonFungibleAbi from './nonFungibleAbi.json';40import {41 submitTransactionAsync,42} from '../substrate/substrate-api';43import getBalance from '../substrate/get-balance';44import {alicesPublicKey} from '../accounts';4546describe('Sponsoring EVM contracts', () => {47 itWeb3('Sponsoring can be set by the address that has deployed the contract', async ({api, web3}) => {48 const owner = await createEthAccountWithBalance(api, web3);49 const flipper = await deployFlipper(web3, owner);50 const helpers = contractHelpers(web3, owner);51 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;52 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});53 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;54 });5556 itWeb3('Sponsoring cannot be set by the address that did not deployed the contract', async ({api, web3}) => {57 const owner = await createEthAccountWithBalance(api, web3);58 const notOwner = await createEthAccountWithBalance(api, web3);59 const flipper = await deployFlipper(web3, owner);60 const helpers = contractHelpers(web3, owner);61 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;62 await expect(helpers.methods.setSponsoringMode(notOwner, SponsoringMode.Allowlisted).send({from: notOwner})).to.rejected;63 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;64 });6566 itWeb3('In generous mode, non-allowlisted user transaction will be sponsored', async ({api, web3}) => {67 const alice = privateKey('//Alice');6869 const owner = await createEthAccountWithBalance(api, web3);70 const caller = await createEthAccountWithBalance(api, web3);7172 const flipper = await deployFlipper(web3, owner);7374 const helpers = contractHelpers(web3, owner);7576 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;77 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: owner});78 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});79 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;8081 await transferBalanceToEth(api, alice, flipper.options.address);8283 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);84 expect(originalFlipperBalance).to.be.not.equal('0');8586 await flipper.methods.flip().send({from: caller});87 expect(await flipper.methods.getValue().call()).to.be.true;8889 // Balance should be taken from flipper instead of caller90 const balanceAfter = await web3.eth.getBalance(flipper.options.address);91 expect(+balanceAfter).to.be.lessThan(+originalFlipperBalance);92 });9394 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}) => {95 const alice = privateKey('//Alice');9697 const owner = await createEthAccountWithBalance(api, web3);98 const caller = createEthAccount(web3);99100 const flipper = await deployFlipper(web3, owner);101102 const helpers = contractHelpers(web3, owner);103 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});104 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});105106 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;107 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});108 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});109 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;110111 await transferBalanceToEth(api, alice, flipper.options.address);112113 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);114 expect(originalFlipperBalance).to.be.not.equal('0');115116 await flipper.methods.flip().send({from: caller});117 expect(await flipper.methods.getValue().call()).to.be.true;118119 // Balance should be taken from flipper instead of caller120 const balanceAfter = await web3.eth.getBalance(flipper.options.address);121 expect(+balanceAfter).to.be.lessThan(+originalFlipperBalance);122 });123124 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}) => {125 const alice = privateKey('//Alice');126127 const owner = await createEthAccountWithBalance(api, web3);128 const caller = createEthAccount(web3);129130 const flipper = await deployFlipper(web3, owner);131132 const helpers = contractHelpers(web3, owner);133134 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;135 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});136 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});137 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;138139 await transferBalanceToEth(api, alice, flipper.options.address);140141 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);142 expect(originalFlipperBalance).to.be.not.equal('0');143144 await expect(flipper.methods.flip().send({from: caller})).to.be.rejectedWith(/InvalidTransaction::Payment/);145 expect(await flipper.methods.getValue().call()).to.be.false;146147 // Balance should be taken from flipper instead of caller148 const balanceAfter = await web3.eth.getBalance(flipper.options.address);149 expect(+balanceAfter).to.be.equals(+originalFlipperBalance);150 });151152 itWeb3('Sponsoring is set, an address that has UNQ can send a transaction and it works. User balance should not change', async ({api, web3}) => {153 const alice = privateKey('//Alice');154155 const owner = await createEthAccountWithBalance(api, web3);156 const caller = await createEthAccountWithBalance(api, web3);157 const originalCallerBalance = await web3.eth.getBalance(caller);158159 const flipper = await deployFlipper(web3, owner);160161 const helpers = contractHelpers(web3, owner);162 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});163 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});164165 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;166 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});167 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: owner});168 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;169170 await transferBalanceToEth(api, alice, flipper.options.address);171172 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);173 expect(originalFlipperBalance).to.be.not.equal('0');174175 await flipper.methods.flip().send({from: caller});176 expect(await flipper.methods.getValue().call()).to.be.true;177178 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);179 });180181 itWeb3('Sponsoring is limited, with setContractRateLimit. The limitation is working if transactions are sent more often, the sender pays the commission.', async ({api, web3}) => {182 const alice = privateKey('//Alice');183184 const owner = await createEthAccountWithBalance(api, web3);185 const caller = await createEthAccountWithBalance(api, web3);186 const originalCallerBalance = await web3.eth.getBalance(caller);187188 const flipper = await deployFlipper(web3, owner);189190 const helpers = contractHelpers(web3, owner);191 await helpers.methods.toggleAllowlist(flipper.options.address, true).send({from: owner});192 await helpers.methods.toggleAllowed(flipper.options.address, caller, true).send({from: owner});193194 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.false;195 await helpers.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Allowlisted).send({from: owner});196 await helpers.methods.setSponsoringRateLimit(flipper.options.address, 10).send({from: owner});197 expect(await helpers.methods.sponsoringEnabled(flipper.options.address).call()).to.be.true;198199 await transferBalanceToEth(api, alice, flipper.options.address);200201 const originalFlipperBalance = await web3.eth.getBalance(flipper.options.address);202 expect(originalFlipperBalance).to.be.not.equal('0');203204 await flipper.methods.flip().send({from: caller});205 expect(await flipper.methods.getValue().call()).to.be.true;206 expect(await web3.eth.getBalance(caller)).to.be.equals(originalCallerBalance);207208 await flipper.methods.flip().send({from: caller});209 expect(await web3.eth.getBalance(caller)).to.be.not.equals(originalCallerBalance);210 });211212 // TODO: Find a way to calculate default rate limit213 itWeb3('Default rate limit equals 7200', async ({api, web3}) => {214 const owner = await createEthAccountWithBalance(api, web3);215 const flipper = await deployFlipper(web3, owner);216 const helpers = contractHelpers(web3, owner);217 expect(await helpers.methods.getSponsoringRateLimit(flipper.options.address).call()).to.be.equals('7200');218 });219220 itWeb3('Sponsoring evm address from substrate collection', async ({api, web3}) => {221 const owner = privateKey('//Alice');222 const userEth = createEthAccount(web3);223 const collectionId = await createCollectionExpectSuccess();224225 {226 const tx = api.tx.unique.setCollectionSponsor(collectionId, owner.address);227 const events = await submitTransactionAsync(owner, tx);228 const result = getCreateCollectionResult(events);229 expect(result.success).to.be.true;230 }231 {232 const tx = api.tx.unique.confirmSponsorship(collectionId);233 const events = await submitTransactionAsync(owner, tx);234 const result = getCreateCollectionResult(events);235 expect(result.success).to.be.true;236 }237238 const address = collectionIdToAddress(collectionId);239 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: userEth, ...GAS_ARGS});240241 { // This part should fail, because user not in access list and user have no money242 const nextTokenId = await contract.methods.nextTokenId().call();243 expect(nextTokenId).to.be.equal('1');244 await expect(contract.methods.mintWithTokenURI(245 userEth,246 nextTokenId,247 'Test URI',248 ).call({from: userEth})).to.be.rejectedWith(/PublicMintingNotAllowed/);249 }250251 {252 const tx = api.tx.unique.setPublicAccessMode(collectionId, 'AllowList');253 const events = await submitTransactionAsync(owner, tx);254 const result = getCreateCollectionResult(events);255 expect(result.success).to.be.true;256 }257 {258 const tx = api.tx.unique.addToAllowList(collectionId, {Ethereum: userEth});259 const events = await submitTransactionAsync(owner, tx);260 const result = getCreateCollectionResult(events);261 expect(result.success).to.be.true;262 }263 {264 const tx = api.tx.unique.setMintPermission(collectionId, true);265 const events = await submitTransactionAsync(owner, tx);266 const result = getCreateCollectionResult(events);267 expect(result.success).to.be.true;268 }269270 const [alicesBalanceBefore] = await getBalance(api, [alicesPublicKey]);271272 {273 const nextTokenId = await contract.methods.nextTokenId().call();274 expect(nextTokenId).to.be.equal('1');275 const result = await contract.methods.mintWithTokenURI(276 userEth,277 nextTokenId,278 'Test URI',279 ).send({from: userEth});280 const events = normalizeEvents(result.events);281282 expect(events).to.be.deep.equal([283 {284 address,285 event: 'Transfer',286 args: {287 from: '0x0000000000000000000000000000000000000000',288 to: userEth,289 tokenId: nextTokenId,290 },291 },292 ]);293294 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');295 }296297 const [alicesBalanceAfter] = await getBalance(api, [alicesPublicKey]);298 expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;299 });300301302 itWeb3('Check that transaction via EVM spend money from substrate address', async ({api, web3}) => {303 const owner = privateKey('//Alice');304 const user = privateKey(`//User/${Date.now()}`);305 const userEth = subToEth(user.address);306 const collectionId = await createCollectionExpectSuccess();307 await addCollectionAdminExpectSuccess(owner, collectionId, {Ethereum: userEth});308 await transferBalanceTo(api, owner, user.address);309310 const address = collectionIdToAddress(collectionId);311 const contract = new web3.eth.Contract(nonFungibleAbi as any, address, {from: userEth, ...GAS_ARGS});312313 const [userBalanceBefore] = await getBalance(api, [user.address]);314315 {316 const nextTokenId = await contract.methods.nextTokenId().call();317 expect(nextTokenId).to.be.equal('1');318 await executeEthTxOnSub(web3, api, user, contract, m => m.mintWithTokenURI(319 userEth,320 nextTokenId,321 'Test URI',322 ));323324 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');325 }326327 const [userBalanceAfter] = await getBalance(api, [user.address]);328 expect(userBalanceAfter < userBalanceBefore).to.be.true;329 });330});