From f4c09d673ad5a3f9b12b38f5989becbb0dbe69a2 Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Mon, 21 Dec 2020 12:19:47 +0000 Subject: [PATCH] sending fees to treasury + integration test --- --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -315,7 +315,7 @@ type Balance = Balance; /// The ubiquitous event type. type Event = Event; - type DustRemoval = (); + type DustRemoval = Treasury; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); @@ -357,7 +357,7 @@ impl pallet_transaction_payment::Trait for Runtime { type Currency = pallet_balances::Module; - type OnTransactionPayment = (); + type OnTransactionPayment = Treasury; type TransactionByteFee = TransactionByteFee; type WeightToFee = IdentityFee; type FeeMultiplierUpdate = (); --- a/tests/package-lock.json +++ b/tests/package-lock.json @@ -13,13 +13,12 @@ "@polkadot/api-contract": "^2.3.1", "@polkadot/types": "^2.3.1", "@polkadot/util": "^3.4.1", - "@types/bn.js": "^4.11.6", + "bignumber.js": "^9.0.0", "chai-as-promised": "^7.1.1" }, "devDependencies": { "@polkadot/dev": "^0.52.11", "@polkadot/ts": "^0.3.41", - "@types/bn.js": "^4.11.6", "@types/chai": "^4.2.12", "@types/chai-as-promised": "^7.1.3", "@types/mocha": "^8.0.3", @@ -7114,6 +7113,14 @@ "node": "*" } }, + "node_modules/bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", @@ -34960,6 +34967,11 @@ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" + }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", --- a/tests/package.json +++ b/tests/package.json @@ -6,7 +6,6 @@ "devDependencies": { "@polkadot/dev": "^0.52.11", "@polkadot/ts": "^0.3.41", - "@types/bn.js": "^4.11.6", "@types/chai": "^4.2.12", "@types/chai-as-promised": "^7.1.3", "@types/mocha": "^8.0.3", @@ -27,7 +26,7 @@ "@polkadot/api-contract": "^2.3.1", "@polkadot/types": "^2.3.1", "@polkadot/util": "^3.4.1", - "@types/bn.js": "^4.11.6", + "bignumber.js": "^9.0.0", "chai-as-promised": "^7.1.1" }, "standard": { --- /dev/null +++ b/tests/src/crefitFeesToTreasury.test.ts @@ -0,0 +1,107 @@ +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api"; +import { alicesPublicKey, bobsPublicKey } from "./accounts"; +import privateKey from "./substrate/privateKey"; +import { BigNumber } from 'bignumber.js'; +import { createCollectionExpectSuccess, getGenericResult } from './util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + +const Treasury = "5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z"; +const saneMinimumFee = 0.0001; +const saneMaximumFee = 0.01; + +describe('integration test: Fees must be credited to Treasury:', () => { + it('Total issuance does not change', async () => { + await usingApi(async (api) => { + const totalBefore = new BigNumber((await api.query.balances.totalIssuance()).toString()); + + const alicePrivateKey = privateKey('//Alice'); + const amount = new BigNumber(1); + const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed()); + + const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer)); + + const totalAfter = new BigNumber((await api.query.balances.totalIssuance()).toString()); + + expect(result.success).to.be.true; + expect(totalAfter.toFixed()).to.be.equal(totalBefore.toFixed()); + }); + }); + + it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => { + await usingApi(async (api) => { + const alicePrivateKey = privateKey('//Alice'); + const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString()); + const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString()); + + const amount = new BigNumber(1); + const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed()); + const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer)); + + const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString()); + const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString()); + const fee = aliceBalanceBefore.minus(aliceBalanceAfter).minus(amount); + const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore); + + expect(result.success).to.be.true; + expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed()); + }); + }); + + it('Treasury balance increased by failed tx fee', async () => { + await usingApi(async (api) => { + const bobPrivateKey = privateKey('//Bob'); + const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString()); + const bobBalanceBefore = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString()); + + const badTx = api.tx.balances.setBalance(alicesPublicKey, 0, 0); + const result = getGenericResult(await submitTransactionAsync(bobPrivateKey, badTx)); + + const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString()); + const bobBalanceAfter = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString()); + const fee = bobBalanceBefore.minus(bobBalanceAfter); + const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore); + + expect(result.success).to.be.false; + expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed()); + }); + }); + + it('NFT Transactions also send fees to Treasury', async () => { + await usingApi(async (api) => { + const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString()); + const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString()); + + await createCollectionExpectSuccess('A', 'B', 'C', 'NFT'); + + const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString()); + const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString()); + const fee = aliceBalanceBefore.minus(aliceBalanceAfter); + const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore); + + expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed()); + }); + }); + + it('Fees are sane', async () => { + await usingApi(async (api) => { + const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString()); + const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString()); + + await createCollectionExpectSuccess('A', 'B', 'C', 'NFT'); + + const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString()); + const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString()); + const fee = aliceBalanceBefore.minus(aliceBalanceAfter); + const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore); + + expect(fee.dividedBy(1e15).toNumber()).to.be.lessThan(0.01); + expect(fee.dividedBy(1e15).toNumber()).to.be.greaterThan(0.0001); + }); + }); + +}); + --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -9,11 +9,28 @@ chai.use(chaiAsPromised); const expect = chai.expect; +type GenericResult = { + success: boolean, +}; + type CreateCollectionResult = { success: boolean, collectionId: number }; +export function getGenericResult(events: EventRecord[]): GenericResult { + let result: GenericResult = { + success: false + } + events.forEach(({ phase, event: { data, method, section } }) => { + // console.log(` ${phase}: ${section}.${method}:: ${data}`); + if (method == 'ExtrinsicSuccess') { + result.success = true; + } + }); + return result; +} + function getCreateCollectionResult(events: EventRecord[]): CreateCollectionResult { let success = false; let collectionId: number = 0; -- gitstuff