1234567891011121314151617import './interfaces/augment-api-consts';18import chai from 'chai';19import chaiAsPromised from 'chai-as-promised';20import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';21import {alicesPublicKey, bobsPublicKey} from './accounts';22import {IKeyringPair} from '@polkadot/types/types';23import {24 createCollectionExpectSuccess,25 createItemExpectSuccess,26 getGenericResult,27 transferExpectSuccess,28 UNIQUE,29} from './util/helpers';3031import {default as waitNewBlocks} from './substrate/wait-new-blocks';32import {ApiPromise} from '@polkadot/api';3334chai.use(chaiAsPromised);35const expect = chai.expect;3637const TREASURY = '5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z';38const saneMinimumFee = 0.05;39const saneMaximumFee = 0.5;40const createCollectionDeposit = 100;4142let alice: IKeyringPair;43let bob: IKeyringPair;4445464748function skipInflationBlock(api: ApiPromise): Promise<void> {49 const promise = new Promise<void>(async (resolve) => {50 const blockInterval = (await api.consts.inflation.inflationBlockInterval).toNumber();51 const unsubscribe = await api.rpc.chain.subscribeNewHeads(head => {52 const currentBlock = head.number.toNumber();53 if (currentBlock % blockInterval < blockInterval - 10) {54 unsubscribe();55 resolve();56 } else {57 console.log(`Skipping inflation block, current block: ${currentBlock}`);58 }59 });60 });6162 return promise;63}6465describe('integration test: Fees must be credited to Treasury:', () => {66 before(async () => {67 await usingApi(async (api, privateKeyWrapper) => {68 alice = privateKeyWrapper('//Alice');69 bob = privateKeyWrapper('//Bob');70 });71 });7273 it('Total issuance does not change', async () => {74 await usingApi(async (api, privateKeyWrapper) => {75 await skipInflationBlock(api);76 await waitNewBlocks(api, 1);7778 const totalBefore = (await api.query.balances.totalIssuance()).toBigInt();7980 const alicePrivateKey = privateKeyWrapper('//Alice');81 const amount = 1n;82 const transfer = api.tx.balances.transfer(bobsPublicKey, amount);8384 const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));8586 const totalAfter = (await api.query.balances.totalIssuance()).toBigInt();8788 expect(result.success).to.be.true;89 expect(totalAfter).to.be.equal(totalBefore);90 });91 });9293 it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => {94 await usingApi(async (api, privateKeyWrapper) => {95 await skipInflationBlock(api);96 await waitNewBlocks(api, 1);9798 const alicePrivateKey = privateKeyWrapper('//Alice');99 const treasuryBalanceBefore: bigint = (await api.query.system.account(TREASURY)).data.free.toBigInt();100 const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();101102 const amount = 1n;103 const transfer = api.tx.balances.transfer(bobsPublicKey, amount);104 const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));105106 const treasuryBalanceAfter: bigint = (await api.query.system.account(TREASURY)).data.free.toBigInt();107 const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();108 const fee = aliceBalanceBefore - aliceBalanceAfter - amount;109 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;110111 expect(result.success).to.be.true;112 expect(treasuryIncrease).to.be.equal(fee);113 });114 });115116 it('Treasury balance increased by failed tx fee', async () => {117 await usingApi(async (api, privateKeyWrapper) => {118 119 await waitNewBlocks(api, 1);120121 const bobPrivateKey = privateKeyWrapper('//Bob');122 const treasuryBalanceBefore = (await api.query.system.account(TREASURY)).data.free.toBigInt();123 const bobBalanceBefore = (await api.query.system.account(bobsPublicKey)).data.free.toBigInt();124125 const badTx = api.tx.balances.setBalance(alicesPublicKey, 0, 0);126 await expect(submitTransactionExpectFailAsync(bobPrivateKey, badTx)).to.be.rejected;127128 const treasuryBalanceAfter = (await api.query.system.account(TREASURY)).data.free.toBigInt();129 const bobBalanceAfter = (await api.query.system.account(bobsPublicKey)).data.free.toBigInt();130 const fee = bobBalanceBefore - bobBalanceAfter;131 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;132133 expect(treasuryIncrease).to.be.equal(fee);134 });135 });136137 it('NFT Transactions also send fees to Treasury', async () => {138 await usingApi(async (api) => {139 await skipInflationBlock(api);140 await waitNewBlocks(api, 1);141142 const treasuryBalanceBefore = (await api.query.system.account(TREASURY)).data.free.toBigInt();143 const aliceBalanceBefore = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();144145 await createCollectionExpectSuccess();146147 const treasuryBalanceAfter = (await api.query.system.account(TREASURY)).data.free.toBigInt();148 const aliceBalanceAfter = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();149 const fee = aliceBalanceBefore - aliceBalanceAfter;150 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;151152 expect(treasuryIncrease).to.be.equal(fee);153 });154 });155156 it('Fees are sane', async () => {157 await usingApi(async (api) => {158 await skipInflationBlock(api);159 await waitNewBlocks(api, 1);160161 const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();162163 await createCollectionExpectSuccess();164165 const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();166 const fee = aliceBalanceBefore - aliceBalanceAfter;167168 expect(fee / UNIQUE < BigInt(Math.ceil(saneMaximumFee + createCollectionDeposit))).to.be.true;169 expect(fee / UNIQUE < BigInt(Math.ceil(saneMinimumFee + createCollectionDeposit))).to.be.true;170 });171 });172173 it('NFT Transfer fee is close to 0.1 Unique', async () => {174 await usingApi(async (api) => {175 await skipInflationBlock(api);176 await waitNewBlocks(api, 1);177178 const collectionId = await createCollectionExpectSuccess();179 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');180181 const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();182 await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');183 const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();184185 const fee = Number(aliceBalanceBefore - aliceBalanceAfter) / Number(UNIQUE);186 const expectedTransferFee = 0.1;187 188 const tolerance = 0.001;189190 expect(Math.abs(fee - expectedTransferFee)).to.be.lessThan(tolerance);191 });192 });193194});