123456import './interfaces/augment-api-consts';7import chai from 'chai';8import chaiAsPromised from 'chai-as-promised';9import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';10import {alicesPublicKey, bobsPublicKey} from './accounts';11import privateKey from './substrate/privateKey';12import {IKeyringPair} from '@polkadot/types/types';13import {14 createCollectionExpectSuccess,15 createItemExpectSuccess,16 getGenericResult,17 transferExpectSuccess,18 UNIQUE,19} from './util/helpers';2021import {default as waitNewBlocks} from './substrate/wait-new-blocks';22import {ApiPromise} from '@polkadot/api';2324chai.use(chaiAsPromised);25const expect = chai.expect;2627const TREASURY = '5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z';28const saneMinimumFee = 0.05;29const saneMaximumFee = 0.5;30const createCollectionDeposit = 100;3132let alice: IKeyringPair;33let bob: IKeyringPair;3435363738function skipInflationBlock(api: ApiPromise): Promise<void> {39 const promise = new Promise<void>(async (resolve) => {40 const blockInterval = (await api.consts.inflation.inflationBlockInterval).toNumber();41 const unsubscribe = await api.rpc.chain.subscribeNewHeads(head => {42 const currentBlock = head.number.toNumber();43 if (currentBlock % blockInterval < blockInterval - 10) {44 unsubscribe();45 resolve();46 } else {47 console.log(`Skipping inflation block, current block: ${currentBlock}`);48 }49 });50 });5152 return promise;53}5455describe('integration test: Fees must be credited to Treasury:', () => {56 before(async () => {57 await usingApi(async () => {58 alice = privateKey('//Alice');59 bob = privateKey('//Bob');60 });61 });6263 it('Total issuance does not change', async () => {64 await usingApi(async (api) => {65 await skipInflationBlock(api);66 await waitNewBlocks(api, 1);6768 const totalBefore = (await api.query.balances.totalIssuance()).toBigInt();6970 const alicePrivateKey = privateKey('//Alice');71 const amount = 1n;72 const transfer = api.tx.balances.transfer(bobsPublicKey, amount);7374 const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));7576 const totalAfter = (await api.query.balances.totalIssuance()).toBigInt();7778 expect(result.success).to.be.true;79 expect(totalAfter).to.be.equal(totalBefore);80 });81 });8283 it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => {84 await usingApi(async (api) => {85 await skipInflationBlock(api);86 await waitNewBlocks(api, 1);8788 const alicePrivateKey = privateKey('//Alice');89 const treasuryBalanceBefore: bigint = (await api.query.system.account(TREASURY)).data.free.toBigInt();90 const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();9192 const amount = 1n;93 const transfer = api.tx.balances.transfer(bobsPublicKey, amount);94 const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));9596 const treasuryBalanceAfter: bigint = (await api.query.system.account(TREASURY)).data.free.toBigInt();97 const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();98 const fee = aliceBalanceBefore - aliceBalanceAfter - amount;99 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;100101 expect(result.success).to.be.true;102 expect(treasuryIncrease).to.be.equal(fee);103 });104 });105106 it('Treasury balance increased by failed tx fee', async () => {107 await usingApi(async (api) => {108 109 await waitNewBlocks(api, 1);110111 const bobPrivateKey = privateKey('//Bob');112 const treasuryBalanceBefore = (await api.query.system.account(TREASURY)).data.free.toBigInt();113 const bobBalanceBefore = (await api.query.system.account(bobsPublicKey)).data.free.toBigInt();114115 const badTx = api.tx.balances.setBalance(alicesPublicKey, 0, 0);116 await expect(submitTransactionExpectFailAsync(bobPrivateKey, badTx)).to.be.rejected;117118 const treasuryBalanceAfter = (await api.query.system.account(TREASURY)).data.free.toBigInt();119 const bobBalanceAfter = (await api.query.system.account(bobsPublicKey)).data.free.toBigInt();120 const fee = bobBalanceBefore - bobBalanceAfter;121 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;122123 expect(treasuryIncrease).to.be.equal(fee);124 });125 });126127 it('NFT Transactions also send fees to Treasury', async () => {128 await usingApi(async (api) => {129 await skipInflationBlock(api);130 await waitNewBlocks(api, 1);131132 const treasuryBalanceBefore = (await api.query.system.account(TREASURY)).data.free.toBigInt();133 const aliceBalanceBefore = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();134135 await createCollectionExpectSuccess();136137 const treasuryBalanceAfter = (await api.query.system.account(TREASURY)).data.free.toBigInt();138 const aliceBalanceAfter = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();139 const fee = aliceBalanceBefore - aliceBalanceAfter;140 const treasuryIncrease = treasuryBalanceAfter - treasuryBalanceBefore;141142 expect(treasuryIncrease).to.be.equal(fee);143 });144 });145146 it('Fees are sane', async () => {147 await usingApi(async (api) => {148 await skipInflationBlock(api);149 await waitNewBlocks(api, 1);150151 const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();152153 await createCollectionExpectSuccess();154155 const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();156 const fee = aliceBalanceBefore - aliceBalanceAfter;157158 expect(fee / UNIQUE < BigInt(Math.ceil(saneMaximumFee + createCollectionDeposit))).to.be.true;159 expect(fee / UNIQUE < BigInt(Math.ceil(saneMinimumFee + createCollectionDeposit))).to.be.true;160 });161 });162163 it('NFT Transfer fee is close to 0.1 Unique', async () => {164 await usingApi(async (api) => {165 await skipInflationBlock(api);166 await waitNewBlocks(api, 1);167168 const collectionId = await createCollectionExpectSuccess();169 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');170171 const aliceBalanceBefore: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();172 await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');173 const aliceBalanceAfter: bigint = (await api.query.system.account(alicesPublicKey)).data.free.toBigInt();174175 const fee = Number(aliceBalanceBefore - aliceBalanceAfter) / Number(UNIQUE);176 const expectedTransferFee = 0.1;177 178 const tolerance = 0.001;179180 expect(Math.abs(fee - expectedTransferFee)).to.be.lessThan(tolerance);181 });182 });183184});