git.delta.rocks / unique-network / refs/commits / 8d5b101bd644

difftreelog

Scheduler without sponsorship features

str-mv2022-04-12parent: #dce25d2.patch.diff
in: master

5 files changed

modifiedpallets/scheduler/src/lib.rsdiffbeforeafterboth
--- a/pallets/scheduler/src/lib.rs
+++ b/pallets/scheduler/src/lib.rs
@@ -361,7 +361,6 @@
 				} else {
 					false
 				};
-
 				let call = match s.call.as_value().cloned() {
 					Some(c) => c,
 					None => {
@@ -419,18 +418,18 @@
 				)
 				.unwrap();
 
-				// if call have id and periodic, it was be reserved
-				if s.maybe_id.is_some() && s.maybe_periodic.is_some() {
-					let _ = T::CallExecutor::pay_for_call(
-						s.maybe_id.unwrap(),
-						sender.clone(),
-						call.clone(),
-					);
-				}
+				// // if call have id it was be reserved
+				// if s.maybe_id.is_some() {
+				// 	let _ = T::CallExecutor::pay_for_call(
+				// 		s.maybe_id.unwrap(),
+				// 		sender.clone(),
+				// 		call.clone(),
+				// 	);
+				// }
 
 				let r = T::CallExecutor::dispatch_call(sender, call.clone());
 
-				let mut actual_call_weight: Weight = item_weight; //PostDispatchInfo;
+				let mut actual_call_weight: Weight = item_weight;
 				let result: Result<_, DispatchError> = match r {
 					Ok(o) => match o {
 						Ok(di) => {
@@ -472,7 +471,8 @@
 					Agenda::<T>::append(wake, Some(s));
 				}
 			}
-			total_weight
+			0
+			//total_weight
 		}
 	}
 
@@ -719,18 +719,18 @@
 		};
 
 		// reserve balance for periodic execution
-		let sender =
-			ensure_signed(<<T as Config>::Origin as From<T::PalletsOrigin>>::from(origin).into())?;
-		let repeats = match maybe_periodic {
-			Some(p) => p.1,
-			None => 0,
-		};
-		let _ = T::CallExecutor::reserve_balance(
-			id.clone(),
-			sender,
-			call.as_value().unwrap().clone(),
-			repeats,
-		);
+		// let sender =
+		// 	ensure_signed(<<T as Config>::Origin as From<T::PalletsOrigin>>::from(origin).into())?;
+		// let repeats = match maybe_periodic {
+		// 	Some(p) => p.1,
+		// 	None => 1,
+		// };
+		// let _ = T::CallExecutor::reserve_balance(
+		// 	id.clone(),
+		// 	sender,
+		// 	call.as_value().unwrap().clone(),
+		// 	repeats,
+		// );
 
 		Agenda::<T>::append(when, Some(s));
 		let index = Agenda::<T>::decode_len(when).unwrap_or(1) as u32 - 1;
@@ -755,13 +755,13 @@
 								return Err(BadOrigin.into());
 							}
 							// release balance reserve
-							let sender = ensure_signed(
-								<<T as Config>::Origin as From<T::PalletsOrigin>>::from(
-									origin.unwrap(),
-								)
-								.into(),
-							)?;
-							let _ = T::CallExecutor::cancel_reserve(id, sender);
+							// let sender = ensure_signed(
+							// 	<<T as Config>::Origin as From<T::PalletsOrigin>>::from(
+							// 		origin.unwrap(),
+							// 	)
+							// 	.into(),
+							// )?;
+							// let _ = T::CallExecutor::cancel_reserve(id, sender);
 
 							s.call.ensure_unrequested::<T::PreimageProvider>();
 						}
modifiedruntime/opal/src/lib.rsdiffbeforeafterboth
--- a/runtime/opal/src/lib.rs
+++ b/runtime/opal/src/lib.rs
@@ -29,7 +29,7 @@
 use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};
 use sp_runtime::DispatchError;
 use fp_self_contained::*;
-use sp_runtime::traits::{SignedExtension, Member};
+use sp_runtime::traits::{Member};
 // #[cfg(any(feature = "std", test))]
 // pub use sp_runtime::BuildStorage;
 
@@ -78,7 +78,7 @@
 	traits::{BaseArithmetic, Unsigned},
 };
 use smallvec::smallvec;
-use scale_info::TypeInfo;
+// use scale_info::TypeInfo;
 use codec::{Encode, Decode};
 use pallet_evm::{Account as EVMAccount, FeeCalculator, GasWeightMapping, OnMethodCall};
 use fp_rpc::TransactionStatus;
