difftreelog
Merge branch 'develop' into feature/NFTPAR-142
in: master
# Conflicts: # pallets/nft/src/default_weights.rs # pallets/nft/src/lib.rs
6 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3737,6 +3737,7 @@
"frame-support",
"frame-system",
"log",
+ "pallet-contracts",
"pallet-transaction-payment",
"parity-scale-codec",
"serde",
pallets/nft/Cargo.tomldiffbeforeafterboth--- a/pallets/nft/Cargo.toml
+++ b/pallets/nft/Cargo.toml
@@ -73,6 +73,34 @@
branch = 'v2.0.0_release'
optional = true
+[dependencies.pallet-contracts]
+default-features = false
+git = 'https://github.com/usetech-llc/substrate.git'
+package = 'pallet-contracts'
+branch = 'v2.0.0_release'
+version = '2.0.0'
+
+[dependencies.pallet-balances]
+default-features = false
+git = 'https://github.com/usetech-llc/substrate.git'
+package = 'pallet-balances'
+branch = 'v2.0.0_release'
+version = '2.0.0'
+
+[dependencies.pallet-timestamp]
+default-features = false
+git = 'https://github.com/usetech-llc/substrate.git'
+package = 'pallet-timestamp'
+branch = 'v2.0.0_release'
+version = '2.0.0'
+
+[dependencies.pallet-randomness-collective-flip]
+default-features = false
+git = 'https://github.com/usetech-llc/substrate.git'
+package = 'pallet-randomness-collective-flip'
+branch = 'v2.0.0_release'
+version = '2.0.0'
+
[features]
default = ['std']
std = [
@@ -80,6 +108,9 @@
"serde/std",
'frame-support/std',
'frame-system/std',
+ 'pallet-balances/std',
+ 'pallet-timestamp/std',
+ 'pallet-randomness-collective-flip/std',
'sp-std/std',
'sp-runtime/std',
'frame-benchmarking/std',
pallets/nft/src/default_weights.rsdiffbeforeafterboth1use frame_support::weights::{Weight, constants::RocksDbWeight as DbWeight};23impl crate::WeightInfo for () {4 fn create_collection() -> Weight {5 (70_000_000 as Weight)6 .saturating_add(DbWeight::get().reads(7 as Weight))7 .saturating_add(DbWeight::get().writes(5 as Weight))8 }9 fn destroy_collection() -> Weight {10 (90_000_000 as Weight)11 .saturating_add(DbWeight::get().reads(2 as Weight))12 .saturating_add(DbWeight::get().writes(5 as Weight))13 }14 fn add_to_white_list() -> Weight {15 (30_000_000 as Weight)16 .saturating_add(DbWeight::get().reads(3 as Weight))17 .saturating_add(DbWeight::get().writes(1 as Weight))18 }19 fn remove_from_white_list() -> Weight {20 (35_000_000 as Weight)21 .saturating_add(DbWeight::get().reads(3 as Weight))22 .saturating_add(DbWeight::get().writes(1 as Weight))23 }24 fn set_public_access_mode() -> Weight {25 (27_000_000 as Weight)26 .saturating_add(DbWeight::get().reads(1 as Weight))27 .saturating_add(DbWeight::get().writes(1 as Weight))28 }29 fn set_mint_permission() -> Weight {30 (27_000_000 as Weight)31 .saturating_add(DbWeight::get().reads(1 as Weight))32 .saturating_add(DbWeight::get().writes(1 as Weight))33 }34 fn change_collection_owner() -> Weight {35 (27_000_000 as Weight)36 .saturating_add(DbWeight::get().reads(1 as Weight))37 .saturating_add(DbWeight::get().writes(1 as Weight))38 }39 fn add_collection_admin() -> Weight {40 (32_000_000 as Weight)41 .saturating_add(DbWeight::get().reads(3 as Weight))42 .saturating_add(DbWeight::get().writes(1 as Weight))43 }44 fn remove_collection_admin() -> Weight {45 (50_000_000 as Weight)46 .saturating_add(DbWeight::get().reads(2 as Weight))47 .saturating_add(DbWeight::get().writes(1 as Weight))48 }49 fn set_collection_sponsor() -> Weight {50 (32_000_000 as Weight)51 .saturating_add(DbWeight::get().reads(2 as Weight))52 .saturating_add(DbWeight::get().writes(1 as Weight))53 } 54 fn confirm_sponsorship() -> Weight {55 (22_000_000 as Weight)56 .saturating_add(DbWeight::get().reads(1 as Weight))57 .saturating_add(DbWeight::get().writes(1 as Weight))58 } 59 fn remove_collection_sponsor() -> Weight {60 (24_000_000 as Weight)61 .saturating_add(DbWeight::get().reads(1 as Weight))62 .saturating_add(DbWeight::get().writes(1 as Weight))63 } 64 fn create_item(s: usize, ) -> Weight {65 (130_000_000 as Weight)66 .saturating_add((2135 as Weight).saturating_mul(s as Weight))67 .saturating_add(DbWeight::get().reads(10 as Weight))68 .saturating_add(DbWeight::get().writes(8 as Weight))69 } 70 fn burn_item() -> Weight {71 (170_000_000 as Weight)72 .saturating_add(DbWeight::get().reads(9 as Weight))73 .saturating_add(DbWeight::get().writes(7 as Weight))74 } 75 fn transfer() -> Weight {76 (125_000_000 as Weight)77 .saturating_add(DbWeight::get().reads(7 as Weight))78 .saturating_add(DbWeight::get().writes(7 as Weight))79 } 80 fn approve() -> Weight {81 (45_000_000 as Weight)82 .saturating_add(DbWeight::get().reads(3 as Weight))83 .saturating_add(DbWeight::get().writes(1 as Weight))84 }85 fn transfer_from() -> Weight {86 (150_000_000 as Weight)87 .saturating_add(DbWeight::get().reads(9 as Weight))88 .saturating_add(DbWeight::get().writes(8 as Weight))89 }90 fn set_offchain_schema() -> Weight {91 (33_000_000 as Weight)92 .saturating_add(DbWeight::get().reads(2 as Weight))93 .saturating_add(DbWeight::get().writes(1 as Weight))94 }95 fn set_const_on_chain_schema() -> Weight {96 (11_100_000 as Weight)97 .saturating_add(DbWeight::get().reads(2 as Weight))98 .saturating_add(DbWeight::get().writes(1 as Weight))99 }100 fn set_variable_on_chain_schema() -> Weight {101 (11_100_000 as Weight)102 .saturating_add(DbWeight::get().reads(2 as Weight))103 .saturating_add(DbWeight::get().writes(1 as Weight))104 }105 fn set_variable_meta_data() -> Weight {106 (17_500_000 as Weight)107 .saturating_add(DbWeight::get().reads(2 as Weight))108 .saturating_add(DbWeight::get().writes(1 as Weight))109 }110}1use frame_support::weights::{Weight, constants::RocksDbWeight as DbWeight};23impl crate::WeightInfo for () {4 fn create_collection() -> Weight {5 (70_000_000 as Weight)6 .saturating_add(DbWeight::get().reads(7 as Weight))7 .saturating_add(DbWeight::get().writes(5 as Weight))8 }9 fn destroy_collection() -> Weight {10 (90_000_000 as Weight)11 .saturating_add(DbWeight::get().reads(2 as Weight))12 .saturating_add(DbWeight::get().writes(5 as Weight))13 }14 fn add_to_white_list() -> Weight {15 (30_000_000 as Weight)16 .saturating_add(DbWeight::get().reads(3 as Weight))17 .saturating_add(DbWeight::get().writes(1 as Weight))18 }19 fn remove_from_white_list() -> Weight {20 (35_000_000 as Weight)21 .saturating_add(DbWeight::get().reads(3 as Weight))22 .saturating_add(DbWeight::get().writes(1 as Weight))23 }24 fn set_public_access_mode() -> Weight {25 (27_000_000 as Weight)26 .saturating_add(DbWeight::get().reads(1 as Weight))27 .saturating_add(DbWeight::get().writes(1 as Weight))28 }29 fn set_mint_permission() -> Weight {30 (27_000_000 as Weight)31 .saturating_add(DbWeight::get().reads(1 as Weight))32 .saturating_add(DbWeight::get().writes(1 as Weight))33 }34 fn change_collection_owner() -> Weight {35 (27_000_000 as Weight)36 .saturating_add(DbWeight::get().reads(1 as Weight))37 .saturating_add(DbWeight::get().writes(1 as Weight))38 }39 fn add_collection_admin() -> Weight {40 (32_000_000 as Weight)41 .saturating_add(DbWeight::get().reads(3 as Weight))42 .saturating_add(DbWeight::get().writes(1 as Weight))43 }44 fn remove_collection_admin() -> Weight {45 (50_000_000 as Weight)46 .saturating_add(DbWeight::get().reads(2 as Weight))47 .saturating_add(DbWeight::get().writes(1 as Weight))48 }49 fn set_collection_sponsor() -> Weight {50 (32_000_000 as Weight)51 .saturating_add(DbWeight::get().reads(2 as Weight))52 .saturating_add(DbWeight::get().writes(1 as Weight))53 } 54 fn confirm_sponsorship() -> Weight {55 (22_000_000 as Weight)56 .saturating_add(DbWeight::get().reads(1 as Weight))57 .saturating_add(DbWeight::get().writes(1 as Weight))58 } 59 fn remove_collection_sponsor() -> Weight {60 (24_000_000 as Weight)61 .saturating_add(DbWeight::get().reads(1 as Weight))62 .saturating_add(DbWeight::get().writes(1 as Weight))63 } 64 fn create_item(s: usize, ) -> Weight {65 (130_000_000 as Weight)66 .saturating_add((2135 as Weight).saturating_mul(s as Weight))67 .saturating_add(DbWeight::get().reads(10 as Weight))68 .saturating_add(DbWeight::get().writes(8 as Weight))69 } 70 fn burn_item() -> Weight {71 (170_000_000 as Weight)72 .saturating_add(DbWeight::get().reads(9 as Weight))73 .saturating_add(DbWeight::get().writes(7 as Weight))74 } 75 fn transfer() -> Weight {76 (125_000_000 as Weight)77 .saturating_add(DbWeight::get().reads(7 as Weight))78 .saturating_add(DbWeight::get().writes(7 as Weight))79 } 80 fn approve() -> Weight {81 (45_000_000 as Weight)82 .saturating_add(DbWeight::get().reads(3 as Weight))83 .saturating_add(DbWeight::get().writes(1 as Weight))84 }85 fn transfer_from() -> Weight {86 (150_000_000 as Weight)87 .saturating_add(DbWeight::get().reads(9 as Weight))88 .saturating_add(DbWeight::get().writes(8 as Weight))89 }90 fn set_offchain_schema() -> Weight {91 (33_000_000 as Weight)92 .saturating_add(DbWeight::get().reads(2 as Weight))93 .saturating_add(DbWeight::get().writes(1 as Weight))94 }95 fn set_const_on_chain_schema() -> Weight {96 (11_100_000 as Weight)97 .saturating_add(DbWeight::get().reads(2 as Weight))98 .saturating_add(DbWeight::get().writes(1 as Weight))99 }100 fn set_variable_on_chain_schema() -> Weight {101 (11_100_000 as Weight)102 .saturating_add(DbWeight::get().reads(2 as Weight))103 .saturating_add(DbWeight::get().writes(1 as Weight))104 }105 fn set_variable_meta_data() -> Weight {106 (17_500_000 as Weight)107 .saturating_add(DbWeight::get().reads(2 as Weight))108 .saturating_add(DbWeight::get().writes(1 as Weight))109 }110 // fn enable_contract_sponsoring() -> Weight {111 // (0 as Weight)112 // .saturating_add(DbWeight::get().reads(1 as Weight))113 // .saturating_add(DbWeight::get().writes(1 as Weight))114 // }115}pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -28,15 +28,15 @@
use sp_runtime::sp_std::prelude::Vec;
use sp_runtime::{
traits::{
- DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SaturatedConversion, Saturating,
- SignedExtension, Zero,
+ DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SignedExtension, Zero,
},
transaction_validity::{
- InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError,
- ValidTransaction,
+ InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
},
FixedPointOperand, FixedU128,
};
+use pallet_contracts::ContractAddressFor;
+use sp_runtime::traits::StaticLookup;
#[cfg(test)]
mod mock;
@@ -208,6 +208,7 @@
fn set_const_on_chain_schema() -> Weight;
fn set_variable_on_chain_schema() -> Weight;
fn set_variable_meta_data() -> Weight;
+ // fn enable_contract_sponsoring() -> Weight;
}
#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
@@ -249,7 +250,7 @@
}
}
-pub trait Trait: system::Trait + Sized {
+pub trait Trait: system::Trait + Sized + transaction_payment::Trait + pallet_contracts::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
/// Weight information for extrinsics in this pallet.
@@ -301,9 +302,9 @@
pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => Vec<BasketItem<T::AccountId, T::BlockNumber>>;
pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber;
- // Sponsorship
- pub ContractSponsor get(fn contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;
- pub UnconfirmedContractSponsor get(fn unconfirmed_contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;
+ // Contract Sponsorship and Ownership
+ pub ContractOwner get(fn contract_owner): map hasher(identity) T::AccountId => T::AccountId;
+ pub ContractSelfSponsoring get(fn contract_self_sponsoring): map hasher(identity) T::AccountId => bool;
}
add_extra_genesis {
build(|config: &GenesisConfig<T>| {
@@ -1251,7 +1252,37 @@
ensure_root(origin)?;
<ChainLimit>::put(limits);
Ok(())
- }
+ }
+
+ /// Enable smart contract self-sponsoring.
+ ///
+ /// # Permissions
+ ///
+ /// * Contract Owner
+ ///
+ /// # Arguments
+ ///
+ /// * contract address
+ /// * enable flag
+ ///
+ #[weight = 0]
+ pub fn enable_contract_sponsoring(
+ origin,
+ contract_address: T::AccountId,
+ enable: bool
+ ) -> DispatchResult {
+ let sender = ensure_signed(origin)?;
+ let mut is_owner = false;
+ if <ContractOwner<T>>::contains_key(contract_address.clone()) {
+ let owner = <ContractOwner<T>>::get(&contract_address);
+ is_owner = sender == owner;
+ }
+ ensure!(is_owner, "Only contract owner may call this method");
+
+ <ContractSelfSponsoring<T>>::insert(contract_address, enable);
+ Ok(())
+ }
+
}
}
@@ -1919,11 +1950,11 @@
/// 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: transaction_payment::Trait + Send + Sync>(
- #[codec(compact)] BalanceOf<T>,
+pub struct ChargeTransactionPayment<T: Trait + Send + Sync>(
+ #[codec(compact)] BalanceOf<T>
);
-impl<T: Trait + transaction_payment::Trait + Send + Sync> sp_std::fmt::Debug
+impl<T: Trait + Send + Sync> sp_std::fmt::Debug
for ChargeTransactionPayment<T>
{
#[cfg(feature = "std")]
@@ -1936,10 +1967,9 @@
}
}
-impl<T: Trait + transaction_payment::Trait + Send + Sync> ChargeTransactionPayment<T>
+impl<T: Trait + Send + Sync> ChargeTransactionPayment<T>
where
- T::Call:
- Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>>,
+ T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>> + IsSubType<pallet_contracts::Call<T>>,
BalanceOf<T>: Send + Sync + FixedPointOperand,
{
/// utility constructor. Used only in client/factory code.
@@ -1969,15 +1999,16 @@
// Set fee based on call type. Creating collection costs 1 Unique.
// All other transactions have traditional fees so far
- let fee = match call.is_sub_type() {
- Some(Call::create_collection(..)) => <BalanceOf<T>>::from(1_000_000_000),
- _ => Self::traditional_fee(len, info, tip), // Flat fee model, use only for testing purposes
- // _ => <BalanceOf<T>>::from(100)
- };
+ // let fee = match call.is_sub_type() {
+ // Some(Call::create_collection(..)) => <BalanceOf<T>>::from(1_000_000_000),
+ // _ => Self::traditional_fee(len, info, tip), // Flat fee model, use only for testing purposes
+ // // _ => <BalanceOf<T>>::from(100)
+ // };
+ let fee = Self::traditional_fee(len, info, tip);
// Determine who is paying transaction fee based on ecnomic model
// Parse call to extract collection ID and access collection sponsor
- let sponsor: T::AccountId = match call.is_sub_type() {
+ let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {
Some(Call::create_item(collection_id, _properties, _owner)) => {
<Collection<T>>::get(collection_id).sponsor
}
@@ -2046,6 +2077,39 @@
_ => T::AccountId::default(),
};
+ // Sponsor smart contracts
+ sponsor = match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
+
+ // On instantiation: set the contract owner
+ Some(pallet_contracts::Call::instantiate(_endowment, _gas_limit, code_hash, data)) => {
+
+ let new_contract_address = <T as pallet_contracts::Trait>::DetermineContractAddress::contract_address_for(
+ code_hash,
+ &data,
+ &who,
+ );
+ <ContractOwner<T>>::insert(new_contract_address.clone(), who.clone());
+
+ T::AccountId::default()
+ },
+
+ // When the contract is called, check if the sponsoring is enabled and pay fees from contract endowment if it is
+ Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {
+
+ let mut sp = T::AccountId::default();
+ let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());
+ if <ContractSelfSponsoring<T>>::contains_key(called_contract.clone()) {
+ if <ContractSelfSponsoring<T>>::get(called_contract.clone()) {
+ sp = called_contract;
+ }
+ }
+
+ sp
+ },
+
+ _ => sponsor,
+ };
+
let mut who_pays_fee: T::AccountId = sponsor.clone();
if sponsor == T::AccountId::default() {
who_pays_fee = who.clone();
@@ -2072,11 +2136,12 @@
}
}
-impl<T: Trait + transaction_payment::Trait + Send + Sync> SignedExtension
+
+impl<T: Trait + Send + Sync> SignedExtension
for ChargeTransactionPayment<T>
where
BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,
- T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>>,
+ T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>> + IsSubType<pallet_contracts::Call<T>>,
{
const IDENTIFIER: &'static str = "ChargeTransactionPayment";
type AccountId = T::AccountId;
@@ -2094,18 +2159,12 @@
fn validate(
&self,
- who: &Self::AccountId,
- call: &Self::Call,
- info: &DispatchInfoOf<Self::Call>,
- len: usize,
+ _who: &Self::AccountId,
+ _call: &Self::Call,
+ _info: &DispatchInfoOf<Self::Call>,
+ _len: usize,
) -> TransactionValidity {
- let (fee, _) = self.withdraw_fee(who, call, info, len)?;
-
- let mut r = ValidTransaction::default();
- // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which
- // will be a bit more than setting the priority to tip. For now, this is enough.
- r.priority = fee.saturated_into::<TransactionPriority>();
- Ok(r)
+ Ok(ValidTransaction::default())
}
fn pre_dispatch(
@@ -2156,6 +2215,7 @@
Ok(())
}
}
+
// #endregion
pallets/nft/src/mock.rsdiffbeforeafterboth--- a/pallets/nft/src/mock.rs
+++ b/pallets/nft/src/mock.rs
@@ -1,20 +1,27 @@
// Creating mock runtime here
use crate::{Module, Trait};
+
+use pallet_contracts::{
+ ContractAddressFor, TrieId, TrieIdGenerator,
+};
+
use frame_support::{
impl_outer_origin, parameter_types,
weights::{
- constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},
- Weight,
+ // constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},
+ Weight, IdentityFee,
},
};
use frame_system as system;
+use transaction_payment;
use sp_core::H256;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup, Saturating},
Perbill,
};
+pub use pallet_balances;
impl_outer_origin! {
pub enum Origin for Test {}
@@ -56,13 +63,101 @@
type AvailableBlockRatio = AvailableBlockRatio;
type Version = ();
type PalletInfo = ();
- type AccountData = ();
+ type AccountData = pallet_balances::AccountData<u64>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
}
-impl Trait for Test {
+
+parameter_types! {
+ pub const ExistentialDeposit: u64 = 1;
+ pub const MaxLocks: u32 = 50;
+}
+
+type System = frame_system::Module<Test>;
+impl pallet_balances::Trait for Test {
+ type AccountStore = System;
+ type Balance = u64;
+ type DustRemoval = ();
type Event = ();
+ type ExistentialDeposit = ExistentialDeposit;
+ type WeightInfo = ();
+ type MaxLocks = MaxLocks;
+}
+
+parameter_types! {
+ pub const TransactionByteFee: u64 = 1;
+}
+impl transaction_payment::Trait for Test {
+ type Currency = pallet_balances::Module<Test>;
+ type OnTransactionPayment = ();
+ type TransactionByteFee = TransactionByteFee;
+ type WeightToFee = IdentityFee<u64>;
+ type FeeMultiplierUpdate = ();
+}
+
+
+parameter_types! {
+ pub const MinimumPeriod: u64 = 1;
+}
+impl pallet_timestamp::Trait for Test {
+ type Moment = u64;
+ type OnTimestampSet = ();
+ type MinimumPeriod = MinimumPeriod;
+ type WeightInfo = ();
+}
+
+type Timestamp = pallet_timestamp::Module<Test>;
+type Randomness = pallet_randomness_collective_flip::Module<Test>;
+
+parameter_types! {
+ pub const TombstoneDeposit: u64 = 1;
+ pub const RentByteFee: u64 = 1;
+ pub const RentDepositOffset: u64 = 1;
+ pub const SurchargeReward: u64 = 1;
+}
+
+pub struct DummyTrieIdGenerator;
+impl TrieIdGenerator<u64> for DummyTrieIdGenerator {
+ fn trie_id(account_id: &u64) -> TrieId {
+ let new_seed = *account_id + 1;
+ let mut res = vec![];
+ res.extend_from_slice(&new_seed.to_le_bytes());
+ res.extend_from_slice(&account_id.to_le_bytes());
+ res
+ }
+}
+
+pub struct DummyContractAddressFor;
+impl ContractAddressFor<H256, u64> for DummyContractAddressFor {
+ fn contract_address_for(_code_hash: &H256, _data: &[u8], origin: &u64) -> u64 {
+ *origin + 1
+ }
+}
+
+impl pallet_contracts::Trait for Test {
+ type Time = Timestamp;
+ type Randomness = Randomness;
+ type Currency = pallet_balances::Module<Test>;
+ type Event = ();
+ type DetermineContractAddress = DummyContractAddressFor;
+ type TrieIdGenerator = DummyTrieIdGenerator;
+ type RentPayment = ();
+ type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap;
+ type TombstoneDeposit = TombstoneDeposit;
+ type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset;
+ type RentByteFee = RentByteFee;
+ type RentDepositOffset = RentDepositOffset;
+ type SurchargeReward = SurchargeReward;
+ type MaxDepth = pallet_contracts::DefaultMaxDepth;
+ type MaxValueSize = pallet_contracts::DefaultMaxValueSize;
+ type WeightPrice = ();
+}
+
+impl Trait for Test {
+ type Event = ();
+ type WeightInfo = ();
+
}
pub type TemplateModule = Module<Test>;
pallets/nft/src/tests.rsdiffbeforeafterboth--- a/pallets/nft/src/tests.rs
+++ b/pallets/nft/src/tests.rs
@@ -292,6 +292,77 @@
assert_eq!(TemplateModule::balance_count(1, 1), 1);
assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+ // neg transfer
+ assert_noop!(TemplateModule::transfer_from(
+ origin2.clone(),
+ 1,
+ 2,
+ 1,
+ 1,
+ 1), "Only item owner, collection owner and admins can modify items");
+
+ // do approve
+ assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
+ assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);
+ assert_eq!(
+ TemplateModule::approved(1, (1, 1))[0],
+ ApprovePermissions {
+ approved: 2,
+ amount: 100000000
+ }
+ );
+
+ assert_ok!(TemplateModule::transfer_from(
+ origin2.clone(),
+ 1,
+ 2,
+ 1,
+ 1,
+ 1
+ ));
+ assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 0);
+ });
+}
+
+#[test]
+fn nft_approve_and_transfer_from_white_list() {
+ new_test_ext().execute_with(|| {
+ let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT(2000);
+
+ assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits {
+ collection_numbers_limit: 10,
+ account_token_ownership_limit: 10,
+ collections_admins_limit: 5,
+ custom_data_limit: 2048,
+ nft_sponsor_transfer_timeout: 15,
+ fungible_sponsor_transfer_timeout: 15,
+ refungible_sponsor_transfer_timeout: 15,
+ }));
+
+ let origin1 = Origin::signed(1);
+ let origin2 = Origin::signed(2);
+ assert_ok!(TemplateModule::create_collection(
+ origin1.clone(),
+ col_name1.clone(),
+ col_desc1.clone(),
+ token_prefix1.clone(),
+ mode
+ ));
+ assert_eq!(TemplateModule::collection(1).owner, 1);
+
+ assert_ok!(TemplateModule::create_item(
+ origin1.clone(),
+ 1,
+ [1, 2, 3].to_vec(),
+ 1
+ ));
+ assert_eq!(TemplateModule::nft_item_id(1, 1).data, [1, 2, 3].to_vec());
+ assert_eq!(TemplateModule::balance_count(1, 1), 1);
+ assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
+
assert_ok!(TemplateModule::set_mint_permission(
origin1.clone(),
1,