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 privateKey from './substrate/privateKey';23import {IKeyringPair} from '@polkadot/types/types';24import {25 createCollectionExpectSuccess,26 createItemExpectSuccess,27 getGenericResult,28 transferExpectSuccess,29 UNIQUE,30} from './util/helpers';3132import {default as waitNewBlocks} from './substrate/wait-new-blocks';33import {ApiPromise} from '@polkadot/api';3435chai.use(chaiAsPromised);36const expect = chai.expect;3738const TREASURY = '5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z';39const saneMinimumFee = 0.05;40const saneMaximumFee = 0.5;41const createCollectionDeposit = 100;4243let alice: IKeyringPair;44let bob: IKeyringPair;4546474849function skipInflationBlock(api: ApiPromise): Promise<void> {50 const promise = new Promise<void>(async (resolve) => {51 const blockInterval = (await api.consts.inflation.inflationBlockInterval).toNumber();52 const unsubscribe = await api.rpc.chain.subscribeNewHeads(head => {53 const currentBlock = head.number.toNumber();54 if (currentBlock % blockInterval < blockInterval - 10) {55 unsubscribe();56 resolve();57 } else {58 console.log(`Skipping inflation block, current block: ${currentBlock}`);59 }60 });61 });6263 return promise;64}6566describe('integration test: Fees must be credited to Treasury:', () => {67 before(async () => {68 await usingApi(async () => {69 alice = privateKey('//Alice');70 bob = privateKey('//Bob');71 });72 });7374 it('Total issuance does not change', async () => {75 await usingApi(async (api) => {76 await skipInflationBlock(api);77 await waitNewBlocks(api, 1);7879 const totalBefore = (await api.query.balances.totalIssuance()).toBigInt();8081 const alicePrivateKey = privateKey('//Alice');82 const amount = 1n;83 const transfer = api.tx.balances.transfer(bobsPublicKey, amount);8485 const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));8687 const totalAfter = (await api.query.balances.totalIssuance()).toBigInt();8889 expect(result.success).to.be.true;90 expect(totalAfter).to.be.equal(totalBefore);91 });92 });9394 it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => {95 await usingApi(async (api) => {96 await skipInflationBlock(api);97 await waitNewBlocks(api, 1);9899 const alicePrivateKey = privateKey('//Alice');100 const treasuryBalanceBefore: bigint = (await api.query.system.account(TREASURY)).data.free.toBigInt();101 const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();102103 const amount = 1n;104 const transfer = api.tx.balances.transfer(bobsPublicKey, amount);105 const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));106107 const treasuryBalanceAfter: bigint = (await api.query.system.account(TREASURY)).data.free.toBigInt();108 const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();109 const fee = aliceBalanceBefore - aliceBalanceAfter - amount;110 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;111112 expect(result.success).to.be.true;113 expect(treasuryIncrease).to.be.equal(fee);114 });115 });116117 it('Treasury balance increased by failed tx fee', async () => {118 await usingApi(async (api) => {119 120 await waitNewBlocks(api, 1);121122 const bobPrivateKey = privateKey('//Bob');123 const treasuryBalanceBefore = (await api.query.system.account(TREASURY)).data.free.toBigInt();124 const bobBalanceBefore = (await api.query.system.account(bobsPublicKey)).data.free.toBigInt();125126 const badTx = api.tx.balances.setBalance(alicesPublicKey, 0, 0);127 await expect(submitTransactionExpectFailAsync(bobPrivateKey, badTx)).to.be.rejected;128129 const treasuryBalanceAfter = (await api.query.system.account(TREASURY)).data.free.toBigInt();130 const bobBalanceAfter = (await api.query.system.account(bobsPublicKey)).data.free.toBigInt();131 const fee = bobBalanceBefore - bobBalanceAfter;132 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;133134 expect(treasuryIncrease).to.be.equal(fee);135 });136 });137138 it('NFT Transactions also send fees to Treasury', async () => {139 await usingApi(async (api) => {140 await skipInflationBlock(api);141 await waitNewBlocks(api, 1);142143 const treasuryBalanceBefore = (await api.query.system.account(TREASURY)).data.free.toBigInt();144 const aliceBalanceBefore = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();145146 await createCollectionExpectSuccess();147148 const treasuryBalanceAfter = (await api.query.system.account(TREASURY)).data.free.toBigInt();149 const aliceBalanceAfter = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();150 const fee = aliceBalanceBefore - aliceBalanceAfter;151 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;152153 expect(treasuryIncrease).to.be.equal(fee);154 });155 });156157 it('Fees are sane', async () => {158 await usingApi(async (api) => {159 await skipInflationBlock(api);160 await waitNewBlocks(api, 1);161162 const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();163164 await createCollectionExpectSuccess();165166 const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();167 const fee = aliceBalanceBefore - aliceBalanceAfter;168169 expect(fee / UNIQUE < BigInt(Math.ceil(saneMaximumFee + createCollectionDeposit))).to.be.true;170 expect(fee / UNIQUE < BigInt(Math.ceil(saneMinimumFee + createCollectionDeposit))).to.be.true;171 });172 });173174 it('NFT Transfer fee is close to 0.1 Unique', async () => {175 await usingApi(async (api) => {176 await skipInflationBlock(api);177 await waitNewBlocks(api, 1);178179 const collectionId = await createCollectionExpectSuccess();180 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');181182 const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();183 await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');184 const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();185186 const fee = Number(aliceBalanceBefore - aliceBalanceAfter) / Number(UNIQUE);187 const expectedTransferFee = 0.1;188 189 const tolerance = 0.001;190191 expect(Math.abs(fee - expectedTransferFee)).to.be.lessThan(tolerance);192 });193 });194195});