git.delta.rocks / unique-network / refs/commits / 3950758e00c3

difftreelog

Merge branch 'develop' into feature/NFTPAR-142

sotmorskiy2020-11-11parents: #f58e687 #6d406a4.patch.diff
in: master
# Conflicts:
#	pallets/nft/src/default_weights.rs
#	pallets/nft/src/lib.rs

6 files changed

modifiedCargo.lockdiffbeforeafterboth
3737 "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",
modifiedpallets/nft/Cargo.tomldiffbeforeafterboth
73branch = 'v2.0.0_release'73branch = 'v2.0.0_release'
74optional = true74optional = true
75
76[dependencies.pallet-contracts]
77default-features = false
78git = 'https://github.com/usetech-llc/substrate.git'
79package = 'pallet-contracts'
80branch = 'v2.0.0_release'
81version = '2.0.0'
82
83[dependencies.pallet-balances]
84default-features = false
85git = 'https://github.com/usetech-llc/substrate.git'
86package = 'pallet-balances'
87branch = 'v2.0.0_release'
88version = '2.0.0'
89
90[dependencies.pallet-timestamp]
91default-features = false
92git = 'https://github.com/usetech-llc/substrate.git'
93package = 'pallet-timestamp'
94branch = 'v2.0.0_release'
95version = '2.0.0'
96
97[dependencies.pallet-randomness-collective-flip]
98default-features = false
99git = 'https://github.com/usetech-llc/substrate.git'
100package = 'pallet-randomness-collective-flip'
101branch = 'v2.0.0_release'
102version = '2.0.0'
75103
76[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',
modifiedpallets/nft/src/default_weights.rsdiffbeforeafterboth
107 .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}
111116
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
28use 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;
4040
41#[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}
212213
213#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]214#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
249 }250 }
250}251}
251252
252pub 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>;
254255
255 /// 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;
303304
304 // Sponsorship305 // Contract Sponsorship and Ownership
305 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 }
1256
1257 /// Enable smart contract self-sponsoring.
1258 ///
1259 /// # Permissions
1260 ///
1261 /// * Contract Owner
1262 ///
1263 /// # Arguments
1264 ///
1265 /// * contract address
1266 /// * enable flag
1267 ///
1268 #[weight = 0]
1269 pub fn enable_contract_sponsoring(
1270 origin,
1271 contract_address: T::AccountId,
1272 enable: bool
1273 ) -> 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");
1281
1282 <ContractSelfSponsoring<T>>::insert(contract_address, enable);
1283 Ok(())
1284 }
1285
1255 }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 priority
1920/// 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);
19251956
1926impl<T: Trait + transaction_payment::Trait + Send + Sync> sp_std::fmt::Debug1957impl<T: Trait + Send + Sync> sp_std::fmt::Debug
1927 for ChargeTransactionPayment<T>1958 for ChargeTransactionPayment<T>
1928{1959{
1929 #[cfg(feature = "std")]1960 #[cfg(feature = "std")]
1936 }1967 }
1937}1968}
19381969
1939impl<T: Trait + transaction_payment::Trait + Send + Sync> ChargeTransactionPayment<T>1970impl<T: Trait + Send + Sync> ChargeTransactionPayment<T>
1940where1971where
1941 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{
19691999
1970 // 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 far
2002 // 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 purposes
2005 // // _ => <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 purposes
1975 // _ => <BalanceOf<T>>::from(100)
1976 };
19772008
1978 // Determine who is paying transaction fee based on ecnomic model2009 // Determine who is paying transaction fee based on ecnomic model
1979 // Parse call to extract collection ID and access collection sponsor2010 // Parse call to extract collection ID and access collection sponsor
1980 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).sponsor
1983 }2014 }
2046 _ => T::AccountId::default(),2077 _ => T::AccountId::default(),
2047 };2078 };
2079
2080 // Sponsor smart contracts
2081 sponsor = match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
2082
2083 // On instantiation: set the contract owner
2084 Some(pallet_contracts::Call::instantiate(_endowment, _gas_limit, code_hash, data)) => {
2085
2086 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());
2092
2093 T::AccountId::default()
2094 },
2095
2096 // When the contract is called, check if the sponsoring is enabled and pay fees from contract endowment if it is
2097 Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {
2098
2099 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 }
2106
2107 sp
2108 },
2109
2110 _ => sponsor,
2111 };
20482112
2049 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}
2138
20742139
2075impl<T: Trait + transaction_payment::Trait + Send + Sync> SignedExtension2140impl<T: Trait + Send + Sync> SignedExtension
2076 for ChargeTransactionPayment<T>2141 for ChargeTransactionPayment<T>
2077where2142where
2078 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;
20942159
2095 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)?;
2103
2104 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, which
2106 // 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 }
21102169
2111 fn pre_dispatch(2170 fn pre_dispatch(
modifiedpallets/nft/src/mock.rsdiffbeforeafterboth
22
3use crate::{Module, Trait};3use crate::{Module, Trait};
4
5use pallet_contracts::{
6 ContractAddressFor, TrieId, TrieIdGenerator,
7};
8
4use 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;
1825
19impl_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}
71
72parameter_types! {
73 pub const ExistentialDeposit: u64 = 1;
74 pub const MaxLocks: u32 = 50;
75}
76
77type 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}
87
88parameter_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}
98
99
100parameter_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}
109
110type Timestamp = pallet_timestamp::Module<Test>;
111type Randomness = pallet_randomness_collective_flip::Module<Test>;
112
113parameter_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}
119
120pub 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 res
128 }
129}
130
131pub struct DummyContractAddressFor;
132impl ContractAddressFor<H256, u64> for DummyContractAddressFor {
133 fn contract_address_for(_code_hash: &H256, _data: &[u8], origin: &u64) -> u64 {
134 *origin + 1
135 }
136}
137
138impl 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}
156
64impl Trait for Test {157impl Trait for Test {
65 type Event = ();158 type Event = ();
159 type WeightInfo = ();
160
66}161}
67pub type TemplateModule = Module<Test>;162pub type TemplateModule = Module<Test>;
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
277}277}
278278
279#[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);
285
286 let data = default_nft_data();
287 create_test_item(collection_id, &data);
288
289 let origin1 = Origin::signed(1);
290 let origin2 = Origin::signed(2);
291
292 assert_eq!(TemplateModule::balance_count(1, 1), 1);
293 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
294
295 // neg transfer
296 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");
303
304 // do approve
305 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: 100000000
312 }
313 );
314
315 assert_ok!(TemplateModule::transfer_from(
316 origin2.clone(),
317 1,
318 2,
319 1,
320 1,
321 1
322 ));
323 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 0);
324 });
325}
326
327#[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>>();
285
286 let data = default_nft_data();332 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
333 let mode: CollectionMode = CollectionMode::NFT(2000);
334
287 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 }));
288344
289 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 mode
353 ));
354 assert_eq!(TemplateModule::collection(1).owner, 1);
355
356 assert_ok!(TemplateModule::create_item(
357 origin1.clone(),
358 1,
359 [1, 2, 3].to_vec(),
360 1
361 ));
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