@@ -898,7 +898,7 @@
 type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
 use frame_support::traits::NamedReservableCurrency;
 
-fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtra {
+fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
 	(
 		frame_system::CheckSpecVersion::<Runtime>::new(),
 		frame_system::CheckGenesis::<Runtime>::new(),
@@ -907,7 +907,8 @@
 			from,
 		)),
 		frame_system::CheckWeight::<Runtime>::new(),
-		pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
+		// sponsoring transaction logic
+		// pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
 	)
 }
 
@@ -937,13 +938,14 @@
 		let extrinsic = fp_self_contained::CheckedExtrinsic::<
 			AccountId,
 			Call,
-			SignedExtra,
+			SignedExtraScheduler,
 			SelfContainedSignedInfo,
 		> {
-			signed: CheckedSignature::<AccountId, SignedExtra, SelfContainedSignedInfo>::Signed(
-				signer.clone().into(),
-				get_signed_extras(signer.into()),
-			),
+			signed:
+				CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(
+					signer.clone().into(),
+					get_signed_extras(signer.into()),
+				),
 			function: call.into(),
 		};
 
@@ -957,23 +959,13 @@
 		count: u32,
 	) -> Result<(), DispatchError> {
 		let dispatch_info = call.get_dispatch_info();
-		let fee_charger = ChargeTransactionPayment::new(0);
-		let pre = match fee_charger.pre_dispatch(
-			&sponsor.clone().into(),
-			&call.into(),
-			&dispatch_info,
-			0,
-		) {
-			Ok(p) => p,
-			Err(_) => fail!("failed to get pre dispatch info"),
-		};
+		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
+			.saturating_mul(count.into());
 
-		let count: u128 = count.into();
-		let total_fee: u128 = pre.2.map(|imbalance| imbalance.peek()).unwrap() * count;
 		<Balances as NamedReservableCurrency<AccountId>>::reserve_named(
 			&id,
 			&(sponsor.into()),
-			total_fee,
+			weight.into(),
 		)
 	}
 
@@ -983,24 +975,12 @@
 		call: <T as pallet_unq_scheduler::Config>::Call,
 	) -> Result<u128, DispatchError> {
 		let dispatch_info = call.get_dispatch_info();
-		let fee_charger = ChargeTransactionPayment::new(0);
-		let pre = match fee_charger.pre_dispatch(
-			&sponsor.clone().into(),
-			&call.into(),
-			&dispatch_info,
-			0,
-		) {
-			Ok(p) => p,
-			Err(_) => fail!("failed to get pre dispatch info"),
-		};
-
-		let single_fee: u128 = pre.2.map(|imbalance| imbalance.peek()).unwrap();
-
+		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
 		Ok(
 			<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
 				&id,
 				&(sponsor.into()),
-				single_fee,
+				weight.into(),
 			),
 		)
 	}
@@ -1184,6 +1164,13 @@
 	ChargeTransactionPayment,
 	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,
 );
+pub type SignedExtraScheduler = (
+	frame_system::CheckSpecVersion<Runtime>,
+	frame_system::CheckGenesis<Runtime>,
+	frame_system::CheckEra<Runtime>,
+	frame_system::CheckNonce<Runtime>,
+	frame_system::CheckWeight<Runtime>,
+);
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
 	fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
modifiedruntime/quartz/src/lib.rsdiffbeforeafterboth
--- a/runtime/quartz/src/lib.rs
+++ b/runtime/quartz/src/lib.rs
@@ -33,10 +33,7 @@
 
 use sp_runtime::{
 	Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,
-	traits::{
-		AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, SignedExtension,
-		Member,
-	},
+	traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},
 	transaction_validity::{TransactionSource, TransactionValidity},
 	ApplyExtrinsicResult, RuntimeAppPublic,
 };
@@ -952,7 +949,7 @@
 type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
 use frame_support::traits::NamedReservableCurrency;
 
-fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtra {
+fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
 	(
 		frame_system::CheckSpecVersion::<Runtime>::new(),
 		frame_system::CheckGenesis::<Runtime>::new(),
@@ -961,7 +958,8 @@
 			from,
 		)),
 		frame_system::CheckWeight::<Runtime>::new(),
-		pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
+		// sponsoring transaction logic
+		// pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
 	)
 }
 
@@ -991,13 +989,14 @@
 		let extrinsic = fp_self_contained::CheckedExtrinsic::<
 			AccountId,
 			Call,
-			SignedExtra,
+			SignedExtraScheduler,
 			SelfContainedSignedInfo,
 		> {
-			signed: CheckedSignature::<AccountId, SignedExtra, SelfContainedSignedInfo>::Signed(
-				signer.clone().into(),
-				get_signed_extras(signer.into()),
-			),
+			signed:
+				CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(
+					signer.clone().into(),
+					get_signed_extras(signer.into()),
+				),
 			function: call.into(),
 		};
 
