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.lockdiffbeforeafterboth3737 "frame-support",3737 "frame-support",3738 "frame-system",3738 "frame-system",3739 "log",3739 "log",3740 "pallet-contracts",3740 "pallet-transaction-payment",3741 "pallet-transaction-payment",3741 "parity-scale-codec",3742 "parity-scale-codec",3742 "serde",3743 "serde",pallets/nft/Cargo.tomldiffbeforeafterboth73branch = 'v2.0.0_release'73branch = 'v2.0.0_release'74optional = true74optional = true7576[dependencies.pallet-contracts]77default-features = false78git = 'https://github.com/usetech-llc/substrate.git'79package = 'pallet-contracts'80branch = 'v2.0.0_release'81version = '2.0.0'8283[dependencies.pallet-balances]84default-features = false85git = 'https://github.com/usetech-llc/substrate.git'86package = 'pallet-balances'87branch = 'v2.0.0_release'88version = '2.0.0'8990[dependencies.pallet-timestamp]91default-features = false92git = 'https://github.com/usetech-llc/substrate.git'93package = 'pallet-timestamp'94branch = 'v2.0.0_release'95version = '2.0.0'9697[dependencies.pallet-randomness-collective-flip]98default-features = false99git = 'https://github.com/usetech-llc/substrate.git'100package = 'pallet-randomness-collective-flip'101branch = 'v2.0.0_release'102version = '2.0.0'7510376[features]104[features]77default = ['std']105default = ['std']80 "serde/std",108 "serde/std",81 'frame-support/std',109 'frame-support/std',82 'frame-system/std',110 'frame-system/std',111 'pallet-balances/std',112 'pallet-timestamp/std',113 'pallet-randomness-collective-flip/std',83 'sp-std/std',114 'sp-std/std',84 'sp-runtime/std',115 'sp-runtime/std',85 'frame-benchmarking/std',116 'frame-benchmarking/std',pallets/nft/src/default_weights.rsdiffbeforeafterboth107 .saturating_add(DbWeight::get().reads(2 as Weight))107 .saturating_add(DbWeight::get().reads(2 as Weight))108 .saturating_add(DbWeight::get().writes(1 as Weight))108 .saturating_add(DbWeight::get().writes(1 as Weight))109 }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 // }110}115}111116pallets/nft/src/lib.rsdiffbeforeafterboth28use sp_runtime::sp_std::prelude::Vec;28use sp_runtime::sp_std::prelude::Vec;29use sp_runtime::{29use sp_runtime::{30 traits::{30 traits::{31 DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SaturatedConversion, Saturating,31 DispatchInfoOf, Dispatchable, PostDispatchInfoOf, Saturating, SignedExtension, Zero,32 SignedExtension, Zero,33 },32 },34 transaction_validity::{33 transaction_validity::{35 InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError,34 InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,36 ValidTransaction,37 },35 },38 FixedPointOperand, FixedU128,36 FixedPointOperand, FixedU128,39};37};38use pallet_contracts::ContractAddressFor;39use sp_runtime::traits::StaticLookup;404041#[cfg(test)]41#[cfg(test)]42mod mock;42mod mock;208 fn set_const_on_chain_schema() -> Weight;208 fn set_const_on_chain_schema() -> Weight;209 fn set_variable_on_chain_schema() -> Weight;209 fn set_variable_on_chain_schema() -> Weight;210 fn set_variable_meta_data() -> Weight;210 fn set_variable_meta_data() -> Weight;211 // fn enable_contract_sponsoring() -> Weight;211}212}212213213#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]214#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]249 }250 }250}251}251252252pub trait Trait: system::Trait + Sized {253pub trait Trait: system::Trait + Sized + transaction_payment::Trait + pallet_contracts::Trait {253 type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;254 type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;254255255 /// Weight information for extrinsics in this pallet.256 /// Weight information for extrinsics in this pallet.301 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>>;302 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>>;302 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber;303 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => T::BlockNumber;303304304 // Sponsorship305 // Contract Sponsorship and Ownership305 pub ContractSponsor get(fn contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;306 pub ContractOwner get(fn contract_owner): map hasher(identity) T::AccountId => T::AccountId;306 pub UnconfirmedContractSponsor get(fn unconfirmed_contract_sponsor): map hasher(identity) T::AccountId => T::AccountId;307 pub ContractSelfSponsoring get(fn contract_self_sponsoring): map hasher(identity) T::AccountId => bool;307 }308 }308 add_extra_genesis {309 add_extra_genesis {309 build(|config: &GenesisConfig<T>| {310 build(|config: &GenesisConfig<T>| {1253 Ok(())1254 Ok(())1254 } 1255 }12561257 /// Enable smart contract self-sponsoring.1258 /// 1259 /// # Permissions1260 /// 1261 /// * Contract Owner1262 /// 1263 /// # Arguments1264 /// 1265 /// * contract address1266 /// * enable flag1267 /// 1268 #[weight = 0]1269 pub fn enable_contract_sponsoring(1270 origin,1271 contract_address: T::AccountId,1272 enable: bool1273 ) -> DispatchResult {1274 let sender = ensure_signed(origin)?;1275 let mut is_owner = false;1276 if <ContractOwner<T>>::contains_key(contract_address.clone()) {1277 let owner = <ContractOwner<T>>::get(&contract_address);1278 is_owner = sender == owner;1279 }1280 ensure!(is_owner, "Only contract owner may call this method");12811282 <ContractSelfSponsoring<T>>::insert(contract_address, enable);1283 Ok(())1284 }12851255 }1286 }1256}1287}1919/// Require the transactor pay for themselves and maybe include a tip to gain additional priority1950/// Require the transactor pay for themselves and maybe include a tip to gain additional priority1920/// in the queue.1951/// in the queue.1921#[derive(Encode, Decode, Clone, Eq, PartialEq)]1952#[derive(Encode, Decode, Clone, Eq, PartialEq)]1922pub struct ChargeTransactionPayment<T: transaction_payment::Trait + Send + Sync>(1953pub struct ChargeTransactionPayment<T: Trait + Send + Sync>(1923 #[codec(compact)] BalanceOf<T>,1954 #[codec(compact)] BalanceOf<T>1924);1955);192519561926impl<T: Trait + transaction_payment::Trait + Send + Sync> sp_std::fmt::Debug1957impl<T: Trait + Send + Sync> sp_std::fmt::Debug1927 for ChargeTransactionPayment<T>1958 for ChargeTransactionPayment<T>1928{1959{1929 #[cfg(feature = "std")]1960 #[cfg(feature = "std")]1936 }1967 }1937}1968}193819691939impl<T: Trait + transaction_payment::Trait + Send + Sync> ChargeTransactionPayment<T>1970impl<T: Trait + Send + Sync> ChargeTransactionPayment<T>1940where1971where1941 T::Call:1972 T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>> + IsSubType<pallet_contracts::Call<T>>,1942 Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>>,1943 BalanceOf<T>: Send + Sync + FixedPointOperand,1973 BalanceOf<T>: Send + Sync + FixedPointOperand,1944{1974{196919991970 // Set fee based on call type. Creating collection costs 1 Unique.2000 // Set fee based on call type. Creating collection costs 1 Unique.1971 // All other transactions have traditional fees so far2001 // All other transactions have traditional fees so far2002 // let fee = match call.is_sub_type() {2003 // Some(Call::create_collection(..)) => <BalanceOf<T>>::from(1_000_000_000),2004 // _ => Self::traditional_fee(len, info, tip), // Flat fee model, use only for testing purposes2005 // // _ => <BalanceOf<T>>::from(100)2006 // };1972 let fee = match call.is_sub_type() {2007 let fee = Self::traditional_fee(len, info, tip);1973 Some(Call::create_collection(..)) => <BalanceOf<T>>::from(1_000_000_000),1974 _ => Self::traditional_fee(len, info, tip), // Flat fee model, use only for testing purposes1975 // _ => <BalanceOf<T>>::from(100)1976 };197720081978 // Determine who is paying transaction fee based on ecnomic model2009 // Determine who is paying transaction fee based on ecnomic model1979 // Parse call to extract collection ID and access collection sponsor2010 // Parse call to extract collection ID and access collection sponsor1980 let sponsor: T::AccountId = match call.is_sub_type() {2011 let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {1981 Some(Call::create_item(collection_id, _properties, _owner)) => {2012 Some(Call::create_item(collection_id, _properties, _owner)) => {1982 <Collection<T>>::get(collection_id).sponsor2013 <Collection<T>>::get(collection_id).sponsor1983 }2014 }2046 _ => T::AccountId::default(),2077 _ => T::AccountId::default(),2047 };2078 };20792080 // Sponsor smart contracts2081 sponsor = match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {20822083 // On instantiation: set the contract owner2084 Some(pallet_contracts::Call::instantiate(_endowment, _gas_limit, code_hash, data)) => {20852086 let new_contract_address = <T as pallet_contracts::Trait>::DetermineContractAddress::contract_address_for(2087 code_hash,2088 &data,2089 &who,2090 );2091 <ContractOwner<T>>::insert(new_contract_address.clone(), who.clone());20922093 T::AccountId::default()2094 },20952096 // When the contract is called, check if the sponsoring is enabled and pay fees from contract endowment if it is2097 Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {20982099 let mut sp = T::AccountId::default();2100 let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());2101 if <ContractSelfSponsoring<T>>::contains_key(called_contract.clone()) {2102 if <ContractSelfSponsoring<T>>::get(called_contract.clone()) {2103 sp = called_contract;2104 }2105 }21062107 sp2108 },21092110 _ => sponsor,2111 };204821122049 let mut who_pays_fee: T::AccountId = sponsor.clone();2113 let mut who_pays_fee: T::AccountId = sponsor.clone();2050 if sponsor == T::AccountId::default() {2114 if sponsor == T::AccountId::default() {2073}2137}2138207421392075impl<T: Trait + transaction_payment::Trait + Send + Sync> SignedExtension2140impl<T: Trait + Send + Sync> SignedExtension2076 for ChargeTransactionPayment<T>2141 for ChargeTransactionPayment<T>2077where2142where2078 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,2143 BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,2079 T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>>,2144 T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Call<T>> + IsSubType<pallet_contracts::Call<T>>,2080{2145{2081 const IDENTIFIER: &'static str = "ChargeTransactionPayment";2146 const IDENTIFIER: &'static str = "ChargeTransactionPayment";2082 type AccountId = T::AccountId;2147 type AccountId = T::AccountId;209421592095 fn validate(2160 fn validate(2096 &self,2161 &self,2097 who: &Self::AccountId,2162 _who: &Self::AccountId,2098 call: &Self::Call,2163 _call: &Self::Call,2099 info: &DispatchInfoOf<Self::Call>,2164 _info: &DispatchInfoOf<Self::Call>,2100 len: usize,2165 _len: usize,2101 ) -> TransactionValidity {2166 ) -> TransactionValidity {2102 let (fee, _) = self.withdraw_fee(who, call, info, len)?;21032104 let mut r = ValidTransaction::default();2167 Ok(ValidTransaction::default())2105 // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which2106 // will be a bit more than setting the priority to tip. For now, this is enough.2107 r.priority = fee.saturated_into::<TransactionPriority>();2108 Ok(r)2109 }2168 }211021692111 fn pre_dispatch(2170 fn pre_dispatch(pallets/nft/src/mock.rsdiffbeforeafterboth223use crate::{Module, Trait};3use crate::{Module, Trait};45use pallet_contracts::{6 ContractAddressFor, TrieId, TrieIdGenerator,7};84use frame_support::{9use frame_support::{5 impl_outer_origin, parameter_types,10 impl_outer_origin, parameter_types,6 weights::{11 weights::{7 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},12 // constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},8 Weight,13 Weight, IdentityFee,9 },14 },10};15};11use frame_system as system;16use frame_system as system;17use transaction_payment;12use sp_core::H256;18use sp_core::H256;13use sp_runtime::{19use sp_runtime::{14 testing::Header,20 testing::Header,15 traits::{BlakeTwo256, IdentityLookup, Saturating},21 traits::{BlakeTwo256, IdentityLookup, Saturating},16 Perbill,22 Perbill,17};23};24pub use pallet_balances;182519impl_outer_origin! {26impl_outer_origin! {20 pub enum Origin for Test {}27 pub enum Origin for Test {}56 type AvailableBlockRatio = AvailableBlockRatio;63 type AvailableBlockRatio = AvailableBlockRatio;57 type Version = ();64 type Version = ();58 type PalletInfo = ();65 type PalletInfo = ();59 type AccountData = ();66 type AccountData = pallet_balances::AccountData<u64>;60 type OnNewAccount = ();67 type OnNewAccount = ();61 type OnKilledAccount = ();68 type OnKilledAccount = ();62 type SystemWeightInfo = ();69 type SystemWeightInfo = ();63}70}7172parameter_types! {73 pub const ExistentialDeposit: u64 = 1;74 pub const MaxLocks: u32 = 50;75}7677type System = frame_system::Module<Test>;78impl pallet_balances::Trait for Test {79 type AccountStore = System;80 type Balance = u64;81 type DustRemoval = ();82 type Event = ();83 type ExistentialDeposit = ExistentialDeposit;84 type WeightInfo = ();85 type MaxLocks = MaxLocks;86}8788parameter_types! {89 pub const TransactionByteFee: u64 = 1;90}91impl transaction_payment::Trait for Test {92 type Currency = pallet_balances::Module<Test>;93 type OnTransactionPayment = ();94 type TransactionByteFee = TransactionByteFee;95 type WeightToFee = IdentityFee<u64>;96 type FeeMultiplierUpdate = ();97}9899100parameter_types! {101 pub const MinimumPeriod: u64 = 1;102}103impl pallet_timestamp::Trait for Test {104 type Moment = u64;105 type OnTimestampSet = ();106 type MinimumPeriod = MinimumPeriod;107 type WeightInfo = ();108}109110type Timestamp = pallet_timestamp::Module<Test>;111type Randomness = pallet_randomness_collective_flip::Module<Test>;112113parameter_types! {114 pub const TombstoneDeposit: u64 = 1;115 pub const RentByteFee: u64 = 1;116 pub const RentDepositOffset: u64 = 1;117 pub const SurchargeReward: u64 = 1;118}119120pub struct DummyTrieIdGenerator;121impl TrieIdGenerator<u64> for DummyTrieIdGenerator {122 fn trie_id(account_id: &u64) -> TrieId {123 let new_seed = *account_id + 1;124 let mut res = vec![];125 res.extend_from_slice(&new_seed.to_le_bytes());126 res.extend_from_slice(&account_id.to_le_bytes());127 res128 }129}130131pub struct DummyContractAddressFor;132impl ContractAddressFor<H256, u64> for DummyContractAddressFor {133 fn contract_address_for(_code_hash: &H256, _data: &[u8], origin: &u64) -> u64 {134 *origin + 1135 }136}137138impl pallet_contracts::Trait for Test {139 type Time = Timestamp;140 type Randomness = Randomness;141 type Currency = pallet_balances::Module<Test>;142 type Event = ();143 type DetermineContractAddress = DummyContractAddressFor;144 type TrieIdGenerator = DummyTrieIdGenerator;145 type RentPayment = ();146 type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap;147 type TombstoneDeposit = TombstoneDeposit;148 type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset;149 type RentByteFee = RentByteFee;150 type RentDepositOffset = RentDepositOffset;151 type SurchargeReward = SurchargeReward;152 type MaxDepth = pallet_contracts::DefaultMaxDepth;153 type MaxValueSize = pallet_contracts::DefaultMaxValueSize;154 type WeightPrice = ();155}15664impl Trait for Test {157impl Trait for Test {65 type Event = ();158 type Event = ();159 type WeightInfo = ();16066}161}67pub type TemplateModule = Module<Test>;162pub type TemplateModule = Module<Test>;pallets/nft/src/tests.rsdiffbeforeafterboth277}277}278278279#[test]279#[test]280fn nft_approve_and_transfer_from() {280fn nft_approve_and_transfer_from() {281 new_test_ext().execute_with(|| {282 default_limits();283 284 let collection_id = create_test_collection(&CollectionMode::NFT);285286 let data = default_nft_data();287 create_test_item(collection_id, &data);288289 let origin1 = Origin::signed(1);290 let origin2 = Origin::signed(2);291292 assert_eq!(TemplateModule::balance_count(1, 1), 1);293 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);294295 // neg transfer296 assert_noop!(TemplateModule::transfer_from(297 origin2.clone(),298 1,299 2,300 1,301 1,302 1), "Only item owner, collection owner and admins can modify items");303304 // do approve305 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));306 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);307 assert_eq!(308 TemplateModule::approved(1, (1, 1))[0],309 ApprovePermissions {310 approved: 2,311 amount: 100000000312 }313 );314315 assert_ok!(TemplateModule::transfer_from(316 origin2.clone(),317 1,318 2,319 1,320 1,321 1322 ));323 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 0);324 });325}326327#[test]328fn nft_approve_and_transfer_from_white_list() {281 new_test_ext().execute_with(|| {329 new_test_ext().execute_with(|| {282 default_limits();330 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();283 284 let collection_id = create_test_collection(&CollectionMode::NFT);331 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();285286 let data = default_nft_data();332 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();333 let mode: CollectionMode = CollectionMode::NFT(2000);334287 create_test_item(collection_id, &data);335 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 336 collection_numbers_limit: 10,337 account_token_ownership_limit: 10,338 collections_admins_limit: 5,339 custom_data_limit: 2048,340 nft_sponsor_transfer_timeout: 15,341 fungible_sponsor_transfer_timeout: 15,342 refungible_sponsor_transfer_timeout: 15, 343 }));288344289 let origin1 = Origin::signed(1);345 let origin1 = Origin::signed(1);290 let origin2 = Origin::signed(2);346 let origin2 = Origin::signed(2);291347 assert_ok!(TemplateModule::create_collection(348 origin1.clone(),349 col_name1.clone(),350 col_desc1.clone(),351 token_prefix1.clone(),352 mode353 ));354 assert_eq!(TemplateModule::collection(1).owner, 1);355356 assert_ok!(TemplateModule::create_item(357 origin1.clone(),358 1,359 [1, 2, 3].to_vec(),360 1361 ));362 assert_eq!(TemplateModule::nft_item_id(1, 1).data, [1, 2, 3].to_vec());292 assert_eq!(TemplateModule::balance_count(1, 1), 1);363 assert_eq!(TemplateModule::balance_count(1, 1), 1);293 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);364 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);294365