difftreelog
style(Scheduler) removed unlikely to be used commented chunks of code
in: master
3 files changed
pallets/scheduler/src/lib.rsdiffbeforeafterboth--- a/pallets/scheduler/src/lib.rs
+++ b/pallets/scheduler/src/lib.rs
@@ -159,15 +159,6 @@
/// The location of a scheduled task that can be used to remove it.
pub type TaskAddress<BlockNumber> = (BlockNumber, u32);
-/*#[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq))] todo remove completely?
-#[derive(Clone, RuntimeDebug, Encode, Decode)]
-struct ScheduledV1<Call, BlockNumber> {
- maybe_id: Option<Vec<u8>>,
- priority: schedule::Priority,
- call: Call,
- maybe_periodic: Option<schedule::Period<BlockNumber>>,
-}*/
-
/// Information regarding an item to be executed in the future.
#[cfg_attr(any(feature = "std", test), derive(PartialEq, Eq))]
#[derive(Clone, RuntimeDebug, Encode, Decode, TypeInfo)]
@@ -185,27 +176,8 @@
/// The information regarding the call's preparation for dispatch, in particular the fee, to be sent to post-dispatch.
pre_dispatch: PreDispatch,
_phantom: PhantomData<AccountId>,
-}
-
-/// The current version of Scheduled struct.
-/*pub type Scheduled<Call, BlockNumber, PalletsOrigin, AccountId, PreDispatch> =
- ScheduledV2<Call, BlockNumber, PalletsOrigin, AccountId, PreDispatch>;*/
-
-// A value placed in storage that represents the current version of the Scheduler storage.
-// This value is used by the `on_runtime_upgrade` logic to determine whether we run
-// storage migration logic.
-/*#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo)] todo remove completely?
-enum Releases {
- V1,
- V2,
}
-impl Default for Releases {
- fn default() -> Self {
- Releases::V1
- }
-}*/
-
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub struct CallSpec {
module: u32,
@@ -223,17 +195,9 @@
T::AccountId,
<<T as Config>::CallExecutor as DispatchCall<T, H160>>::Pre
>>>;
-
- /*pub SpecAgenda: map hasher(twox_64_concat) T::BlockNumber todo remove completely?
- => Vec<Option<CallSpec>>;*/
-
+
/// Lookup from identity to the block number and index of the task.
Lookup: map hasher(twox_64_concat) Vec<u8> => Option<TaskAddress<T::BlockNumber>>;
-
- // / Storage version of the pallet.
- // /
- // / New networks start with last version.
- //StorageVersion build(|_| Releases::V2): Releases; todo remove completely?
}
}
@@ -535,9 +499,9 @@
<<T as Config>::Origin as From<T::PalletsOrigin>>::from(origin.clone()).into(),
)
.unwrap_or_default(); // todo sponsoring doesn't work with the line below -- found sponsoring is already checked for in transaction_payment
- //let who_will_pay = T::SponsorshipHandler::get_sponsor(&sender, &call).unwrap_or(sender);
- //let sponsor = T::PalletsOrigin::from(system::RawOrigin::Signed(who_will_pay.clone()));
- //let r = call.clone().dispatch(sponsor.into());
+ //let who_will_pay = T::SponsorshipHandler::get_sponsor(&sender, &call).unwrap_or(sender);
+ //let sponsor = T::PalletsOrigin::from(system::RawOrigin::Signed(who_will_pay.clone()));
+ //let r = call.clone().dispatch(sponsor.into());
let pre_dispatch = match T::CallExecutor::pre_dispatch(sender.clone(), call.clone()) {
Ok(pre_dispatch) => pre_dispatch,
runtime/src/lib.rsdiffbeforeafterboth--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -811,19 +811,6 @@
type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
-/*fn get_signed_extra(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtra {
- (
- frame_system::CheckSpecVersion::<Runtime>::new(),
- frame_system::CheckGenesis::<Runtime>::new(),
- frame_system::CheckEra::<Runtime>::from(Era::Immortal),
- frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(
- from,
- )),
- frame_system::CheckWeight::<Runtime>::new(),
- ChargeTransactionPayment::new(0),
- )
-}*/
-
#[derive(Default, Encode, Decode, Clone, TypeInfo)]
pub struct SchedulerPreDispatch {
tip: Balance,
@@ -849,29 +836,12 @@
type Pre = SchedulerPreDispatch;
fn dispatch_call(
- //signer: <T as frame_system::Config>::AccountId,
pre_dispatch: Self::Pre,
call: <T as pallet_unq_scheduler::Config>::Call,
) -> Result<
Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
TransactionValidityError,
> {
- /*let dispatch_info = call.get_dispatch_info();
-
- let extrinsic = fp_self_contained::CheckedExtrinsic::<
- AccountId,
- Call,
- SignedExtra,
- SelfContainedSignedInfo,
- > {
- signed: CheckedSignature::<AccountId, SignedExtra, SelfContainedSignedInfo>::Signed(
- signer.clone().into(),
- get_signed_extra(signer.clone().into()),
- ),
- function: call.clone().into(),
- };
-
- extrinsic.apply::<Runtime>(&dispatch_info, 0)*/
let dispatch_info = call.get_dispatch_info();
let pre = (
pre_dispatch.tip,
tests/src/scheduler.test.tsdiffbeforeafterboth1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56import chai, { expect } from 'chai';7import chaiAsPromised from 'chai-as-promised';8import privateKey from './substrate/privateKey';9import {10 default as usingApi, 11 submitTransactionAsync,12 submitTransactionExpectFailAsync,13} from './substrate/substrate-api';14import {15 createItemExpectSuccess,16 createCollectionExpectSuccess,17 scheduleTransferExpectSuccess,18 scheduleTransferAndWaitExpectSuccess,19 setCollectionSponsorExpectSuccess,20 confirmSponsorshipExpectSuccess,21 findUnusedAddress,22 UNIQUE,23 enablePublicMintingExpectSuccess,24 addToAllowListExpectSuccess,25 waitNewBlocks,26 normalizeAccountId,27 getTokenOwner,28 getGenericResult,29 scheduleTransferFundsPeriodicExpectSuccess,30 setCollectionLimitsExpectSuccess,31 getDetailedCollectionInfo,32 getFreeBalance,33 confirmSponsorshipByKeyExpectSuccess,34} from './util/helpers';35import {IKeyringPair} from '@polkadot/types/types';36import {getBalanceSingle} from './substrate/get-balance';3738chai.use(chaiAsPromised);3940describe('Scheduling token and balance transfers', () => {41 let alice: IKeyringPair;42 let bob: IKeyringPair;4344 before(async() => {45 await usingApi(async () => {46 alice = privateKey('//Alice');47 bob = privateKey('//Bob');48 });49 });5051 it('Can schedule a transfer of an owned token with delay', async () => {52 await usingApi(async () => {53 // nft54 const nftCollectionId = await createCollectionExpectSuccess();55 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');56 await setCollectionSponsorExpectSuccess(nftCollectionId, alice.address);57 await confirmSponsorshipExpectSuccess(nftCollectionId);5859 await scheduleTransferAndWaitExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 4);60 });61 });6263 it('Can transfer funds periodically', async () => {64 await usingApi(async (api) => {65 const waitForBlocks = 4;66 const period = 2;67 await scheduleTransferFundsPeriodicExpectSuccess(1n * UNIQUE, alice, bob, waitForBlocks, period, 2);68 const bobsBalanceBefore = await getBalanceSingle(api, bob.address);6970 // discounting already waited-for operations71 await waitNewBlocks(waitForBlocks - 2);72 const bobsBalanceAfterFirst = await getBalanceSingle(api, bob.address);73 expect(bobsBalanceAfterFirst > bobsBalanceBefore).to.be.true;7475 await waitNewBlocks(period);76 const bobsBalanceAfterSecond = await getBalanceSingle(api, bob.address);77 expect(bobsBalanceAfterSecond > bobsBalanceAfterFirst).to.be.true;78 });79 });8081 it('Can sponsor scheduling a transaction', async () => {82 const collectionId = await createCollectionExpectSuccess();83 await setCollectionSponsorExpectSuccess(collectionId, bob.address);84 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');8586 await usingApi(async () => {87 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);8889 const aliceBalanceBefore = await getFreeBalance(alice);90 // no need to wait to check, fees must be deducted on scheduling, immediately91 await scheduleTransferExpectSuccess(collectionId, tokenId, alice, bob, 0, 4);92 const aliceBalanceAfter = await getFreeBalance(alice);93 expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true;94 });95 });9697 /*it('Can\'t schedule a transaction with no funds', async () => {98 await usingApi(async (api) => {99 // Find an empty, unused account100 const zeroBalance = await findUnusedAddress(api);101102 const collectionId = await createCollectionExpectSuccess();103 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');104105 await transferExpectSuccess(collectionId, tokenId, alice, zeroBalance);106107 await scheduleTransferAndWaitExpectSuccess(collectionId, tokenId, zeroBalance, alice, 1, 4);108 });109 });*/110111 it('Schedules and dispatches a transaction even if the caller has no funds at the time of the dispatch', async () => {112 await usingApi(async (api) => {113 // Find an empty, unused account114 const zeroBalance = await findUnusedAddress(api);115116 const collectionId = await createCollectionExpectSuccess();117118 // Add zeroBalance address to allow list119 await enablePublicMintingExpectSuccess(alice, collectionId);120 await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);121122 // Grace zeroBalance with money, enough to cover future transactions123 const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);124 await submitTransactionAsync(alice, balanceTx);125126 // Mint a fresh NFT127 const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT');128129 // Schedule transfer of the NFT a few blocks ahead130 const waitForBlocks = 5;131 await scheduleTransferExpectSuccess(collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks);132133 // Get rid of the account's funds before the scheduled transaction takes place134 const emptyBalanceTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); // do not null reserved?135 const sudoTx = api.tx.sudo.sudo(emptyBalanceTx as any);136 const events = await submitTransactionAsync(alice, sudoTx);137 expect(getGenericResult(events).success).to.be.true;138139 // Wait for a certain number of blocks, discarding the ones that already happened while accepting the late transactions140 await waitNewBlocks(waitForBlocks - 3);141142 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address));143 });144 });145146 /*it.skip('Going bankrupt after sponsoring a scheduled transaction does not nullify the transaction', async () => {147 await usingApi(async (api) => {148 // Find two empty, unused accounts149 const zeroBalance = await findUnusedAddress(api);150 const zeroBalanceSponsor = await findUnusedAddress(api);151152 const collectionId = await createCollectionExpectSuccess();153154 // Grace these with money, enough to cover future transactions155 const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);156 await submitTransactionAsync(alice, balanceTx);157158 // Grace these with money, enough to cover future transactions159 const balanceSponsorTx = api.tx.balances.transfer(zeroBalanceSponsor.address, 1n * UNIQUE);160 await submitTransactionAsync(alice, balanceSponsorTx);161162 // Set a collection sponsor163 await setCollectionSponsorExpectSuccess(collectionId, zeroBalanceSponsor.address);164 await confirmSponsorshipExpectSuccess(collectionId);165166 // Add zeroBalance address to allow list167 await enablePublicMintingExpectSuccess(alice, collectionId);168 await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);169170 // Mint a fresh NFT171 const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT');172173 // Schedule transfer of the NFT a few blocks ahead174 // const waitForBlocks = 4;175 await scheduleTransferExpectSuccess(collectionId, tokenId, zeroBalance, alice, 1, 4);176 //await waitAfterScheduleExpectSuccess(collectionId, tokenId, alice, 3);177178 // Get rid of the account's funds before the scheduled transaction takes place179 const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalanceSponsor.address, 0, 0);180 const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any);181 const events = await submitTransactionAsync(alice, sudoTx);182 expect(getGenericResult(events).success).to.be.true;183184 // Wait for a certain number of blocks, save for the ones that already happened while accepting the late transactions185 await waitNewBlocks(4);186187 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address));188 });189 });*/190191 it('Sponsor going bankrupt does not impact a scheduled transaction', async () => {192 const collectionId = await createCollectionExpectSuccess();193194 await usingApi(async (api) => {195 const zeroBalance = await findUnusedAddress(api);196197 /*await setCollectionLimitsExpectSuccess(alice, nftCollectionId, {198 sponsoredDataRateLimit: 2,199 });*/200 //console.log(await getDetailedCollectionInfo(api, nftCollectionId));201 const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);202 await submitTransactionAsync(alice, balanceTx);203204 await setCollectionSponsorExpectSuccess(collectionId, zeroBalance.address);205 await confirmSponsorshipByKeyExpectSuccess(collectionId, zeroBalance);206207 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);208209 await scheduleTransferExpectSuccess(collectionId, tokenId, alice, zeroBalance, 1, 5);210211 const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0);212 const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any);213 const events = await submitTransactionAsync(alice, sudoTx);214 expect(getGenericResult(events).success).to.be.true;215216 // Wait for a certain number of blocks, save for the ones that already happened while accepting the late transactions217 await waitNewBlocks(2);218219 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(zeroBalance.address));220 });221 });222});223224describe.skip('Scheduling EVM smart contracts', () => {225 let alice: IKeyringPair;226 let bob: IKeyringPair;227228 before(async() => {229 await usingApi(async () => {230 alice = privateKey('//Alice');231 bob = privateKey('//Bob');232 });233 });234235 // todo contract testing236 it.skip('NFT: Sponsoring of transfers is rate limited', async () => {237 const collectionId = await createCollectionExpectSuccess();238 await setCollectionSponsorExpectSuccess(collectionId, bob.address);239 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');240241 await usingApi(async (api) => {242 // Find unused address243 const zeroBalance = await findUnusedAddress(api);244245 // Mint token for alice246 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);247248 // Transfer this token from Alice to unused address and back249 // Alice to Zero gets sponsored250 const aliceToZero = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);251 const events1 = await submitTransactionAsync(alice, aliceToZero);252 const result1 = getGenericResult(events1);253254 // Second transfer should fail255 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();256 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);257 const badTransaction = async function () {258 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);259 };260 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');261 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();262263 // Try again after Zero gets some balance - now it should succeed264 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);265 await submitTransactionAsync(alice, balancetx);266 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);267 const result2 = getGenericResult(events2);268269 expect(result1.success).to.be.true;270 expect(result2.success).to.be.true;271 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);272 });273 });274});1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56import chai, {expect} from 'chai';7import chaiAsPromised from 'chai-as-promised';8import privateKey from './substrate/privateKey';9import {10 default as usingApi, 11 submitTransactionAsync,12 submitTransactionExpectFailAsync,13} from './substrate/substrate-api';14import {15 createItemExpectSuccess,16 createCollectionExpectSuccess,17 scheduleTransferExpectSuccess,18 scheduleTransferAndWaitExpectSuccess,19 setCollectionSponsorExpectSuccess,20 confirmSponsorshipExpectSuccess,21 findUnusedAddress,22 UNIQUE,23 enablePublicMintingExpectSuccess,24 addToAllowListExpectSuccess,25 waitNewBlocks,26 normalizeAccountId,27 getTokenOwner,28 getGenericResult,29 scheduleTransferFundsPeriodicExpectSuccess,30 getFreeBalance,31 confirmSponsorshipByKeyExpectSuccess,32} from './util/helpers';33import {IKeyringPair} from '@polkadot/types/types';34import {getBalanceSingle} from './substrate/get-balance';3536chai.use(chaiAsPromised);3738describe('Scheduling token and balance transfers', () => {39 let alice: IKeyringPair;40 let bob: IKeyringPair;4142 before(async() => {43 await usingApi(async () => {44 alice = privateKey('//Alice');45 bob = privateKey('//Bob');46 });47 });4849 it('Can schedule a transfer of an owned token with delay', async () => {50 await usingApi(async () => {51 // nft52 const nftCollectionId = await createCollectionExpectSuccess();53 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');54 await setCollectionSponsorExpectSuccess(nftCollectionId, alice.address);55 await confirmSponsorshipExpectSuccess(nftCollectionId);5657 await scheduleTransferAndWaitExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 4);58 });59 });6061 it('Can transfer funds periodically', async () => {62 await usingApi(async (api) => {63 const waitForBlocks = 4;64 const period = 2;65 await scheduleTransferFundsPeriodicExpectSuccess(1n * UNIQUE, alice, bob, waitForBlocks, period, 2);66 const bobsBalanceBefore = await getBalanceSingle(api, bob.address);6768 // discounting already waited-for operations69 await waitNewBlocks(waitForBlocks - 2);70 const bobsBalanceAfterFirst = await getBalanceSingle(api, bob.address);71 expect(bobsBalanceAfterFirst > bobsBalanceBefore).to.be.true;7273 await waitNewBlocks(period);74 const bobsBalanceAfterSecond = await getBalanceSingle(api, bob.address);75 expect(bobsBalanceAfterSecond > bobsBalanceAfterFirst).to.be.true;76 });77 });7879 it('Can sponsor scheduling a transaction', async () => {80 const collectionId = await createCollectionExpectSuccess();81 await setCollectionSponsorExpectSuccess(collectionId, bob.address);82 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');8384 await usingApi(async () => {85 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);8687 const aliceBalanceBefore = await getFreeBalance(alice);88 // no need to wait to check, fees must be deducted on scheduling, immediately89 await scheduleTransferExpectSuccess(collectionId, tokenId, alice, bob, 0, 4);90 const aliceBalanceAfter = await getFreeBalance(alice);91 expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true;92 });93 });9495 /*it('Can\'t schedule a transaction with no funds', async () => {96 await usingApi(async (api) => {97 // Find an empty, unused account98 const zeroBalance = await findUnusedAddress(api);99100 const collectionId = await createCollectionExpectSuccess();101 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');102103 await transferExpectSuccess(collectionId, tokenId, alice, zeroBalance);104105 await scheduleTransferAndWaitExpectSuccess(collectionId, tokenId, zeroBalance, alice, 1, 4);106 });107 });*/108109 it('Schedules and dispatches a transaction even if the caller has no funds at the time of the dispatch', async () => {110 await usingApi(async (api) => {111 // Find an empty, unused account112 const zeroBalance = await findUnusedAddress(api);113114 const collectionId = await createCollectionExpectSuccess();115116 // Add zeroBalance address to allow list117 await enablePublicMintingExpectSuccess(alice, collectionId);118 await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);119120 // Grace zeroBalance with money, enough to cover future transactions121 const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);122 await submitTransactionAsync(alice, balanceTx);123124 // Mint a fresh NFT125 const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT');126127 // Schedule transfer of the NFT a few blocks ahead128 const waitForBlocks = 5;129 await scheduleTransferExpectSuccess(collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks);130131 // Get rid of the account's funds before the scheduled transaction takes place132 const emptyBalanceTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); // do not null reserved?133 const sudoTx = api.tx.sudo.sudo(emptyBalanceTx as any);134 const events = await submitTransactionAsync(alice, sudoTx);135 expect(getGenericResult(events).success).to.be.true;136137 // Wait for a certain number of blocks, discarding the ones that already happened while accepting the late transactions138 await waitNewBlocks(waitForBlocks - 3);139140 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address));141 });142 });143144 it('Sponsor going bankrupt does not impact a scheduled transaction', async () => {145 const collectionId = await createCollectionExpectSuccess();146147 await usingApi(async (api) => {148 const zeroBalance = await findUnusedAddress(api);149150 /*await setCollectionLimitsExpectSuccess(alice, nftCollectionId, {151 sponsoredDataRateLimit: 2,152 });*/153 //console.log(await getDetailedCollectionInfo(api, nftCollectionId));154 const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);155 await submitTransactionAsync(alice, balanceTx);156157 await setCollectionSponsorExpectSuccess(collectionId, zeroBalance.address);158 await confirmSponsorshipByKeyExpectSuccess(collectionId, zeroBalance);159160 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);161162 await scheduleTransferExpectSuccess(collectionId, tokenId, alice, zeroBalance, 1, 5);163164 const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0);165 const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any);166 const events = await submitTransactionAsync(alice, sudoTx);167 expect(getGenericResult(events).success).to.be.true;168169 // Wait for a certain number of blocks, save for the ones that already happened while accepting the late transactions170 await waitNewBlocks(2);171172 expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(zeroBalance.address));173 });174 });175});176177describe.skip('Scheduling EVM smart contracts', () => {178 let alice: IKeyringPair;179 let bob: IKeyringPair;180181 before(async() => {182 await usingApi(async () => {183 alice = privateKey('//Alice');184 bob = privateKey('//Bob');185 });186 });187188 // todo contract testing189 it.skip('NFT: Sponsoring of transfers is rate limited', async () => {190 const collectionId = await createCollectionExpectSuccess();191 await setCollectionSponsorExpectSuccess(collectionId, bob.address);192 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');193194 await usingApi(async (api) => {195 // Find unused address196 const zeroBalance = await findUnusedAddress(api);197198 // Mint token for alice199 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);200201 // Transfer this token from Alice to unused address and back202 // Alice to Zero gets sponsored203 const aliceToZero = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);204 const events1 = await submitTransactionAsync(alice, aliceToZero);205 const result1 = getGenericResult(events1);206207 // Second transfer should fail208 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();209 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);210 const badTransaction = async function () {211 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);212 };213 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');214 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();215216 // Try again after Zero gets some balance - now it should succeed217 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);218 await submitTransactionAsync(alice, balancetx);219 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);220 const result2 = getGenericResult(events2);221222 expect(result1.success).to.be.true;223 expect(result2.success).to.be.true;224 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);225 });226 });227});