difftreelog
Scheduler refactored and fixed
in: master
8 files changed
pallets/nft-charge-transaction/src/lib.rsdiffbeforeafterboth1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56#![cfg_attr(not(feature = "std"), no_std)]78#[cfg(feature = "std")]9pub use std::*;1011#[cfg(feature = "std")]12pub use serde::*;1314#[cfg(feature = "runtime-benchmarks")]15mod benchmarking;1617#[cfg(test)]18mod tests;1920use codec::{Decode, Encode};21use frame_support::traits::{ Get};22use frame_support::{23 decl_module, decl_storage,24 traits::{25 IsSubType, 26 },27 weights::{28 DispatchInfo, PostDispatchInfo, DispatchClass29 }30};31use sp_runtime::{32 traits::{ 33 DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SaturatedConversion, SignedExtension, Zero,34 },35 transaction_validity::{ 36 TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction,37 },38 FixedPointOperand, DispatchResult39};40use pallet_contracts::chain_extension::UncheckedFrom;41use pallet_transaction_payment::OnChargeTransaction;42use sp_std::prelude::*;434445 pub trait Config: frame_system::Config + 46 pallet_nft_transaction_payment::Config47 {4849 }5051 decl_storage! {52 trait Store for Module<T: Config> as NftTransactionPayment{5354 }55}5657decl_module! {5859 pub struct Module<T: Config> for enum Call 60 where 61 origin: T::Origin,62 {}63}6465type BalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::Balance;6667/// Require the transactor pay for themselves and maybe include a tip to gain additional priority68/// in the queue.69#[derive(Encode, Decode, Clone, Eq, PartialEq)]70pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);7172impl<T: Config + Send + Sync> sp_std::fmt::Debug 73 for ChargeTransactionPayment<T>74{75 #[cfg(feature = "std")]76 fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {77 write!(f, "ChargeTransactionPayment<{:?}>", self.0)78 }79 #[cfg(not(feature = "std"))]80 fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {81 Ok(())82 }83}8485impl<T: Config> ChargeTransactionPayment<T>86where87 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,88 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,89 T::AccountId: AsRef<[u8]>,90 T::AccountId: UncheckedFrom<T::Hash>,91{92 fn traditional_fee(93 len: usize,94 info: &DispatchInfoOf<T::Call>,95 tip: BalanceOf<T>,96 ) -> BalanceOf<T>97 where98 T::Call: Dispatchable<Info = DispatchInfo>,99 {100 <pallet_transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)101 }102103 fn get_priority(len: usize, info: &DispatchInfoOf<T::Call>, final_fee: BalanceOf<T>) -> TransactionPriority {104 let weight_saturation = T::BlockWeights::get().max_block / info.weight.max(1);105 let max_block_length = *T::BlockLength::get().max.get(DispatchClass::Normal);106 let len_saturation = max_block_length as u64 / (len as u64).max(1);107 let coefficient: BalanceOf<T> = weight_saturation108 .min(len_saturation)109 .saturated_into::<BalanceOf<T>>();110 final_fee111 .saturating_mul(coefficient)112 .saturated_into::<TransactionPriority>()113 }114115 fn withdraw_fee(116 &self,117 who: &T::AccountId,118 call: &T::Call,119 info: &DispatchInfoOf<T::Call>,120 len: usize,121 ) -> Result<122 (123 BalanceOf<T>,124 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,125 ),126 TransactionValidityError,127 > {128 let tip = self.0;129130 let fee = Self::traditional_fee(len, info, tip);131132 // Only mess with balances if fee is not zero.133 if fee.is_zero() {134 return <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(who, call, info, fee, tip)135 .map(|i| (fee, i));136 }137138 // Determine who is paying transaction fee based on ecnomic model139 // Parse call to extract collection ID and access collection sponsor 140 let sponsor = <pallet_nft_transaction_payment::Module<T>>::withdraw_type(who, call);141142 let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());143144 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)145 .map(|i| (fee, i))146 }147}148149impl<T: Config + Send + Sync> SignedExtension150 for ChargeTransactionPayment<T>151where152 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,153 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,154 T::AccountId: AsRef<[u8]>,155 T::AccountId: UncheckedFrom<T::Hash>,156{157 const IDENTIFIER: &'static str = "ChargeTransactionPayment";158 type AccountId = T::AccountId;159 type Call = T::Call;160 type AdditionalSigned = ();161 type Pre = (162 // tip163 BalanceOf<T>,164 // who pays fee165 Self::AccountId,166 // imbalance resulting from withdrawing the fee167 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,168 );169 fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {170 Ok(())171 }172173 fn validate(174 &self,175 who: &Self::AccountId,176 call: &Self::Call,177 info: &DispatchInfoOf<Self::Call>,178 len: usize,179 ) -> TransactionValidity {180 let (fee, _) = self.withdraw_fee(who, call, info, len)?;181 Ok(ValidTransaction {182 priority: Self::get_priority(len, info, fee),183 ..Default::default()184 })185 }186187 fn pre_dispatch(188 self,189 who: &Self::AccountId,190 call: &Self::Call,191 info: &DispatchInfoOf<Self::Call>,192 len: usize,193 ) -> Result<Self::Pre, TransactionValidityError> {194 let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;195 Ok((self.0, who.clone(), imbalance))196 }197198 fn post_dispatch(199 pre: Self::Pre,200 info: &DispatchInfoOf<Self::Call>,201 post_info: &PostDispatchInfoOf<Self::Call>,202 len: usize,203 _result: &DispatchResult,204 ) -> Result<(), TransactionValidityError> {205 let (tip, who, imbalance) = pre;206 let actual_fee = pallet_transaction_payment::Module::<T>::compute_actual_fee(207 len as u32,208 info,209 post_info,210 tip,211 );212 <T as pallet_transaction_payment::Config>::OnChargeTransaction::correct_and_deposit_fee(&who, info, post_info, actual_fee, tip, imbalance)?;213 Ok(())214 }215}1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56#![cfg_attr(not(feature = "std"), no_std)]78#[cfg(feature = "std")]9pub use std::*;1011#[cfg(feature = "std")]12pub use serde::*;1314#[cfg(feature = "runtime-benchmarks")]15mod benchmarking;1617#[cfg(test)]18mod tests;1920use codec::{Decode, Encode};21use frame_support::traits::{ Get};22use frame_support::{23 decl_module, decl_storage,24 traits::{25 IsSubType, 26 },27 weights::{28 DispatchInfo, PostDispatchInfo, DispatchClass29 }30};31use sp_runtime::{32 traits::{ 33 DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SaturatedConversion, SignedExtension, Zero,34 },35 transaction_validity::{ 36 TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction,37 },38 FixedPointOperand, DispatchResult39};40use pallet_contracts::chain_extension::UncheckedFrom;41use pallet_transaction_payment::OnChargeTransaction;42use sp_std::prelude::*;434445 pub trait Config: frame_system::Config + 46 pallet_nft_transaction_payment::Config47 {4849 }5051 decl_storage! {52 trait Store for Module<T: Config> as NftTransactionPayment{5354 }55}5657decl_module! {5859 pub struct Module<T: Config> for enum Call 60 where 61 origin: T::Origin,62 {}63}6465type BalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::Balance;6667/// Require the transactor pay for themselves and maybe include a tip to gain additional priority68/// in the queue.69#[derive(Encode, Decode, Clone, Eq, PartialEq)]70pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);7172impl<T: Config + Send + Sync> sp_std::fmt::Debug 73 for ChargeTransactionPayment<T>74{75 #[cfg(feature = "std")]76 fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {77 write!(f, "ChargeTransactionPayment<{:?}>", self.0)78 }79 #[cfg(not(feature = "std"))]80 fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {81 Ok(())82 }83}8485impl<T: Config> ChargeTransactionPayment<T>86where87 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,88 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,89 T::AccountId: AsRef<[u8]>,90 T::AccountId: UncheckedFrom<T::Hash>,91{92 fn traditional_fee(93 len: usize,94 info: &DispatchInfoOf<T::Call>,95 tip: BalanceOf<T>,96 ) -> BalanceOf<T>97 where98 T::Call: Dispatchable<Info = DispatchInfo>,99 {100 <pallet_transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)101 }102103 fn get_priority(len: usize, info: &DispatchInfoOf<T::Call>, final_fee: BalanceOf<T>) -> TransactionPriority {104 let weight_saturation = T::BlockWeights::get().max_block / info.weight.max(1);105 let max_block_length = *T::BlockLength::get().max.get(DispatchClass::Normal);106 let len_saturation = max_block_length as u64 / (len as u64).max(1);107 let coefficient: BalanceOf<T> = weight_saturation108 .min(len_saturation)109 .saturated_into::<BalanceOf<T>>();110 final_fee111 .saturating_mul(coefficient)112 .saturated_into::<TransactionPriority>()113 }114115 fn withdraw_fee(116 &self,117 who: &T::AccountId,118 call: &T::Call,119 info: &DispatchInfoOf<T::Call>,120 len: usize,121 ) -> Result<122 (123 BalanceOf<T>,124 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,125 ),126 TransactionValidityError,127 > {128 let tip = self.0;129130 let fee = Self::traditional_fee(len, info, tip);131132 // Only mess with balances if fee is not zero.133 if fee.is_zero() {134 return <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(who, call, info, fee, tip)135 .map(|i| (fee, i));136 }137138 // check errors139 let error = <pallet_nft_transaction_payment::Module<T>>::check_error(who, call);140 match error {141 Err(error) => return Err(error),142 Ok(error) => {}143 };144145 // Determine who is paying transaction fee based on ecnomic model146 // Parse call to extract collection ID and access collection sponsor 147 let sponsor = <pallet_nft_transaction_payment::Module<T>>::withdraw_type(who, call);148149 let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());150151 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)152 .map(|i| (fee, i))153 }154}155156impl<T: Config + Send + Sync> SignedExtension157 for ChargeTransactionPayment<T>158where159 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,160 T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,161 T::AccountId: AsRef<[u8]>,162 T::AccountId: UncheckedFrom<T::Hash>,163{164 const IDENTIFIER: &'static str = "ChargeTransactionPayment";165 type AccountId = T::AccountId;166 type Call = T::Call;167 type AdditionalSigned = ();168 type Pre = (169 // tip170 BalanceOf<T>,171 // who pays fee172 Self::AccountId,173 // imbalance resulting from withdrawing the fee174 <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,175 );176 fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {177 Ok(())178 }179180 fn validate(181 &self,182 who: &Self::AccountId,183 call: &Self::Call,184 info: &DispatchInfoOf<Self::Call>,185 len: usize,186 ) -> TransactionValidity {187 let (fee, _) = self.withdraw_fee(who, call, info, len)?;188 Ok(ValidTransaction {189 priority: Self::get_priority(len, info, fee),190 ..Default::default()191 })192 }193194 fn pre_dispatch(195 self,196 who: &Self::AccountId,197 call: &Self::Call,198 info: &DispatchInfoOf<Self::Call>,199 len: usize,200 ) -> Result<Self::Pre, TransactionValidityError> {201 let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;202 Ok((self.0, who.clone(), imbalance))203 }204205 fn post_dispatch(206 pre: Self::Pre,207 info: &DispatchInfoOf<Self::Call>,208 post_info: &PostDispatchInfoOf<Self::Call>,209 len: usize,210 _result: &DispatchResult,211 ) -> Result<(), TransactionValidityError> {212 let (tip, who, imbalance) = pre;213 let actual_fee = pallet_transaction_payment::Module::<T>::compute_actual_fee(214 len as u32,215 info,216 post_info,217 tip,218 );219 <T as pallet_transaction_payment::Config>::OnChargeTransaction::correct_and_deposit_fee(&who, info, post_info, actual_fee, tip, imbalance)?;220 Ok(())221 }222}pallets/nft-transaction-payment/README.mddiffbeforeafterboth--- /dev/null
+++ b/pallets/nft-transaction-payment/README.md
@@ -0,0 +1,13 @@
+# Nft Transaction Payment
+
+## Overview
+
+A module containing the sponsoring logic for paying for sponsored collections
+
+**NOTE:** The scheduled calls will be dispatched with the default filter
+for the origin: namely `frame_system::Config::BaseCallFilter` for all origin
+except root which will get no filter. And not the filter contained in origin
+use to call `fn schedule`.
+
+If a call is scheduled using proxy or whatever mecanism which adds filter,
+then those filter will not be used when dispatching the schedule call.
pallets/nft-transaction-payment/src/lib.rsdiffbeforeafterboth--- a/pallets/nft-transaction-payment/src/lib.rs
+++ b/pallets/nft-transaction-payment/src/lib.rs
@@ -31,6 +31,9 @@
traits::{
Hash, Dispatchable,
},
+ transaction_validity::{
+ InvalidTransaction, TransactionValidityError,
+ },
};
use pallet_contracts::chain_extension::UncheckedFrom;
use sp_std::prelude::*;
@@ -85,6 +88,36 @@
impl<T: Config> Module<T>
{
+ pub fn check_error(
+ who: &T::AccountId,
+ call: &T::Call
+ ) -> Result<bool, TransactionValidityError> where
+ T::Call: Dispatchable<Info=DispatchInfo>,
+ T::Call: IsSubType<pallet_nft::Call<T>>,
+ T::Call: IsSubType<pallet_contracts::Call<T>>,
+ T::AccountId: AsRef<[u8]>,
+ T::AccountId: UncheckedFrom<T::Hash>
+ {
+
+ match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
+ Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {
+
+ let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());
+
+ let owned_contract = pallet_nft::ContractOwner::<T>::get(called_contract.clone()).as_ref() == Some(who);
+ let white_list_enabled = pallet_nft::ContractWhiteListEnabled::<T>::contains_key(called_contract.clone());
+
+ if !owned_contract && white_list_enabled {
+ if !pallet_nft::ContractWhiteList::<T>::contains_key(called_contract.clone(), who) {
+ return Err(InvalidTransaction::Call.into());
+ }
+ }
+ Ok(true)
+ },
+ _ => { Ok(true) },
+ }
+ }
+
pub fn withdraw_type(
who: &T::AccountId,
call: &T::Call
@@ -366,160 +399,4 @@
None
}
-}
-
-// type BalanceOf<T> = <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::Balance;
-
-// /// Require the transactor pay for themselves and maybe include a tip to gain additional priority
-// /// in the queue.
-// #[derive(Encode, Decode, Clone, Eq, PartialEq)]
-// pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);
-
-// impl<T: Config + Send + Sync> sp_std::fmt::Debug
-// for ChargeTransactionPayment<T>
-// {
-// #[cfg(feature = "std")]
-// fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
-// write!(f, "ChargeTransactionPayment<{:?}>", self.0)
-// }
-// #[cfg(not(feature = "std"))]
-// fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
-// Ok(())
-// }
-// }
-
-// impl<T: Config> ChargeTransactionPayment<T>
-// where
-// T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,
-// BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,
-// T::AccountId: AsRef<[u8]>,
-// T::AccountId: UncheckedFrom<T::Hash>,
-// {
-// fn traditional_fee(
-// len: usize,
-// info: &DispatchInfoOf<T::Call>,
-// tip: BalanceOf<T>,
-// ) -> BalanceOf<T>
-// where
-// T::Call: Dispatchable<Info = DispatchInfo>,
-// {
-// <pallet_transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)
-// }
-
-// fn get_priority(len: usize, info: &DispatchInfoOf<T::Call>, final_fee: BalanceOf<T>) -> TransactionPriority {
-// let weight_saturation = T::BlockWeights::get().max_block / info.weight.max(1);
-// let max_block_length = *T::BlockLength::get().max.get(DispatchClass::Normal);
-// let len_saturation = max_block_length as u64 / (len as u64).max(1);
-// let coefficient: BalanceOf<T> = weight_saturation
-// .min(len_saturation)
-// .saturated_into::<BalanceOf<T>>();
-// final_fee
-// .saturating_mul(coefficient)
-// .saturated_into::<TransactionPriority>()
-// }
-
-// fn withdraw_fee(
-// &self,
-// who: &T::AccountId,
-// call: &T::Call,
-// info: &DispatchInfoOf<T::Call>,
-// len: usize,
-// ) -> Result<
-// (
-// BalanceOf<T>,
-// <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,
-// ),
-// TransactionValidityError,
-// > {
-// let tip = self.0;
-
-// let fee = Self::traditional_fee(len, info, tip);
-
-// // Only mess with balances if fee is not zero.
-// if fee.is_zero() {
-// return <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(who, call, info, fee, tip)
-// .map(|i| (fee, i));
-// }
-
-// // Determine who is paying transaction fee based on ecnomic model
-// // Parse call to extract collection ID and access collection sponsor
-
-// let sponsor = pallet_nft_transaction_payment::<T>::withdraw_type(who, call);
-// //let sponsor = Self::Module::<T>::withdraw_type(who, call);;
-// // <pallet_nft_transaction_payment::Module<T>>::withdraw_type(who, call);
-
-// let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());
-
-// <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)
-// .map(|i| (fee, i))
-// }
-// }
-
-
-// impl<T: Config + Send + Sync> SignedExtension
-// for ChargeTransactionPayment<T>
-// where
-// BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,
-// T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<pallet_nft::Call<T>> + IsSubType<pallet_contracts::Call<T>>,
-// T::AccountId: AsRef<[u8]>,
-// T::AccountId: UncheckedFrom<T::Hash>,
-// {
-// const IDENTIFIER: &'static str = "ChargeTransactionPayment";
-// type AccountId = T::AccountId;
-// type Call = T::Call;
-// type AdditionalSigned = ();
-// type Pre = (
-// // tip
-// BalanceOf<T>,
-// // who pays fee
-// Self::AccountId,
-// // imbalance resulting from withdrawing the fee
-// <<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::LiquidityInfo,
-// );
-// fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {
-// Ok(())
-// }
-
-// fn validate(
-// &self,
-// who: &Self::AccountId,
-// call: &Self::Call,
-// info: &DispatchInfoOf<Self::Call>,
-// len: usize,
-// ) -> TransactionValidity {
-// let (fee, _) = self.withdraw_fee(who, call, info, len)?;
-// Ok(ValidTransaction {
-// priority: Self::get_priority(len, info, fee),
-// ..Default::default()
-// })
-// }
-
-// fn pre_dispatch(
-// self,
-// who: &Self::AccountId,
-// call: &Self::Call,
-// info: &DispatchInfoOf<Self::Call>,
-// len: usize,
-// ) -> Result<Self::Pre, TransactionValidityError> {
-// let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
-// Ok((self.0, who.clone(), imbalance))
-// }
-
-// fn post_dispatch(
-// pre: Self::Pre,
-// info: &DispatchInfoOf<Self::Call>,
-// post_info: &PostDispatchInfoOf<Self::Call>,
-// len: usize,
-// _result: &DispatchResult,
-// ) -> Result<(), TransactionValidityError> {
-// let (tip, who, imbalance) = pre;
-// let actual_fee = pallet_transaction_payment::Module::<T>::compute_actual_fee(
-// len as u32,
-// info,
-// post_info,
-// tip,
-// );
-// <T as pallet_transaction_payment::Config>::OnChargeTransaction::correct_and_deposit_fee(&who, info, post_info, actual_fee, tip, imbalance)?;
-// Ok(())
-// }
-// }
\ No newline at end of file
+}
\ No newline at end of file
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -32,10 +32,11 @@
use frame_system::{self as system, ensure_signed, ensure_root};
use sp_runtime::sp_std::prelude::Vec;
+use core::ops::{Deref, DerefMut};
use nft_data_structs::{
MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, MAX_REFUNGIBLE_PIECES,
AccessMode, ChainLimits, Collection, CreateItemData, CollectionLimits,
- CollectionId, CollectionMode, CollectionHandle, TokenId,
+ CollectionId, CollectionMode, TokenId,
SchemaVersion, SponsorshipState, Ownership,
NftItemType, FungibleItemType, ReFungibleItemType
};
@@ -164,7 +165,25 @@
}
}
-// + pallet_transaction_payment::Config + pallet_nft_transaction_payment::Config + pallet_contracts::Config
+pub struct CollectionHandle<T: frame_system::Config> {
+ pub id: CollectionId,
+ pub collection: Collection<T>,
+}
+
+impl<T: frame_system::Config> Deref for CollectionHandle<T> {
+ type Target = Collection<T>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.collection
+ }
+}
+
+impl<T: frame_system::Config> DerefMut for CollectionHandle<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.collection
+ }
+}
+
pub trait Config: system::Config + Sized {
pallets/scheduler/src/lib.rsdiffbeforeafterboth--- a/pallets/scheduler/src/lib.rs
+++ b/pallets/scheduler/src/lib.rs
@@ -102,7 +102,7 @@
/// Not strictly enforced, but used for weight estimation.
type MaxScheduledPerBlock: Get<u32>;
- /// TODO
+ /// Sponsoring function
type Sponsoring: SponsoringResolve<Self::AccountId, <Self as Config>::Call>;
/// Weight information for extrinsics in this pallet.
@@ -230,8 +230,7 @@
/// - Write: Agenda
/// - Will use base weight of 25 which should be good for up to 30 scheduled calls
/// # </weight>
- // #[weight = <T as Config>::WeightInfo::schedule(T::MaxScheduledPerBlock::get())]
- #[weight = 0]
+ #[weight = <T as Config>::WeightInfo::schedule(T::MaxScheduledPerBlock::get())]
fn schedule(origin,
when: T::BlockNumber,
maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
@@ -367,7 +366,7 @@
}
queued.sort_by_key(|(_, s)| s.priority);
let base_weight: Weight = T::DbWeight::get().reads_writes(1, 2); // Agenda + Agenda(next)
- let mut total_weight: Weight = <T as Config>::WeightInfo::schedule(T::MaxScheduledPerBlock::get());
+ let mut total_weight: Weight = 0;
queued.into_iter()
.enumerate()
.scan(base_weight, |cumulative_weight, (order, (index, s))| {
@@ -407,7 +406,7 @@
).into();
let sender = ensure_signed(origin).unwrap_or(T::AccountId::default());
let who_will_pay = T::Sponsoring::resolve(&sender, &s.call.clone()).unwrap_or(
- T::AccountId::default());
+ sender);
let sponsor = T::PalletsOrigin::from(system::RawOrigin::Signed(who_will_pay));
let r = s.call.clone().dispatch(sponsor.into());
let maybe_id = s.maybe_id.clone();
tests/src/pallet-presence.test.tsdiffbeforeafterboth--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -13,7 +13,8 @@
// Pallets that must always be present
const requiredPallets = [
- 'nft', 'inflation', 'balances', 'contracts', 'randomnesscollectiveflip', 'system', 'timestamp', 'transactionpayment', 'treasury', 'vesting'
+ 'nft', 'inflation', 'balances', 'contracts', 'randomnesscollectiveflip', 'system', 'timestamp', 'transactionpayment', 'treasury', 'vesting',
+ 'scheduler', 'nftpayment', 'charging'
];
// Pallets that depend on consensus and governance configuration
tests/src/scheduler.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/scheduler.test.ts
@@ -0,0 +1,94 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { IKeyringPair } from '@polkadot/types/types';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import {
+ createItemExpectSuccess,
+ createCollectionExpectSuccess,
+ destroyCollectionExpectSuccess,
+ findNotExistingCollection,
+ queryCollectionExpectSuccess,
+ setOffchainSchemaExpectFailure,
+ setOffchainSchemaExpectSuccess,
+ transferExpectSuccess,
+ scheduleTransferExpectSuccess,
+ setCollectionSponsorExpectSuccess,
+ confirmSponsorshipExpectSuccess
+} from './util/helpers';
+
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+const DATA = [1, 2, 3, 4];
+
+describe('Integration Test scheduler base transaction', () => {
+ let alice: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async () => {
+ alice = privateKey('//Alice');
+ });
+ });
+
+ it('User can transfer owned token with delay (scheduler)', async () => {
+ await usingApi(async (api) => {
+ const Alice = privateKey('//Alice');
+ const Bob = privateKey('//Bob');
+ // nft
+ const nftCollectionId = await createCollectionExpectSuccess();
+ const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT');
+ await setCollectionSponsorExpectSuccess(nftCollectionId, Alice.address);
+ await confirmSponsorshipExpectSuccess(nftCollectionId);
+
+ await scheduleTransferExpectSuccess(nftCollectionId, newNftTokenId, Alice, Bob, 1, 'NFT');
+ });
+ });
+
+
+});
+
+// describe('Negative Integration Test setOffchainSchema', () => {
+// let alice: IKeyringPair;
+// let bob: IKeyringPair;
+
+// let validCollectionId: number;
+
+// before(async () => {
+// await usingApi(async () => {
+// alice = privateKey('//Alice');
+// bob = privateKey('//Bob');
+
+// validCollectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+// });
+// });
+
+// it('fails on not existing collection id', async () => {
+// const nonExistingCollectionId = await usingApi(findNotExistingCollection);
+
+// await setOffchainSchemaExpectFailure(alice, nonExistingCollectionId, DATA);
+// });
+
+// it('fails on destroyed collection id', async () => {
+// const destroyedCollectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } });
+// await destroyCollectionExpectSuccess(destroyedCollectionId);
+
+// await setOffchainSchemaExpectFailure(alice, destroyedCollectionId, DATA);
+// });
+
+// it('fails on too long data', async () => {
+// const tooLongData = new Array(4097).fill(0xff);
+
+// await setOffchainSchemaExpectFailure(alice, validCollectionId, tooLongData);
+// });
+
+// it('fails on execution by non-owner', async () => {
+// await setOffchainSchemaExpectFailure(bob, validCollectionId, DATA);
+// });
+// });
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -5,7 +5,7 @@
import { ApiPromise, Keyring } from '@polkadot/api';
import { Enum, Struct } from '@polkadot/types/codec';
-import type { AccountId, EventRecord } from '@polkadot/types/interfaces';
+import type { AccountId, BlockNumber, Call, EventRecord } from '@polkadot/types/interfaces';
import { u128 } from '@polkadot/types/primitive';
import { IKeyringPair } from '@polkadot/types/types';
import { BigNumber } from 'bignumber.js';
@@ -17,6 +17,8 @@
import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from '../substrate/substrate-api';
import { ICollectionInterface } from '../types';
import { hexToStr, strToUTF16, utf16ToStr } from './util';
+import { Compact, Option, Raw, Vec } from '@polkadot/types/codec';
+// import { AccountId, AccountIdOf, AccountIndex, Address, AssetId, Balance, BalanceOf, Block, BlockNumber, Call, ChangesTrieConfiguration, Consensus, ConsensusEngineId, Digest, DigestItem, DispatchClass, DispatchInfo, DispatchInfoTo190, EcdsaSignature, Ed25519Signature, Extrinsic, ExtrinsicEra, ExtrinsicPayload, ExtrinsicPayloadUnknown, ExtrinsicPayloadV1, ExtrinsicPayloadV2, ExtrinsicPayloadV3, ExtrinsicPayloadV4, ExtrinsicSignatureV1, ExtrinsicSignatureV2, ExtrinsicSignatureV3, ExtrinsicSignatureV4, ExtrinsicUnknown, ExtrinsicV1, ExtrinsicV2, ExtrinsicV3, ExtrinsicV4, Hash, Header, ImmortalEra, Index, Justification, KeyTypeId, KeyValue, LockIdentifier, LookupSource, LookupTarget, Moment, MortalEra, MultiSignature, Origin, Perbill, Percent, Permill, Perquintill, Phantom, PhantomData, PreRuntime, Seal, SealV0, Signature, SignedBlock, SignerPayload, Sr25519Signature, ValidatorId, Weight, WeightMultiplier } from '@polkadot/types/interfaces/runtime';
chai.use(chaiAsPromised);
const expect = chai.expect;
@@ -702,6 +704,54 @@
});
}
+async function getBlockNumber(api: ApiPromise): Promise<number> {
+ return new Promise<number>(async (resolve, reject) => {
+ const unsubscribe = await api.rpc.chain.subscribeNewHeads((head) => {
+ unsubscribe();
+ resolve(head.number.toNumber());
+ });
+ });
+}
+
+export async function
+scheduleTransferExpectSuccess(collectionId: number,
+ tokenId: number,
+ sender: IKeyringPair,
+ recipient: IKeyringPair,
+ value: number | bigint = 1,
+ type: string = 'NFT') {
+ await usingApi(async (api: ApiPromise) => {
+ let balanceBefore = new BN(0);
+
+
+ let blockNumber: number | undefined = await getBlockNumber(api);
+ let expectedBlockNumber = blockNumber + 2;
+
+ expect(blockNumber).to.be.greaterThan(0);
+ const transferTx = await api.tx.nft.transfer(recipient.address, collectionId, tokenId, value);
+ const scheduleTx = await api.tx.scheduler.schedule(expectedBlockNumber, null, 0, transferTx);
+
+ const events = await submitTransactionAsync(sender, scheduleTx);
+
+ const sponsorBalanceBefore = new BigNumber((await api.query.system.account(sender.address)).data.free.toString());
+ const recipientBalanceBefore = new BigNumber((await api.query.system.account(recipient.address)).data.free.toString());
+
+ const nftItemDataBefore = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON() as unknown as ITokenDataType;
+ expect(nftItemDataBefore.Owner.toString()).to.be.equal(sender.address);
+
+ // sleep for 2 blocks
+ await new Promise(resolve => setTimeout(resolve, 6000 * 2));
+
+ const sponsorBalanceAfter = new BigNumber((await api.query.system.account(sender.address)).data.free.toString());
+ const recipientBalanceAfter = new BigNumber((await api.query.system.account(recipient.address)).data.free.toString());
+
+ const nftItemData = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON() as unknown as ITokenDataType;
+ expect(nftItemData.Owner.toString()).to.be.equal(recipient.address);
+ expect(recipientBalanceAfter.toNumber()).to.be.equal(recipientBalanceBefore.toNumber());
+ });
+}
+
+
export async function
transferExpectSuccess(collectionId: number,
tokenId: number,