@@ -1011,23 +1010,13 @@
 		count: u32,
 	) -> Result<(), DispatchError> {
 		let dispatch_info = call.get_dispatch_info();
-		let fee_charger = ChargeTransactionPayment::new(0);
-		let pre = match fee_charger.pre_dispatch(
-			&sponsor.clone().into(),
-			&call.into(),
-			&dispatch_info,
-			0,
-		) {
-			Ok(p) => p,
-			Err(_) => fail!("failed to get pre dispatch info"),
-		};
+		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
+			.saturating_mul(count.into());
 
-		let count: u128 = count.into();
-		let total_fee: u128 = pre.2.map(|imbalance| imbalance.peek()).unwrap() * count;
 		<Balances as NamedReservableCurrency<AccountId>>::reserve_named(
 			&id,
 			&(sponsor.into()),
-			total_fee,
+			weight.into(),
 		)
 	}
 
@@ -1037,24 +1026,12 @@
 		call: <T as pallet_unq_scheduler::Config>::Call,
 	) -> Result<u128, DispatchError> {
 		let dispatch_info = call.get_dispatch_info();
-		let fee_charger = ChargeTransactionPayment::new(0);
-		let pre = match fee_charger.pre_dispatch(
-			&sponsor.clone().into(),
-			&call.into(),
-			&dispatch_info,
-			0,
-		) {
-			Ok(p) => p,
-			Err(_) => fail!("failed to get pre dispatch info"),
-		};
-
-		let single_fee: u128 = pre.2.map(|imbalance| imbalance.peek()).unwrap();
-
+		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
 		Ok(
 			<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
 				&id,
 				&(sponsor.into()),
-				single_fee,
+				weight.into(),
 			),
 		)
 	}
@@ -1182,6 +1159,15 @@
 	pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
 	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,
 );
+
+pub type SignedExtraScheduler = (
+	frame_system::CheckSpecVersion<Runtime>,
+	frame_system::CheckGenesis<Runtime>,
+	frame_system::CheckEra<Runtime>,
+	frame_system::CheckNonce<Runtime>,
+	frame_system::CheckWeight<Runtime>,
+	// pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
+);
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
 	fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
modifiedruntime/unique/src/lib.rsdiffbeforeafterboth
--- a/runtime/unique/src/lib.rs
+++ b/runtime/unique/src/lib.rs
@@ -37,7 +37,7 @@
 	traits::{
 		Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, Saturating,
 		CheckedConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion,
-		Zero, Member, SignedExtension,
+		Zero, Member,
 	},
 	transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
 	ApplyExtrinsicResult, RuntimeAppPublic, SaturatedConversion, DispatchErrorWithPostInfo,
@@ -918,7 +918,7 @@
 type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
 use frame_support::traits::NamedReservableCurrency;
 
-fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtra {
+fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
 	(
 		frame_system::CheckSpecVersion::<Runtime>::new(),
 		frame_system::CheckGenesis::<Runtime>::new(),
@@ -927,7 +927,8 @@
 			from,
 		)),
 		frame_system::CheckWeight::<Runtime>::new(),
-		pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
+		// sponsoring transaction logic
+		// pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
 	)
 }
 
@@ -957,13 +958,14 @@
 		let extrinsic = fp_self_contained::CheckedExtrinsic::<
 			AccountId,
 			Call,
-			SignedExtra,
+			SignedExtraScheduler,
 			SelfContainedSignedInfo,
 		> {
-			signed: CheckedSignature::<AccountId, SignedExtra, SelfContainedSignedInfo>::Signed(
-				signer.clone().into(),
-				get_signed_extras(signer.into()),
-			),
+			signed:
+				CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(
+					signer.clone().into(),
+					get_signed_extras(signer.into()),
+				),
 			function: call.into(),
 		};
 
@@ -977,23 +979,13 @@
 		count: u32,
 	) -> Result<(), DispatchError> {
 		let dispatch_info = call.get_dispatch_info();
-		let fee_charger = ChargeTransactionPayment::new(0);
-		let pre = match fee_charger.pre_dispatch(
-			&sponsor.clone().into(),
-			&call.into(),
-			&dispatch_info,
-			0,
-		) {
-			Ok(p) => p,
-			Err(_) => fail!("failed to get pre dispatch info"),
-		};
+		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
+			.saturating_mul(count.into());
 
-		let count: u128 = count.into();
-		let total_fee: u128 = pre.2.map(|imbalance| imbalance.peek()).unwrap() * count;
 		<Balances as NamedReservableCurrency<AccountId>>::reserve_named(
 			&id,
 			&(sponsor.into()),
-			total_fee,
+			weight.into(),
 		)
 	}
 
