From 0cb5e99ca2ae9ae2e548c0116fc134af50f296ed Mon Sep 17 00:00:00 2001 From: Daniel Shiposha Date: Wed, 07 Sep 2022 09:50:21 +0000 Subject: [PATCH] draft: scheduler tx fees test --- --- a/runtime/common/scheduler.rs +++ b/runtime/common/scheduler.rs @@ -24,11 +24,14 @@ transaction_validity::TransactionValidityError, DispatchErrorWithPostInfo, DispatchError, }; -use crate::{Runtime, Call, Origin, Balances, ChargeTransactionPayment}; +use crate::{Runtime, Call, Origin, Balances}; use up_common::types::{AccountId, Balance}; use fp_self_contained::SelfContainedCall; use pallet_unique_scheduler::DispatchCall; +use pallet_transaction_payment::ChargeTransactionPayment; +type SponsorshipChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment; + /// The SignedExtension to the basic transaction logic. pub type SignedExtraScheduler = ( frame_system::CheckSpecVersion, @@ -36,6 +39,7 @@ frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, + ChargeTransactionPayment::, ); fn get_signed_extras(from: ::AccountId) -> SignedExtraScheduler { @@ -47,8 +51,7 @@ from, )), frame_system::CheckWeight::::new(), - // sponsoring transaction logic - // pallet_charge_transaction::ChargeTransactionPayment::::new(0), + ChargeTransactionPayment::::from(0), ) } @@ -100,7 +103,7 @@ count: u32, ) -> Result<(), DispatchError> { let dispatch_info = call.get_dispatch_info(); - let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0) + let weight: Balance = SponsorshipChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0) .saturating_mul(count.into()); >::reserve_named( @@ -116,7 +119,7 @@ call: ::Call, ) -> Result { let dispatch_info = call.get_dispatch_info(); - let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0); + let weight: Balance = SponsorshipChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0); Ok( >::unreserve_named( &id, --- a/tests/src/.outdated/eth/scheduling.test.ts +++ b/tests/src/.outdated/eth/scheduling.test.ts @@ -16,7 +16,7 @@ import {expect} from 'chai'; import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from '../../deprecated-helpers/eth/helpers'; -import {scheduleExpectSuccess, waitNewBlocks, requirePallets, Pallets} from '../../deprecated-helpers/helpers'; +import {makeScheduledId, scheduleAfter, waitNewBlocks, requirePallets, Pallets} from '../../deprecated-helpers/helpers'; // TODO mrshiposha update this test in #581 describe.skip('Scheduing EVM smart contracts', () => { @@ -25,6 +25,7 @@ }); itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => { + const scheduledId = await makeScheduledId(); const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper); const flipper = await deployFlipper(web3, deployer); const initialValue = await flipper.methods.getValue().call(); @@ -45,8 +46,17 @@ ); const waitForBlocks = 4; const periodBlocks = 2; + const repetitions = 2; - await scheduleExpectSuccess(tx, alice, waitForBlocks, '0x' + '0'.repeat(32), periodBlocks, 2); + await expect(scheduleAfter( + api, + tx, + alice, + waitForBlocks, + scheduledId, + periodBlocks, + repetitions, + )).to.not.be.rejected; expect(await flipper.methods.getValue().call()).to.be.equal(initialValue); await waitNewBlocks(waitForBlocks - 1); --- a/tests/src/.outdated/scheduler.test.ts +++ b/tests/src/.outdated/scheduler.test.ts @@ -33,6 +33,7 @@ enablePublicMintingExpectSuccess, addToAllowListExpectSuccess, waitNewBlocks, + makeScheduledId, normalizeAccountId, getTokenOwner, getGenericResult, @@ -45,19 +46,12 @@ requirePallets, Pallets, } from '../deprecated-helpers/helpers'; -import {IKeyringPair} from '@polkadot/types/types'; +import {IKeyringPair, SignatureOptions} from '@polkadot/types/types'; import {ApiPromise} from '@polkadot/api'; +import {objectSpread} from '@polkadot/util'; chai.use(chaiAsPromised); - -const scheduledIdBase: string = '0x' + '0'.repeat(31); -let scheduledIdSlider = 0; -// Loop scheduledId around 10. Unless there are concurrent tasks with long periods/repetitions, tests' tasks' ids shouldn't ovelap. -function makeScheduledId(): string { - return scheduledIdBase + ((scheduledIdSlider++) % 10); -} - // Check that there are no failing Dispatched events in the block function checkForFailedSchedulerEvents(api: ApiPromise, events: any[]) { return new Promise((res, rej) => { @@ -78,6 +72,13 @@ }); } +function makeSignOptions(api: ApiPromise): SignatureOptions { + return objectSpread( + {blockHash: api.genesisHash, genesisHash: api.genesisHash}, + {runtimeVersion: api.runtimeVersion, signedExtensions: api.registry.signedExtensions}, + ); +} + describe('Scheduling token and balance transfers', () => { let alice: IKeyringPair; let bob: IKeyringPair; @@ -96,20 +97,22 @@ await usingApi(async api => { const collectionId = await createCollectionExpectSuccess(); const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT'); + const scheduledId = await makeScheduledId(); - await scheduleTransferAndWaitExpectSuccess(api, collectionId, tokenId, alice, bob, 1, 4, makeScheduledId()); + await scheduleTransferAndWaitExpectSuccess(api, collectionId, tokenId, alice, bob, 1, 4, scheduledId); }); }); it('Can transfer funds periodically', async () => { await usingApi(async api => { + const scheduledId = await makeScheduledId(); const waitForBlocks = 1; const period = 2; const repetitions = 2; const amount = 1n * UNIQUE; - await scheduleTransferFundsExpectSuccess(api, amount, alice, bob, waitForBlocks, makeScheduledId(), period, repetitions); + await scheduleTransferFundsExpectSuccess(api, amount, alice, bob, waitForBlocks, scheduledId, period, repetitions); const bobsBalanceBefore = await getFreeBalance(bob); await waitNewBlocks(waitForBlocks + 1); @@ -134,7 +137,7 @@ await usingApi(async api => { const collectionId = await createCollectionExpectSuccess(); const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT'); - const scheduledId = makeScheduledId(); + const scheduledId = await makeScheduledId(); const waitForBlocks = 4; const amount = 1; @@ -154,7 +157,7 @@ const period = 3; const repetitions = 2; - const scheduledId = makeScheduledId(); + const scheduledId = await makeScheduledId(); const amount = 1n * UNIQUE; const bobsBalanceBefore = await getFreeBalance(bob); @@ -184,10 +187,8 @@ await requirePallets(this, [Pallets.TestUtils]); await usingApi(async api => { - const scheduledId = makeScheduledId(); + const scheduledId = await makeScheduledId(); const waitForBlocks = 4; - const period = null; - const priority = 0; const initTestVal = 42; const changedTestVal = 111; @@ -197,17 +198,15 @@ const changeErrTx = api.tx.testUtils.setTestValueAndRollback(changedTestVal); - const scheduleTx = api.tx.scheduler.scheduleNamedAfter( + await expect(scheduleAfter( + api, + changeErrTx, + alice, + waitForBlocks, scheduledId, - waitForBlocks, - period, - priority, - {Value: changeErrTx as any}, - ); - - await submitTransactionAsync(alice, scheduleTx); + )).to.not.be.rejected; - await waitNewBlocks(waitForBlocks); + await waitNewBlocks(waitForBlocks + 1); const testVal = (await api.query.testUtils.testValue()).toNumber(); expect(testVal, 'The test value should NOT be commited') @@ -216,18 +215,30 @@ }); }); - it('Scheduled tasks should take some fees', async function() { + it.only('Scheduled tasks should take some fees', async function() { await requirePallets(this, [Pallets.TestUtils]); await usingApi(async api => { - const scheduledId = makeScheduledId(); - const waitForBlocks = 10; + const scheduledId = await makeScheduledId(); + const waitForBlocks = 8; const period = 2; - const repetitions = 1; + const repetitions = 2; - const dummyTxFeeAmount = 100_000_000; + const dummyTx = api.tx.testUtils.justTakeFee(); + const expectedFee = (await dummyTx.paymentInfo(alice)).partialFee.toBigInt(); + const expFee = (await api.rpc.payment.queryFeeDetails(dummyTx.toHex())).inclusionFee.unwrap().toHuman(); + + console.log('>>>>>> expFee = ' + JSON.stringify(expFee)); + + // const collectionCreate = api.tx.unique.createCollectionEx({ + // name: 0, + // tokenPrefix: 0xfaf, + // }); - const dummyTx = api.tx.testUtils.justTakeFee(); + // const options = makeSignOptions(api); + // const signed = collectionCreate.sign(alice, options); + // const expFee2 = (await api.rpc.payment.queryFeeDetails(signed.toHex())).inclusionFee.unwrap().toHuman(); + // console.log('!!!!!!!!!!!! expFee2 = ' + JSON.stringify(expFee2)); await expect(scheduleAfter( api, @@ -239,10 +250,12 @@ repetitions, )).to.not.be.rejected; + await waitNewBlocks(1); + const aliceInitBalance = await getFreeBalance(alice); let diff; - await waitNewBlocks(waitForBlocks + 1); + await waitNewBlocks(waitForBlocks); const aliceBalanceAfterFirst = await getFreeBalance(alice); expect( @@ -251,7 +264,7 @@ ).to.be.true; diff = aliceInitBalance - aliceBalanceAfterFirst; - expect(diff).to.be.equal(dummyTxFeeAmount, 'Scheduled task should take the right amount of fees'); + expect(diff).to.be.equal(expectedFee, 'Scheduled task should take the right amount of fees'); await waitNewBlocks(period); @@ -262,14 +275,14 @@ ).to.be.true; diff = aliceBalanceAfterFirst - aliceBalanceAfterSecond; - expect(diff).to.be.equal(dummyTxFeeAmount, 'Scheduled task should take the right amount of fees'); + expect(diff).to.be.equal(expectedFee, 'Scheduled task should take the right amount of fees'); }); }); // FIXME What purpose of this test? it.skip('Can schedule a scheduled operation of canceling the scheduled operation', async () => { await usingApi(async api => { - const scheduledId = makeScheduledId(); + const scheduledId = await makeScheduledId(); const waitForBlocks = 2; const period = 3; @@ -323,7 +336,7 @@ await usingApi(async api => { const collectionId = await createCollectionExpectSuccess(); const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT'); - const scheduledId = makeScheduledId(); + const scheduledId = await makeScheduledId(); const waitForBlocks = 4; const amount = 1; @@ -338,7 +351,7 @@ const bobsBalanceBefore = await getFreeBalance(bob); - await waitNewBlocks(waitForBlocks); + await waitNewBlocks(waitForBlocks + 1); expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(bob.address)); expect(bobsBalanceBefore).to.be.equal(await getFreeBalance(bob)); @@ -347,7 +360,7 @@ it("Can't cancel an operation which is not scheduled", async () => { await usingApi(async api => { - const scheduledId = makeScheduledId(); + const scheduledId = await makeScheduledId(); await expect(cancelScheduled(api, alice, scheduledId)).to.be.rejectedWith(/scheduler\.NotFound/); }); }); @@ -356,7 +369,7 @@ await usingApi(async api => { const collectionId = await createCollectionExpectSuccess(); const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT'); - const scheduledId = makeScheduledId(); + const scheduledId = await makeScheduledId(); const waitForBlocks = 8; const amount = 1; @@ -364,7 +377,7 @@ await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, bob, amount, waitForBlocks, scheduledId); await expect(cancelScheduled(api, bob, scheduledId)).to.be.rejectedWith(/BadOrigin/); - await waitNewBlocks(waitForBlocks); + await waitNewBlocks(waitForBlocks + 1); expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(bob.address)); }); @@ -389,12 +402,13 @@ await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); await usingApi(async api => { + const scheduledId = await makeScheduledId(); const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address); const bobBalanceBefore = await getFreeBalance(bob); const waitForBlocks = 4; // no need to wait to check, fees must be deducted on scheduling, immediately - await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, bob, 0, waitForBlocks, makeScheduledId()); + await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, bob, 0, waitForBlocks, scheduledId); const bobBalanceAfter = await getFreeBalance(bob); // expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true; expect(bobBalanceAfter < bobBalanceBefore).to.be.true; @@ -420,10 +434,11 @@ // Mint a fresh NFT const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT'); + const scheduledId = await makeScheduledId(); // Schedule transfer of the NFT a few blocks ahead const waitForBlocks = 5; - await scheduleTransferExpectSuccess(api, collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks, makeScheduledId()); + await scheduleTransferExpectSuccess(api, collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks, scheduledId); // Get rid of the account's funds before the scheduled transaction takes place const balanceTx2 = api.tx.balances.transfer(alice.address, UNIQUE * 68n / 100n); @@ -452,10 +467,11 @@ await setCollectionSponsorExpectSuccess(collectionId, zeroBalance.address); await confirmSponsorshipByKeyExpectSuccess(collectionId, zeroBalance); + const scheduledId = await makeScheduledId(); const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address); const waitForBlocks = 5; - await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, zeroBalance, 1, waitForBlocks, makeScheduledId()); + await scheduleTransferExpectSuccess(api, collectionId, tokenId, alice, zeroBalance, 1, waitForBlocks, scheduledId); const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any); @@ -484,13 +500,14 @@ const createData = {nft: {const_data: [], variable_data: []}}; const creationTx = api.tx.unique.createItem(collectionId, normalizeAccountId(zeroBalance), createData as any); + const scheduledId = await makeScheduledId(); /*const badTransaction = async function () { await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice); }; await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');*/ - await expect(scheduleAfter(api, creationTx, zeroBalance, 3, makeScheduledId(), 1, 3)).to.be.rejectedWith(/Inability to pay some fees/); + await expect(scheduleAfter(api, creationTx, zeroBalance, 3, scheduledId, 1, 3)).to.be.rejectedWith(/Inability to pay some fees/); expect(await getFreeBalance(bob)).to.be.equal(bobBalanceBefore); }); --- a/tests/src/deprecated-helpers/helpers.ts +++ b/tests/src/deprecated-helpers/helpers.ts @@ -1260,15 +1260,9 @@ ) { const transferTx = api.tx.balances.transfer(recipient.address, amount); -<<<<<<< HEAD - const balanceBefore = await getFreeBalance(recipient); - - await scheduleExpectSuccess(transferTx, sender, blockSchedule, scheduledId, period, repetitions); -======= const balanceBefore = await getFreeBalance(recipient); await expect(scheduleAfter(api, transferTx, sender, blocksBeforeExecution, scheduledId, period, repetitions)).to.not.be.rejected; ->>>>>>> test(scheduler): enable and add more coverage, leave sponsorship disabled expect(await getFreeBalance(recipient)).to.be.equal(balanceBefore); } -- gitstuff