@@ -1003,24 +995,12 @@
 		call: <T as pallet_unq_scheduler::Config>::Call,
 	) -> Result<u128, DispatchError> {
 		let dispatch_info = call.get_dispatch_info();
-		let fee_charger = ChargeTransactionPayment::new(0);
-		let pre = match fee_charger.pre_dispatch(
-			&sponsor.clone().into(),
-			&call.into(),
-			&dispatch_info,
-			0,
-		) {
-			Ok(p) => p,
-			Err(_) => fail!("failed to get pre dispatch info"),
-		};
-
-		let single_fee: u128 = pre.2.map(|imbalance| imbalance.peek()).unwrap();
-
+		let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
 		Ok(
 			<Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
 				&id,
 				&(sponsor.into()),
-				single_fee,
+				weight.into(),
 			),
 		)
 	}
@@ -1173,6 +1153,14 @@
 	pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
 	//pallet_contract_helpers::ContractHelpersExtension<Runtime>,
 );
+pub type SignedExtraScheduler = (
+	frame_system::CheckSpecVersion<Runtime>,
+	frame_system::CheckGenesis<Runtime>,
+	frame_system::CheckEra<Runtime>,
+	frame_system::CheckNonce<Runtime>,
+	frame_system::CheckWeight<Runtime>,
+	// pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
+);
 /// Unchecked extrinsic type as expected by this runtime.
 pub type UncheckedExtrinsic =
 	fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
modifiedtests/src/scheduler.test.tsdiffbeforeafterboth
before · tests/src/scheduler.test.ts
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import chai, {expect} from 'chai';18import chaiAsPromised from 'chai-as-promised';19import privateKey from './substrate/privateKey';20import {21  default as usingApi, 22  submitTransactionAsync,23} from './substrate/substrate-api';24import {25  createItemExpectSuccess,26  createCollectionExpectSuccess,27  scheduleTransferExpectSuccess,28  scheduleTransferAndWaitExpectSuccess,29  setCollectionSponsorExpectSuccess,30  confirmSponsorshipExpectSuccess,31  findUnusedAddress,32  UNIQUE,33  enablePublicMintingExpectSuccess,34  addToAllowListExpectSuccess,35  waitNewBlocks,36  normalizeAccountId,37  getTokenOwner,38  getGenericResult,39  scheduleTransferFundsPeriodicExpectSuccess,40  getFreeBalance,41  confirmSponsorshipByKeyExpectSuccess,42  scheduleExpectFailure,43} from './util/helpers';44import {IKeyringPair} from '@polkadot/types/types';4546chai.use(chaiAsPromised);4748describe('Scheduling token and balance transfers', () => {49  let alice: IKeyringPair;50  let bob: IKeyringPair;51  let scheduledIdBase: string;52  let scheduledIdSlider: number;5354  before(async() => {55    await usingApi(async () => {56      alice = privateKey('//Alice');57      bob = privateKey('//Bob');58    });5960    scheduledIdBase = '0x' + '0'.repeat(31);61    scheduledIdSlider = 0;62  });6364  // Loop scheduledId around 10. Unless there are concurrent tasks with long periods/repetitions, tests' tasks' ids shouldn't ovelap.65  function makeScheduledId(): string {66    return scheduledIdBase + ((scheduledIdSlider++) % 10);67  }6869  it('Can schedule a transfer of an owned token with delay', async () => {70    await usingApi(async () => {71      const nftCollectionId = await createCollectionExpectSuccess();72      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');73      await setCollectionSponsorExpectSuccess(nftCollectionId, alice.address);74      await confirmSponsorshipExpectSuccess(nftCollectionId);7576      await scheduleTransferAndWaitExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 4, makeScheduledId());77    });78  });7980  it('Can transfer funds periodically', async () => {81    await usingApi(async () => {82      const waitForBlocks = 4;83      const period = 2;84      await scheduleTransferFundsPeriodicExpectSuccess(1n * UNIQUE, alice, bob, waitForBlocks, makeScheduledId(), period, 2);85      const bobsBalanceBefore = await getFreeBalance(bob);8687      // discounting already waited-for operations88      await waitNewBlocks(waitForBlocks - 2);89      const bobsBalanceAfterFirst = await getFreeBalance(bob);90      expect(bobsBalanceAfterFirst > bobsBalanceBefore).to.be.true;9192      await waitNewBlocks(period);93      const bobsBalanceAfterSecond = await getFreeBalance(bob);94      expect(bobsBalanceAfterSecond > bobsBalanceAfterFirst).to.be.true;95    });96  });9798  it('Can sponsor scheduling a transaction', async () => {99    const collectionId = await createCollectionExpectSuccess();100    await setCollectionSponsorExpectSuccess(collectionId, bob.address);101    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');102103    await usingApi(async () => {104      const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);105106      const bobBalanceBefore = await getFreeBalance(bob);107      const waitForBlocks = 4;108      // no need to wait to check, fees must be deducted on scheduling, immediately109      await scheduleTransferExpectSuccess(collectionId, tokenId, alice, bob, 0, waitForBlocks, makeScheduledId());110      const bobBalanceAfter = await getFreeBalance(bob);111      // expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true;112      expect(bobBalanceAfter < bobBalanceBefore).to.be.true;113      // wait for sequentiality matters114      await waitNewBlocks(waitForBlocks - 1);115    });116  });117118  it('Schedules and dispatches a transaction even if the caller has no funds at the time of the dispatch', async () => {119    await usingApi(async (api) => {120      // Find an empty, unused account121      const zeroBalance = await findUnusedAddress(api);122123      const collectionId = await createCollectionExpectSuccess();124125      // Add zeroBalance address to allow list126      await enablePublicMintingExpectSuccess(alice, collectionId);127      await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);128129      // Grace zeroBalance with money, enough to cover future transactions130      const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);131      await submitTransactionAsync(alice, balanceTx);132133      // Mint a fresh NFT134      const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT');135136      // Schedule transfer of the NFT a few blocks ahead137      const waitForBlocks = 5;138      await scheduleTransferExpectSuccess(collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks, makeScheduledId());139140      // Get rid of the account's funds before the scheduled transaction takes place141      const balanceTx2 = api.tx.balances.transfer(alice.address, UNIQUE * 68n / 100n);142      const events = await submitTransactionAsync(zeroBalance, balanceTx2);143      expect(getGenericResult(events).success).to.be.true;144      /*const emptyBalanceTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); // do not null reserved?145      const sudoTx = api.tx.sudo.sudo(emptyBalanceTx as any);146      const events = await submitTransactionAsync(alice, sudoTx);147      expect(getGenericResult(events).success).to.be.true;*/148149      // Wait for a certain number of blocks, discarding the ones that already happened while accepting the late transactions150      await waitNewBlocks(waitForBlocks - 3);151152      expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address));153    });154  });155156  it('Sponsor going bankrupt does not impact a scheduled transaction', async () => {157    const collectionId = await createCollectionExpectSuccess();158159    await usingApi(async (api) => {160      const zeroBalance = await findUnusedAddress(api);161      const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);162      await submitTransactionAsync(alice, balanceTx);163164      await setCollectionSponsorExpectSuccess(collectionId, zeroBalance.address);165      await confirmSponsorshipByKeyExpectSuccess(collectionId, zeroBalance);166167      const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);168169      const waitForBlocks = 5;170      await scheduleTransferExpectSuccess(collectionId, tokenId, alice, zeroBalance, 1, waitForBlocks, makeScheduledId());171172      const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0);173      const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any);174      const events = await submitTransactionAsync(alice, sudoTx);175      expect(getGenericResult(events).success).to.be.true;176177      // Wait for a certain number of blocks, save for the ones that already happened while accepting the late transactions178      await waitNewBlocks(waitForBlocks - 3);179180      expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(zeroBalance.address));181    });182  });183184  it.skip('Exceeding sponsor rate limit without having enough funds prevents scheduling a periodic transaction', async () => {185    const collectionId = await createCollectionExpectSuccess();186    await setCollectionSponsorExpectSuccess(collectionId, bob.address);187    await confirmSponsorshipExpectSuccess(collectionId, '//Bob');188189    await usingApi(async (api) => {190      const zeroBalance = await findUnusedAddress(api);191192      await enablePublicMintingExpectSuccess(alice, collectionId);193      await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);194195      const bobBalanceBefore = await getFreeBalance(bob);196197      const createData = {nft: {const_data: [], variable_data: []}};198      const creationTx = api.tx.unique.createItem(collectionId, normalizeAccountId(zeroBalance), createData as any);199200      /*const badTransaction = async function () {201        await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);202      };203      await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');*/204205      await scheduleExpectFailure(creationTx, zeroBalance, 3, makeScheduledId(), 1, 3);206207      expect(await getFreeBalance(bob)).to.be.equal(bobBalanceBefore);208    });209  });210});