git.delta.rocks / unique-network / refs/commits / f3ce0b5ee1c5

difftreelog

refactor Remove variable data from tokens

Daniel Shiposha2022-05-14parent: #c4410a4.patch.diff
in: master

23 files changed

modifiedclient/rpc/src/lib.rsdiffbeforeafterboth
71 token: TokenId,71 token: TokenId,
72 at: Option<BlockHash>,72 at: Option<BlockHash>,
73 ) -> Result<Vec<u8>>;73 ) -> Result<Vec<u8>>;
74 #[rpc(name = "unique_variableMetadata")]
75 fn variable_metadata(
76 &self,
77 collection: CollectionId,
78 token: TokenId,
79 at: Option<BlockHash>,
80 ) -> Result<Vec<u8>>;
8174
82 #[rpc(name = "unique_collectionProperties")]75 #[rpc(name = "unique_collectionProperties")]
83 fn collection_properties(76 fn collection_properties(
279 );272 );
280 pass_method!(topmost_token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>);273 pass_method!(topmost_token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>);
281 pass_method!(const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);274 pass_method!(const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);
282 pass_method!(variable_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);
283275
284 pass_method!(collection_properties(276 pass_method!(collection_properties(
285 collection: CollectionId,277 collection: CollectionId,
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
33 MAX_TOKEN_PREFIX_LENGTH, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, TokenId,33 MAX_TOKEN_PREFIX_LENGTH, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, TokenId,
34 CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode, NFT_SPONSOR_TRANSFER_TIMEOUT,34 CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode, NFT_SPONSOR_TRANSFER_TIMEOUT,
35 FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT,35 FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT,
36 CUSTOM_DATA_LIMIT, CollectionLimits, CustomDataLimit, CreateCollectionData, SponsorshipState,36 CUSTOM_DATA_LIMIT, CollectionLimits, CreateCollectionData, SponsorshipState,
37 CreateItemExData, SponsoringRateLimit, budget::Budget, COLLECTION_FIELD_LIMIT, CollectionField,37 CreateItemExData, SponsoringRateLimit, budget::Budget, COLLECTION_FIELD_LIMIT, CollectionField,
38 PhantomType, Property, Properties, PropertiesPermissionMap, PropertyKey, PropertyPermission,38 PhantomType, Property, Properties, PropertiesPermissionMap, PropertyKey, PropertyPermission,
39 PropertiesError, PropertyKeyPermission, TokenData, TrySet,39 PropertiesError, PropertyKeyPermission, TokenData, TrySet,
312 CollectionTokenPrefixLimitExceeded,312 CollectionTokenPrefixLimitExceeded,
313 /// Total collections bound exceeded.313 /// Total collections bound exceeded.
314 TotalCollectionsLimitExceeded,314 TotalCollectionsLimitExceeded,
315 /// variable_data exceeded data limit.
316 TokenVariableDataLimitExceeded,
317 /// Exceeded max admin count315 /// Exceeded max admin count
318 CollectionAdminCountExceeded,316 CollectionAdminCountExceeded,
319 /// Collection limit bounds per collection exceeded317 /// Collection limit bounds per collection exceeded
1073 fn approve() -> Weight;1071 fn approve() -> Weight;
1074 fn transfer_from() -> Weight;1072 fn transfer_from() -> Weight;
1075 fn burn_from() -> Weight;1073 fn burn_from() -> Weight;
1076 fn set_variable_metadata(bytes: u32) -> Weight;
1077}1074}
10781075
1079pub trait CommonCollectionOperations<T: Config> {1076pub trait CommonCollectionOperations<T: Config> {
1163 nesting_budget: &dyn Budget,1160 nesting_budget: &dyn Budget,
1164 ) -> DispatchResultWithPostInfo;1161 ) -> DispatchResultWithPostInfo;
1165
1166 fn set_variable_metadata(
1167 &self,
1168 sender: T::CrossAccountId,
1169 token: TokenId,
1170 data: BoundedVec<u8, CustomDataLimit>,
1171 ) -> DispatchResultWithPostInfo;
11721162
1173 fn check_nesting(1163 fn check_nesting(
1174 &self,1164 &self,
11851175
1186 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;1176 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;
1187 fn const_metadata(&self, token: TokenId) -> Vec<u8>;1177 fn const_metadata(&self, token: TokenId) -> Vec<u8>;
1188 fn variable_metadata(&self, token: TokenId) -> Vec<u8>;
1189 fn token_properties(&self, token_id: TokenId, keys: Vec<PropertyKey>) -> Vec<Property>;1178 fn token_properties(&self, token_id: TokenId, keys: Vec<PropertyKey>) -> Vec<Property>;
1190 /// Amount of unique collection tokens1179 /// Amount of unique collection tokens
1191 fn total_supply(&self) -> u32;1180 fn total_supply(&self) -> u32;
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
1616
17use core::marker::PhantomData;17use core::marker::PhantomData;
1818
19use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};19use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
20use up_data_structs::{TokenId, CollectionId, CreateItemExData, budget::Budget};20use up_data_structs::{TokenId, CollectionId, CreateItemExData, budget::Budget};
21use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};21use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
22use sp_runtime::ArithmeticError;22use sp_runtime::ArithmeticError;
23use sp_std::{vec::Vec, vec};23use sp_std::{vec::Vec, vec};
24use up_data_structs::{CustomDataLimit, Property, PropertyKey, PropertyKeyPermission};24use up_data_structs::{Property, PropertyKey, PropertyKeyPermission};
2525
26use crate::{26use crate::{
27 Allowance, Balance, Config, Error, FungibleHandle, Pallet, SelfWeightOf, weights::WeightInfo,27 Allowance, Balance, Config, Error, FungibleHandle, Pallet, SelfWeightOf, weights::WeightInfo,
86 <SelfWeightOf<T>>::burn_from()86 <SelfWeightOf<T>>::burn_from()
87 }87 }
88
89 fn set_variable_metadata(_bytes: u32) -> Weight {
90 // Error
91 0
92 }
93}88}
9489
95impl<T: Config> CommonCollectionOperations<T> for FungibleHandle<T> {90impl<T: Config> CommonCollectionOperations<T> for FungibleHandle<T> {
287 fail!(<Error<T>>::SettingPropertiesNotAllowed)282 fail!(<Error<T>>::SettingPropertiesNotAllowed)
288 }283 }
289
290 fn set_variable_metadata(
291 &self,
292 _sender: T::CrossAccountId,
293 _token: TokenId,
294 _data: BoundedVec<u8, CustomDataLimit>,
295 ) -> DispatchResultWithPostInfo {
296 fail!(<Error<T>>::FungibleItemsDontHaveData)
297 }
298284
299 fn check_nesting(285 fn check_nesting(
300 &self,286 &self,
332 fn const_metadata(&self, _token: TokenId) -> Vec<u8> {318 fn const_metadata(&self, _token: TokenId) -> Vec<u8> {
333 Vec::new()319 Vec::new()
334 }320 }
335 fn variable_metadata(&self, _token: TokenId) -> Vec<u8> {
336 Vec::new()
337 }
338321
339 fn token_properties(&self, _token_id: TokenId, _keys: Vec<PropertyKey>) -> Vec<Property> {322 fn token_properties(&self, _token_id: TokenId, _keys: Vec<PropertyKey>) -> Vec<Property> {
340 Vec::new()323 Vec::new()
modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
27scale-info = { version = "2.0.1", default-features = false, features = [27scale-info = { version = "2.0.1", default-features = false, features = [
28 "derive",28 "derive",
29] }29] }
30struct-versioning = { path = "../../crates/struct-versioning" }
3031
31[features]32[features]
32default = ["std"]33default = ["std"]
modifiedpallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth
2828
29fn create_max_item_data<T: Config>(owner: T::CrossAccountId) -> CreateItemData<T> {29fn create_max_item_data<T: Config>(owner: T::CrossAccountId) -> CreateItemData<T> {
30 let const_data = create_data::<CUSTOM_DATA_LIMIT>();30 let const_data = create_data::<CUSTOM_DATA_LIMIT>();
31 let variable_data = create_data::<CUSTOM_DATA_LIMIT>();
32 CreateItemData::<T> {31 CreateItemData::<T> {
33 const_data,32 const_data,
34 variable_data,
35 owner,33 owner,
36 }34 }
37}35}
126 <Pallet<T>>::set_allowance(&collection, &sender, item, Some(&burner))?;124 <Pallet<T>>::set_allowance(&collection, &sender, item, Some(&burner))?;
127 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, &Unlimited)?}125 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, &Unlimited)?}
128
129 set_variable_metadata {
130 let b in 0..CUSTOM_DATA_LIMIT;
131 bench_init!{
132 owner: sub; collection: collection(owner);
133 owner: cross_from_sub; sender: cross_sub;
134 };
135 let item = create_max_item(&collection, &owner, sender.clone())?;
136 let data = create_var_data(b).try_into().unwrap();
137 }: {<Pallet<T>>::set_variable_metadata(&collection, &sender, item, data)?}
138}126}
139127
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
1616
17use core::marker::PhantomData;17use core::marker::PhantomData;
1818
19use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};19use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
20use up_data_structs::{20use up_data_structs::{
21 TokenId, CustomDataLimit, CreateItemExData, CollectionId, budget::Budget, Property,21 TokenId, CreateItemExData, CollectionId, budget::Budget, Property,
22 PropertyKey, PropertyKeyPermission,22 PropertyKey, PropertyKeyPermission,
23};23};
24use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};24use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
87 <SelfWeightOf<T>>::burn_from()87 <SelfWeightOf<T>>::burn_from()
88 }88 }
89
90 fn set_variable_metadata(bytes: u32) -> Weight {
91 <SelfWeightOf<T>>::set_variable_metadata(bytes)
92 }
93}89}
9490
95fn map_create_data<T: Config>(91fn map_create_data<T: Config>(
99 match data {95 match data {
100 up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {96 up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {
101 const_data: data.const_data,97 const_data: data.const_data,
102 variable_data: data.variable_data,
103 properties: data.properties,98 properties: data.properties,
104 owner: to.clone(),99 owner: to.clone(),
105 }),100 }),
327 }322 }
328 }323 }
329
330 fn set_variable_metadata(
331 &self,
332 sender: T::CrossAccountId,
333 token: TokenId,
334 data: BoundedVec<u8, CustomDataLimit>,
335 ) -> DispatchResultWithPostInfo {
336 let len = data.len();
337 with_weight(
338 <Pallet<T>>::set_variable_metadata(self, &sender, token, data),
339 <CommonWeights<T>>::set_variable_metadata(len as u32),
340 )
341 }
342324
343 fn check_nesting(325 fn check_nesting(
344 &self,326 &self,
379 .unwrap_or_default()361 .unwrap_or_default()
380 .into_inner()362 .into_inner()
381 }363 }
382 fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
383 <TokenData<T>>::get((self.id, token))
384 .map(|t| t.variable_data)
385 .unwrap_or_default()
386 .into_inner()
387 }
388364
389 fn token_properties(&self, token_id: TokenId, keys: Vec<PropertyKey>) -> Vec<Property> {365 fn token_properties(&self, token_id: TokenId, keys: Vec<PropertyKey>) -> Vec<Property> {
390 let properties = <Pallet<T>>::token_properties((self.id, token_id));366 let properties = <Pallet<T>>::token_properties((self.id, token_id));
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
24use up_data_structs::{TokenId, SchemaVersion};24use up_data_structs::{TokenId, SchemaVersion};
25use pallet_evm_coder_substrate::dispatch_to_evm;25use pallet_evm_coder_substrate::dispatch_to_evm;
26use sp_core::{H160, U256};26use sp_core::{H160, U256};
27use sp_std::{vec::Vec, vec};27use sp_std::vec::Vec;
28use pallet_common::{28use pallet_common::{
29 erc::{CommonEvmHandler, PrecompileResult, CollectionPropertiesCall},29 erc::{CommonEvmHandler, PrecompileResult, CollectionPropertiesCall},
30 CollectionHandle,30 CollectionHandle,
274 &caller,274 &caller,
275 CreateItemData::<T> {275 CreateItemData::<T> {
276 const_data: BoundedVec::default(),276 const_data: BoundedVec::default(),
277 variable_data: BoundedVec::default(),
278 properties: BoundedVec::default(),277 properties: BoundedVec::default(),
279 owner: to,278 owner: to,
280 },279 },
322 const_data: Vec::<u8>::from(token_uri)321 const_data: Vec::<u8>::from(token_uri)
323 .try_into()322 .try_into()
324 .map_err(|_| "token uri is too long")?,323 .map_err(|_| "token uri is too long")?,
325 variable_data: BoundedVec::default(),
326 properties: BoundedVec::default(),324 properties: BoundedVec::default(),
327 owner: to,325 owner: to,
328 },326 },
387 .into())385 .into())
388 }386 }
389
390 #[weight(<SelfWeightOf<T>>::set_variable_metadata(data.len() as u32))]
391 fn set_variable_metadata(
392 &mut self,
393 caller: caller,
394 token_id: uint256,
395 data: bytes,
396 ) -> Result<void> {
397 let caller = T::CrossAccountId::from_eth(caller);
398 let token = token_id.try_into()?;
399
400 <Pallet<T>>::set_variable_metadata(
401 self,
402 &caller,
403 token,
404 data.try_into()
405 .map_err(|_| "metadata size exceeded limit")?,
406 )
407 .map_err(dispatch_to_evm::<T>)?;
408 Ok(())
409 }
410
411 fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {
412 self.consume_store_reads(1)?;
413 let token: TokenId = token_id.try_into()?;
414
415 Ok(<TokenData<T>>::get((self.id, token))
416 .ok_or("token not found")?
417 .variable_data
418 .into_inner())
419 }
420387
421 #[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]388 #[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]
422 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {389 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
440 let data = (0..total_tokens)407 let data = (0..total_tokens)
441 .map(|_| CreateItemData::<T> {408 .map(|_| CreateItemData::<T> {
442 const_data: BoundedVec::default(),409 const_data: BoundedVec::default(),
443 variable_data: BoundedVec::default(),
444 properties: BoundedVec::default(),410 properties: BoundedVec::default(),
445 owner: to.clone(),411 owner: to.clone(),
446 })412 })
484 const_data: Vec::<u8>::from(token_uri)450 const_data: Vec::<u8>::from(token_uri)
485 .try_into()451 .try_into()
486 .map_err(|_| "token uri is too long")?,452 .map_err(|_| "token uri is too long")?,
487 variable_data: vec![].try_into().unwrap(),
488 properties: BoundedVec::default(),453 properties: BoundedVec::default(),
489 owner: to.clone(),454 owner: to.clone(),
490 });455 });
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
49pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::account::Config>::CrossAccountId>;49pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::account::Config>::CrossAccountId>;
50pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;50pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
5151
52#[struct_versioning::versioned(version = 2, upper)]
52#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]53#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]
53pub struct ItemData<CrossAccountId> {54pub struct ItemData<CrossAccountId> {
54 pub const_data: BoundedVec<u8, CustomDataLimit>,55 pub const_data: BoundedVec<u8, CustomDataLimit>,
56
57 #[version(..2)]
55 pub variable_data: BoundedVec<u8, CustomDataLimit>,58 pub variable_data: BoundedVec<u8, CustomDataLimit>,
59
56 pub owner: CrossAccountId,60 pub owner: CrossAccountId,
57}61}
5862
59#[frame_support::pallet]63#[frame_support::pallet]
60pub mod pallet {64pub mod pallet {
61 use super::*;65 use super::*;
62 use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};66 use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};
67 use frame_system::pallet_prelude::*;
63 use up_data_structs::{CollectionId, TokenId};68 use up_data_structs::{CollectionId, TokenId};
64 use super::weights::WeightInfo;69 use super::weights::WeightInfo;
6570
78 type WeightInfo: WeightInfo;83 type WeightInfo: WeightInfo;
79 }84 }
85
86 const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
8087
81 #[pallet::pallet]88 #[pallet::pallet]
89 #[pallet::storage_version(STORAGE_VERSION)]
82 #[pallet::generate_store(pub(super) trait Store)]90 #[pallet::generate_store(pub(super) trait Store)]
83 pub struct Pallet<T>(_);91 pub struct Pallet<T>(_);
8492
134 QueryKind = OptionQuery,142 QueryKind = OptionQuery,
135 >;143 >;
144
145 #[pallet::hooks]
146 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
147 fn on_runtime_upgrade() -> Weight {
148 if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {
149 <TokenData<T>>::translate_values::<ItemDataVersion1<T::CrossAccountId>, _>(|v| {
150 Some(<ItemDataVersion2<T::CrossAccountId>>::from(v))
151 })
152 }
153
154 0
155 }
156 }
136}157}
137158
138pub struct NonfungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);159pub struct NonfungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);
577 (collection.id, token),598 (collection.id, token),
578 ItemData {599 ItemData {
579 const_data: data.const_data,600 const_data: data.const_data,
580 variable_data: data.variable_data,
581 owner: data.owner.clone(),601 owner: data.owner.clone(),
582 },602 },
583 );603 );
775 Self::burn(collection, from, token)795 Self::burn(collection, from, token)
776 }796 }
777
778 pub fn set_variable_metadata(
779 collection: &NonfungibleHandle<T>,
780 sender: &T::CrossAccountId,
781 token: TokenId,
782 data: BoundedVec<u8, CustomDataLimit>,
783 ) -> DispatchResult {
784 let token_data =
785 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
786 collection.check_can_update_meta(sender, &token_data.owner)?;
787
788 // =========
789
790 <TokenData<T>>::insert(
791 (collection.id, token),
792 ItemData {
793 variable_data: data,
794 ..token_data
795 },
796 );
797 Ok(())
798 }
799797
800 pub fn check_nesting(798 pub fn check_nesting(
801 handle: &NonfungibleHandle<T>,799 handle: &NonfungibleHandle<T>,
modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
61 }61 }
62}62}
63
64// Selector: 56fd500b
65contract CollectionProperties is Dummy, ERC165 {
66 // Selector: setProperty(string,string) 62d9491f
67 function setProperty(string memory key, string memory value) public {
68 require(false, stub_error);
69 key;
70 value;
71 dummy = 0;
72 }
73
74 // Selector: deleteProperty(string) 34241914
75 function deleteProperty(string memory key) public {
76 require(false, stub_error);
77 key;
78 dummy = 0;
79 }
80}
6381
64// Selector: 5880016182// Selector: 58800161
65contract ERC721 is Dummy, ERC165, ERC721Events {83contract ERC721 is Dummy, ERC165, ERC721Events {
276 }294 }
277}295}
278296
279// Selector: e562194d297// Selector: d74d154f
280contract ERC721UniqueExtensions is Dummy, ERC165 {298contract ERC721UniqueExtensions is Dummy, ERC165 {
281 // Selector: transfer(address,uint256) a9059cbb299 // Selector: transfer(address,uint256) a9059cbb
282 function transfer(address to, uint256 tokenId) public {300 function transfer(address to, uint256 tokenId) public {
301 return 0;319 return 0;
302 }320 }
303
304 // Selector: setVariableMetadata(uint256,bytes) d4eac26d
305 function setVariableMetadata(uint256 tokenId, bytes memory data) public {
306 require(false, stub_error);
307 tokenId;
308 data;
309 dummy = 0;
310 }
311
312 // Selector: getVariableMetadata(uint256) e6c5ce6f
313 function getVariableMetadata(uint256 tokenId)
314 public
315 view
316 returns (bytes memory)
317 {
318 require(false, stub_error);
319 tokenId;
320 dummy;
321 return hex"";
322 }
323321
324 // Selector: mintBulk(address,uint256[]) 44a9945e322 // Selector: mintBulk(address,uint256[]) 44a9945e
325 function mintBulk(address to, uint256[] memory tokenIds)323 function mintBulk(address to, uint256[] memory tokenIds)
354 ERC721Enumerable,352 ERC721Enumerable,
355 ERC721UniqueExtensions,353 ERC721UniqueExtensions,
356 ERC721Mintable,354 ERC721Mintable,
357 ERC721Burnable355 ERC721Burnable,
356 CollectionProperties
358{}357{}
359358
modifiedpallets/nonfungible/src/weights.rsdiffbeforeafterboth
45 fn approve() -> Weight;45 fn approve() -> Weight;
46 fn transfer_from() -> Weight;46 fn transfer_from() -> Weight;
47 fn burn_from() -> Weight;47 fn burn_from() -> Weight;
48 fn set_variable_metadata(b: u32, ) -> Weight;
49}48}
5049
51/// Weights for pallet_nonfungible using the Substrate node and recommended hardware.50/// Weights for pallet_nonfungible using the Substrate node and recommended hardware.
156 .saturating_add(T::DbWeight::get().reads(4 as Weight))155 .saturating_add(T::DbWeight::get().reads(4 as Weight))
157 .saturating_add(T::DbWeight::get().writes(5 as Weight))156 .saturating_add(T::DbWeight::get().writes(5 as Weight))
158 }157 }
159 // Storage: Nonfungible TokenData (r:1 w:1)
160 fn set_variable_metadata(_b: u32, ) -> Weight {
161 (7_700_000 as Weight)
162 .saturating_add(T::DbWeight::get().reads(1 as Weight))
163 .saturating_add(T::DbWeight::get().writes(1 as Weight))
164 }
165}158}
166159
167// For backwards compatibility and tests160// For backwards compatibility and tests
271 .saturating_add(RocksDbWeight::get().reads(4 as Weight))264 .saturating_add(RocksDbWeight::get().reads(4 as Weight))
272 .saturating_add(RocksDbWeight::get().writes(5 as Weight))265 .saturating_add(RocksDbWeight::get().writes(5 as Weight))
273 }266 }
274 // Storage: Nonfungible TokenData (r:1 w:1)
275 fn set_variable_metadata(_b: u32, ) -> Weight {
276 (7_700_000 as Weight)
277 .saturating_add(RocksDbWeight::get().reads(1 as Weight))
278 .saturating_add(RocksDbWeight::get().writes(1 as Weight))
279 }
280}267}
281268
modifiedpallets/refungible/Cargo.tomldiffbeforeafterboth
24scale-info = { version = "2.0.1", default-features = false, features = [24scale-info = { version = "2.0.1", default-features = false, features = [
25 "derive",25 "derive",
26] }26] }
27struct-versioning = { path = "../../crates/struct-versioning" }
2728
28[features]29[features]
29default = ["std"]30default = ["std"]
modifiedpallets/refungible/src/benchmarking.rsdiffbeforeafterboth
31 users: impl IntoIterator<Item = (CrossAccountId, u128)>,31 users: impl IntoIterator<Item = (CrossAccountId, u128)>,
32) -> CreateRefungibleExData<CrossAccountId> {32) -> CreateRefungibleExData<CrossAccountId> {
33 let const_data = create_data::<CUSTOM_DATA_LIMIT>();33 let const_data = create_data::<CUSTOM_DATA_LIMIT>();
34 let variable_data = create_data::<CUSTOM_DATA_LIMIT>();
35 CreateRefungibleExData {34 CreateRefungibleExData {
36 const_data,35 const_data,
37 variable_data,
38 users: users36 users: users
39 .into_iter()37 .into_iter()
40 .collect::<BTreeMap<_, _>>()38 .collect::<BTreeMap<_, _>>()
204 <Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;202 <Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;
205 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200, &Unlimited)?}203 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200, &Unlimited)?}
206
207 set_variable_metadata {
208 let b in 0..CUSTOM_DATA_LIMIT;
209 bench_init!{
210 owner: sub; collection: collection(owner);
211 sender: cross_from_sub(owner);
212 };
213 let item = create_max_item(&collection, &sender, [(sender.clone(), 200)])?;
214 let data = create_var_data(b).try_into().unwrap();
215 }: {<Pallet<T>>::set_variable_metadata(&collection, &sender, item, data)?}
216}204}
217205
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
17use core::marker::PhantomData;17use core::marker::PhantomData;
1818
19use sp_std::collections::btree_map::BTreeMap;19use sp_std::collections::btree_map::BTreeMap;
20use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight, BoundedVec};20use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight};
21use up_data_structs::{21use up_data_structs::{
22 CollectionId, TokenId, CustomDataLimit, CreateItemExData, CreateRefungibleExData,22 CollectionId, TokenId, CreateItemExData, CreateRefungibleExData,
23 budget::Budget, Property, PropertyKey, PropertyKeyPermission,23 budget::Budget, Property, PropertyKey, PropertyKeyPermission,
24};24};
25use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};25use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
112 <SelfWeightOf<T>>::burn_from()112 <SelfWeightOf<T>>::burn_from()
113 }113 }
114
115 fn set_variable_metadata(bytes: u32) -> Weight {
116 <SelfWeightOf<T>>::set_variable_metadata(bytes)
117 }
118}114}
119115
120fn map_create_data<T: Config>(116fn map_create_data<T: Config>(
124 match data {120 match data {
125 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateRefungibleExData {121 up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateRefungibleExData {
126 const_data: data.const_data,122 const_data: data.const_data,
127 variable_data: data.variable_data,
128 users: {123 users: {
129 let mut out = BTreeMap::new();124 let mut out = BTreeMap::new();
130 out.insert(to.clone(), data.pieces);125 out.insert(to.clone(), data.pieces);
306 fail!(<Error<T>>::SettingPropertiesNotAllowed)301 fail!(<Error<T>>::SettingPropertiesNotAllowed)
307 }302 }
308
309 fn set_variable_metadata(
310 &self,
311 sender: T::CrossAccountId,
312 token: TokenId,
313 data: BoundedVec<u8, CustomDataLimit>,
314 ) -> DispatchResultWithPostInfo {
315 let len = data.len();
316 with_weight(
317 <Pallet<T>>::set_variable_metadata(self, &sender, token, data),
318 <CommonWeights<T>>::set_variable_metadata(len as u32),
319 )
320 }
321303
322 fn check_nesting(304 fn check_nesting(
323 &self,305 &self,
357 .const_data339 .const_data
358 .into_inner()340 .into_inner()
359 }341 }
360 fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
361 <TokenData<T>>::get((self.id, token))
362 .variable_data
363 .into_inner()
364 }
365342
366 fn token_properties(&self, _token_id: TokenId, _keys: Vec<PropertyKey>) -> Vec<Property> {343 fn token_properties(&self, _token_id: TokenId, _keys: Vec<PropertyKey>) -> Vec<Property> {
367 Vec::new()344 Vec::new()
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
41pub mod weights;41pub mod weights;
42pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;42pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
4343
44#[struct_versioning::versioned(version = 2, upper)]
44#[derive(Encode, Decode, Default, TypeInfo, MaxEncodedLen)]45#[derive(Encode, Decode, Default, TypeInfo, MaxEncodedLen)]
45pub struct ItemData {46pub struct ItemData {
46 pub const_data: BoundedVec<u8, CustomDataLimit>,47 pub const_data: BoundedVec<u8, CustomDataLimit>,
48
49 #[version(..2)]
47 pub variable_data: BoundedVec<u8, CustomDataLimit>,50 pub variable_data: BoundedVec<u8, CustomDataLimit>,
48}51}
4952
50#[frame_support::pallet]53#[frame_support::pallet]
51pub mod pallet {54pub mod pallet {
52 use super::*;55 use super::*;
53 use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};56 use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};
57 use frame_system::pallet_prelude::*;
54 use up_data_structs::{CollectionId, TokenId};58 use up_data_structs::{CollectionId, TokenId};
55 use super::weights::WeightInfo;59 use super::weights::WeightInfo;
5660
73 type WeightInfo: WeightInfo;77 type WeightInfo: WeightInfo;
74 }78 }
79
80 const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
7581
76 #[pallet::pallet]82 #[pallet::pallet]
83 #[pallet::storage_version(STORAGE_VERSION)]
77 #[pallet::generate_store(pub(super) trait Store)]84 #[pallet::generate_store(pub(super) trait Store)]
78 pub struct Pallet<T>(_);85 pub struct Pallet<T>(_);
7986
147 QueryKind = ValueQuery,154 QueryKind = ValueQuery,
148 >;155 >;
156
157 #[pallet::hooks]
158 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
159 fn on_runtime_upgrade() -> Weight {
160 if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {
161 <TokenData<T>>::translate_values::<ItemDataVersion1, _>(|v| {
162 Some(<ItemDataVersion2>::from(v))
163 })
164 }
165
166 0
167 }
168 }
149}169}
150170
151pub struct RefungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);171pub struct RefungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);
494 (collection.id, token_id),514 (collection.id, token_id),
495 ItemData {515 ItemData {
496 const_data: token.const_data,516 const_data: token.const_data,
497 variable_data: token.variable_data,
498 },517 },
499 );518 );
500 for (user, amount) in token.users.into_iter() {519 for (user, amount) in token.users.into_iter() {
646 Ok(())665 Ok(())
647 }666 }
648
649 pub fn set_variable_metadata(
650 collection: &RefungibleHandle<T>,
651 sender: &T::CrossAccountId,
652 token: TokenId,
653 data: BoundedVec<u8, CustomDataLimit>,
654 ) -> DispatchResult {
655 collection.check_can_update_meta(
656 sender,
657 &T::CrossAccountId::from_sub(collection.owner.clone()),
658 )?;
659
660 let token_data = <TokenData<T>>::get((collection.id, token));
661
662 // =========
663
664 <TokenData<T>>::insert(
665 (collection.id, token),
666 ItemData {
667 variable_data: data,
668 ..token_data
669 },
670 );
671 Ok(())
672 }
673667
674 /// Delegated to `create_multiple_items`668 /// Delegated to `create_multiple_items`
675 pub fn create_item(669 pub fn create_item(
modifiedpallets/refungible/src/weights.rsdiffbeforeafterboth
53 fn transfer_from_removing() -> Weight;53 fn transfer_from_removing() -> Weight;
54 fn transfer_from_creating_removing() -> Weight;54 fn transfer_from_creating_removing() -> Weight;
55 fn burn_from() -> Weight;55 fn burn_from() -> Weight;
56 fn set_variable_metadata(b: u32, ) -> Weight;
57}56}
5857
59/// Weights for pallet_refungible using the Substrate node and recommended hardware.58/// Weights for pallet_refungible using the Substrate node and recommended hardware.
243 .saturating_add(T::DbWeight::get().reads(5 as Weight))242 .saturating_add(T::DbWeight::get().reads(5 as Weight))
244 .saturating_add(T::DbWeight::get().writes(7 as Weight))243 .saturating_add(T::DbWeight::get().writes(7 as Weight))
245 }244 }
246 // Storage: Refungible TokenData (r:1 w:1)
247 fn set_variable_metadata(_b: u32, ) -> Weight {
248 (7_364_000 as Weight)
249 .saturating_add(T::DbWeight::get().reads(1 as Weight))
250 .saturating_add(T::DbWeight::get().writes(1 as Weight))
251 }
252}245}
253246
254// For backwards compatibility and tests247// For backwards compatibility and tests
437 .saturating_add(RocksDbWeight::get().reads(5 as Weight))430 .saturating_add(RocksDbWeight::get().reads(5 as Weight))
438 .saturating_add(RocksDbWeight::get().writes(7 as Weight))431 .saturating_add(RocksDbWeight::get().writes(7 as Weight))
439 }432 }
440 // Storage: Refungible TokenData (r:1 w:1)
441 fn set_variable_metadata(_b: u32, ) -> Weight {
442 (7_364_000 as Weight)
443 .saturating_add(RocksDbWeight::get().reads(1 as Weight))
444 .saturating_add(RocksDbWeight::get().writes(1 as Weight))
445 }
446}433}
447434
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
38 CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,38 CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,
39 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,39 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,
40 AccessMode, CreateItemData, CollectionLimits, CollectionId, CollectionMode, TokenId,40 AccessMode, CreateItemData, CollectionLimits, CollectionId, CollectionMode, TokenId,
41 SchemaVersion, SponsorshipState, MetaUpdatePermission, CreateCollectionData, CustomDataLimit,41 SchemaVersion, SponsorshipState, MetaUpdatePermission, CreateCollectionData,
42 CreateItemExData, budget, CollectionField, Property, PropertyKey, PropertyKeyPermission,42 CreateItemExData, budget, CollectionField, Property, PropertyKey, PropertyKeyPermission,
43};43};
44use pallet_evm::account::CrossAccountId;44use pallet_evm::account::CrossAccountId;
238 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;238 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
239 //#endregion239 //#endregion
240240
241 /// Variable metadata sponsoring
242 /// Collection id (controlled?2), token id (controlled?2)
243 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
244 /// Approval sponsoring241 /// Approval sponsoring
245 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;242 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
246 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;243 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
333 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);330 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);
334 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);331 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);
335332
336 <VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);
337 <NftApproveBasket<T>>::remove_prefix(collection_id, None);333 <NftApproveBasket<T>>::remove_prefix(collection_id, None);
338 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);334 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);
339 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);335 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);
931 dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))927 dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))
932 }928 }
933
934 /// Set off-chain data schema.
935 ///
936 /// # Permissions
937 ///
938 /// * Collection Owner
939 /// * Collection Admin
940 ///
941 /// # Arguments
942 ///
943 /// * collection_id.
944 ///
945 /// * schema: String representing the offchain data schema.
946 #[weight = T::CommonWeightInfo::set_variable_metadata(data.len() as u32)]
947 #[transactional]
948 pub fn set_variable_meta_data (
949 origin,
950 collection_id: CollectionId,
951 item_id: TokenId,
952 data: BoundedVec<u8, CustomDataLimit>,
953 ) -> DispatchResultWithPostInfo {
954 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
955
956 dispatch_call::<T, _>(collection_id, |d| d.set_variable_metadata(sender, item_id, data))
957 }
958929
959 /// Set meta_update_permission value for particular collection930 /// Set meta_update_permission value for particular collection
960 ///931 ///
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
364pub type CollectionPropertiesVec =364pub type CollectionPropertiesVec =
365 BoundedVec<Property, ConstU32<MAX_COLLECTION_PROPERTIES_ENCODE_LEN>>;365 BoundedVec<Property, ConstU32<MAX_COLLECTION_PROPERTIES_ENCODE_LEN>>;
366
367#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
368#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
369pub struct NftItemType<AccountId> {
370 pub owner: AccountId,
371 pub const_data: Vec<u8>,
372 pub variable_data: Vec<u8>,
373}
374
375#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]
376#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
377pub struct FungibleItemType {
378 pub value: u128,
379}
380
381#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]
382#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
383pub struct ReFungibleItemType<AccountId> {
384 pub owner: Vec<Ownership<AccountId>>,
385 pub const_data: Vec<u8>,
386 pub variable_data: Vec<u8>,
387}
388366
389/// All fields are wrapped in `Option`s, where None means chain default367/// All fields are wrapped in `Option`s, where None means chain default
390#[struct_versioning::versioned(version = 2, upper)]368#[struct_versioning::versioned(version = 2, upper)]
394 pub account_token_ownership_limit: Option<u32>,372 pub account_token_ownership_limit: Option<u32>,
395 pub sponsored_data_size: Option<u32>,373 pub sponsored_data_size: Option<u32>,
374
375 /// FIXME should we delete this or repurpose it?
396 /// None - setVariableMetadata is not sponsored376 /// None - setVariableMetadata is not sponsored
397 /// Some(v) - setVariableMetadata is sponsored377 /// Some(v) - setVariableMetadata is sponsored
398 /// if there is v block between txs378 /// if there is v block between txs
490 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]470 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
491 #[derivative(Debug(format_with = "bounded::vec_debug"))]471 #[derivative(Debug(format_with = "bounded::vec_debug"))]
492 pub const_data: BoundedVec<u8, CustomDataLimit>,472 pub const_data: BoundedVec<u8, CustomDataLimit>,
493 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
494 #[derivative(Debug(format_with = "bounded::vec_debug"))]
495 pub variable_data: BoundedVec<u8, CustomDataLimit>,
496473
497 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]474 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
498 #[derivative(Debug(format_with = "bounded::vec_debug"))]475 #[derivative(Debug(format_with = "bounded::vec_debug"))]
512 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]489 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
513 #[derivative(Debug(format_with = "bounded::vec_debug"))]490 #[derivative(Debug(format_with = "bounded::vec_debug"))]
514 pub const_data: BoundedVec<u8, CustomDataLimit>,491 pub const_data: BoundedVec<u8, CustomDataLimit>,
515 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
516 #[derivative(Debug(format_with = "bounded::vec_debug"))]
517 pub variable_data: BoundedVec<u8, CustomDataLimit>,
518 pub pieces: u128,492 pub pieces: u128,
519}493}
520494
545pub struct CreateNftExData<CrossAccountId> {519pub struct CreateNftExData<CrossAccountId> {
546 #[derivative(Debug(format_with = "bounded::vec_debug"))]520 #[derivative(Debug(format_with = "bounded::vec_debug"))]
547 pub const_data: BoundedVec<u8, CustomDataLimit>,521 pub const_data: BoundedVec<u8, CustomDataLimit>,
548 #[derivative(Debug(format_with = "bounded::vec_debug"))]
549 pub variable_data: BoundedVec<u8, CustomDataLimit>,
550 #[derivative(Debug(format_with = "bounded::vec_debug"))]522 #[derivative(Debug(format_with = "bounded::vec_debug"))]
551 pub properties: CollectionPropertiesVec,523 pub properties: CollectionPropertiesVec,
552 pub owner: CrossAccountId,524 pub owner: CrossAccountId,
557pub struct CreateRefungibleExData<CrossAccountId> {529pub struct CreateRefungibleExData<CrossAccountId> {
558 #[derivative(Debug(format_with = "bounded::vec_debug"))]530 #[derivative(Debug(format_with = "bounded::vec_debug"))]
559 pub const_data: BoundedVec<u8, CustomDataLimit>,531 pub const_data: BoundedVec<u8, CustomDataLimit>,
560 #[derivative(Debug(format_with = "bounded::vec_debug"))]
561 pub variable_data: BoundedVec<u8, CustomDataLimit>,
562 #[derivative(Debug(format_with = "bounded::map_debug"))]532 #[derivative(Debug(format_with = "bounded::map_debug"))]
563 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,533 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
564}534}
586impl CreateItemData {556impl CreateItemData {
587 pub fn data_size(&self) -> usize {557 pub fn data_size(&self) -> usize {
588 match self {558 match self {
589 CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),559 CreateItemData::NFT(data) => data.const_data.len(),
590 CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),560 CreateItemData::ReFungible(data) => data.const_data.len(),
591 _ => 0,561 _ => 0,
592 }562 }
593 }563 }
modifiedprimitives/rpc/src/lib.rsdiffbeforeafterboth
42 fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>>;42 fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>>;
43 fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>>;43 fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>>;
44 fn const_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>>;44 fn const_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>>;
45 fn variable_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>>;
4645
47 fn collection_properties(collection: CollectionId, properties: Vec<Vec<u8>>) -> Result<Vec<Property>>;46 fn collection_properties(collection: CollectionId, properties: Vec<Vec<u8>>) -> Result<Vec<Property>>;
4847
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
32 fn const_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>, DispatchError> {32 fn const_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>, DispatchError> {
33 dispatch_unique_runtime!(collection.const_metadata(token))33 dispatch_unique_runtime!(collection.const_metadata(token))
34 }34 }
35 fn variable_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>, DispatchError> {
36 dispatch_unique_runtime!(collection.variable_metadata(token))
37 }
3835
39 fn collection_properties(36 fn collection_properties(
40 collection: CollectionId,37 collection: CollectionId,
modifiedruntime/common/src/sponsoring.rsdiffbeforeafterboth
21 storage::{StorageMap, StorageDoubleMap, StorageNMap},21 storage::{StorageMap, StorageDoubleMap, StorageNMap},
22};22};
23use up_data_structs::{23use up_data_structs::{
24 CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,24 CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
25 NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode,25 NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode,
26 CreateItemData,26 CreateItemData,
27};27};
30use pallet_evm::account::CrossAccountId;30use pallet_evm::account::CrossAccountId;
31use pallet_unique::{31use pallet_unique::{
32 Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,32 Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,
33 NftApproveBasket, VariableMetaDataBasket, CreateItemBasket, ReFungibleTransferBasket,33 NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket,
34 FungibleTransferBasket, NftTransferBasket,34 FungibleTransferBasket, NftTransferBasket,
35};35};
36use pallet_fungible::Config as FungibleConfig;36use pallet_fungible::Config as FungibleConfig;
140 Some(())140 Some(())
141}141}
142
143pub fn withdraw_set_variable_meta_data<T: Config>(
144 who: &T::CrossAccountId,
145 collection: &CollectionHandle<T>,
146 item_id: &TokenId,
147 data: &[u8],
148) -> Option<()> {
149 // TODO: make it work for admins
150 if collection.meta_update_permission != MetaUpdatePermission::ItemOwner {
151 return None;
152 }
153 // preliminary sponsoring correctness check
154 match collection.mode {
155 CollectionMode::NFT => {
156 let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
157 if !owner.conv_eq(who) {
158 return None;
159 }
160 }
161 CollectionMode::Fungible(_) => {
162 if item_id != &TokenId::default() {
163 return None;
164 }
165 if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
166 return None;
167 }
168 }
169 CollectionMode::ReFungible => {
170 if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
171 return None;
172 }
173 }
174 }
175
176 // Can't sponsor fungible collection, this tx will be rejected
177 // as invalid
178 if matches!(collection.mode, CollectionMode::Fungible(_)) {
179 return None;
180 }
181 if data.len() > collection.limits.sponsored_data_size() as usize {
182 return None;
183 }
184
185 let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
186 let limit = collection.limits.sponsored_data_rate_limit()?;
187
188 if let Some(last_tx_block) = VariableMetaDataBasket::<T>::get(collection.id, item_id) {
189 let timeout = last_tx_block + limit.into();
190 if block_number < timeout {
191 return None;
192 }
193 }
194
195 <VariableMetaDataBasket<T>>::insert(collection.id, item_id, block_number);
196
197 Some(())
198}
199142
200pub fn withdraw_approve<T: Config>(143pub fn withdraw_approve<T: Config>(
201 collection: &CollectionHandle<T>,144 collection: &CollectionHandle<T>,
291 let (sponsor, collection) = load(*collection_id)?;234 let (sponsor, collection) = load(*collection_id)?;
292 withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)235 withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)
293 }236 }
294 UniqueCall::set_variable_meta_data {
295 collection_id,
296 item_id,
297 data,
298 } => {
299 let (sponsor, collection) = load(*collection_id)?;
300 withdraw_set_variable_meta_data::<T>(
301 &T::CrossAccountId::from_sub(who.clone()),
302 &collection,
303 item_id,
304 data,
305 )
306 .map(|()| sponsor)
307 }
308 _ => None,237 _ => None,
309 }238 }
310 }239 }
modifiedruntime/common/src/weights.rsdiffbeforeafterboth
86 dispatch_weight::<T>() + max_weight_of!(transfer_from())86 dispatch_weight::<T>() + max_weight_of!(transfer_from())
87 }87 }
88
89 fn set_variable_metadata(bytes: u32) -> Weight {
90 dispatch_weight::<T>() + max_weight_of!(set_variable_metadata(bytes))
91 }
9288
93 fn burn_from() -> Weight {89 fn burn_from() -> Weight {
94 dispatch_weight::<T>() + max_weight_of!(burn_from())90 dispatch_weight::<T>() + max_weight_of!(burn_from())
modifiedruntime/tests/src/tests.rsdiffbeforeafterboth
47fn default_nft_data() -> CreateNftData {47fn default_nft_data() -> CreateNftData {
48 CreateNftData {48 CreateNftData {
49 const_data: vec![1, 2, 3].try_into().unwrap(),49 const_data: vec![1, 2, 3].try_into().unwrap(),
50 variable_data: vec![3, 2, 1].try_into().unwrap(),
51 }50 }
52}51}
5352
58fn default_re_fungible_data() -> CreateReFungibleData {57fn default_re_fungible_data() -> CreateReFungibleData {
59 CreateReFungibleData {58 CreateReFungibleData {
60 const_data: vec![1, 2, 3].try_into().unwrap(),59 const_data: vec![1, 2, 3].try_into().unwrap(),
61 variable_data: vec![3, 2, 1].try_into().unwrap(),
62 pieces: 1023,60 pieces: 1023,
63 }61 }
64}62}
215213
216 let item = <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1)).unwrap();214 let item = <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1)).unwrap();
217 assert_eq!(item.const_data, data.const_data.into_inner());215 assert_eq!(item.const_data, data.const_data.into_inner());
218 assert_eq!(item.variable_data, data.variable_data.into_inner());
219 });216 });
220}217}
221218
247 ))244 ))
248 .unwrap();245 .unwrap();
249 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());246 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
250 assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
251 }247 }
252 });248 });
253}249}
263 let balance =259 let balance =
264 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));260 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));
265 assert_eq!(item.const_data, data.const_data.into_inner());261 assert_eq!(item.const_data, data.const_data.into_inner());
266 assert_eq!(item.variable_data, data.variable_data.into_inner());
267 assert_eq!(balance, 1023);262 assert_eq!(balance, 1023);
268 });263 });
269}264}
299 let balance =294 let balance =
300 <pallet_refungible::Balance<Test>>::get((CollectionId(1), TokenId(1), account(1)));295 <pallet_refungible::Balance<Test>>::get((CollectionId(1), TokenId(1), account(1)));
301 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());296 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
302 assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
303 assert_eq!(balance, 1023);297 assert_eq!(balance, 1023);
304 }298 }
305 });299 });
413 create_test_item(collection_id, &data.clone().into());407 create_test_item(collection_id, &data.clone().into());
414 let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));408 let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));
415 assert_eq!(item.const_data, data.const_data.into_inner());409 assert_eq!(item.const_data, data.const_data.into_inner());
416 assert_eq!(item.variable_data, data.variable_data.into_inner());
417 assert_eq!(410 assert_eq!(
418 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),411 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),
419 1412 1
2426 });2419 });
2427}2420}
2428
2429#[test]
2430fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {
2431 new_test_ext().execute_with(|| {
2432 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
2433
2434 let origin1 = Origin::signed(1);
2435
2436 let data = default_nft_data();
2437 create_test_item(CollectionId(1), &data.into());
2438
2439 let variable_data = b"test data".to_vec();
2440 assert_ok!(Unique::set_variable_meta_data(
2441 origin1,
2442 collection_id,
2443 TokenId(1),
2444 variable_data.clone().try_into().unwrap()
2445 ));
2446
2447 assert_eq!(
2448 <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))
2449 .unwrap()
2450 .variable_data,
2451 variable_data
2452 );
2453 });
2454}
2455
2456#[test]
2457fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {
2458 new_test_ext().execute_with(|| {
2459 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
2460
2461 let origin1 = Origin::signed(1);
2462
2463 let data = default_re_fungible_data();
2464 create_test_item(collection_id, &data.into());
2465
2466 let variable_data = b"test data".to_vec();
2467 assert_ok!(Unique::set_variable_meta_data(
2468 origin1,
2469 collection_id,
2470 TokenId(1),
2471 variable_data.clone().try_into().unwrap()
2472 ));
2473
2474 assert_eq!(
2475 <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1))).variable_data,
2476 variable_data
2477 );
2478 });
2479}
2480
2481#[test]
2482fn set_variable_meta_data_on_fungible_token_fails() {
2483 new_test_ext().execute_with(|| {
2484 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
2485
2486 let origin1 = Origin::signed(1);
2487
2488 let data = default_fungible_data();
2489 create_test_item(collection_id, &data.into());
2490
2491 let variable_data = b"test data".to_vec();
2492 assert_noop!(
2493 Unique::set_variable_meta_data(
2494 origin1,
2495 collection_id,
2496 TokenId(0),
2497 variable_data.try_into().unwrap()
2498 )
2499 .map_err(|e| e.error),
2500 <pallet_fungible::Error<Test>>::FungibleItemsDontHaveData
2501 );
2502 });
2503}
2504
2505#[test]
2506fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {
2507 new_test_ext().execute_with(|| {
2508 //default_limits();
2509
2510 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
2511
2512 let origin1 = Origin::signed(1);
2513
2514 let data = default_nft_data();
2515 create_test_item(collection_id, &data.into());
2516
2517 assert_ok!(Unique::set_meta_update_permission_flag(
2518 origin1.clone(),
2519 collection_id,
2520 MetaUpdatePermission::ItemOwner,
2521 ));
2522
2523 let variable_data = b"ten chars.".to_vec();
2524 assert_ok!(Unique::set_variable_meta_data(
2525 origin1,
2526 collection_id,
2527 TokenId(1),
2528 variable_data.clone().try_into().unwrap()
2529 ));
2530
2531 assert_eq!(
2532 <pallet_nonfungible::TokenData<Test>>::get((collection_id, TokenId(1)))
2533 .unwrap()
2534 .variable_data,
2535 variable_data
2536 );
2537 });
2538}
25392421
2540#[test]2422#[test]
2541fn collection_transfer_flag_works() {2423fn collection_transfer_flag_works() {
2589 });2471 });
2590}2472}
2591
2592#[test]
2593fn set_variable_meta_data_on_nft_with_admin_flag() {
2594 new_test_ext().execute_with(|| {
2595 // default_limits();
2596
2597 let collection_id =
2598 create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));
2599
2600 let origin1 = Origin::signed(1);
2601 let origin2 = Origin::signed(2);
2602
2603 assert_ok!(Unique::set_mint_permission(
2604 origin2.clone(),
2605 collection_id,
2606 true
2607 ));
2608 assert_ok!(Unique::add_to_allow_list(
2609 origin2.clone(),
2610 collection_id,
2611 account(1)
2612 ));
2613
2614 assert_ok!(Unique::add_collection_admin(
2615 origin2.clone(),
2616 collection_id,
2617 account(1)
2618 ));
2619
2620 let data = default_nft_data();
2621 create_test_item(collection_id, &data.into());
2622
2623 assert_ok!(Unique::set_meta_update_permission_flag(
2624 origin2.clone(),
2625 collection_id,
2626 MetaUpdatePermission::Admin,
2627 ));
2628
2629 let variable_data = b"test.".to_vec();
2630 assert_ok!(Unique::set_variable_meta_data(
2631 origin1,
2632 collection_id,
2633 TokenId(1),
2634 variable_data.clone().try_into().unwrap()
2635 ));
2636
2637 assert_eq!(
2638 <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))
2639 .unwrap()
2640 .variable_data,
2641 variable_data
2642 );
2643 });
2644}
2645
2646#[test]
2647fn set_variable_meta_data_on_nft_with_admin_flag_neg() {
2648 new_test_ext().execute_with(|| {
2649 // default_limits();
2650
2651 let collection_id =
2652 create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));
2653
2654 let origin1 = Origin::signed(1);
2655 let origin2 = Origin::signed(2);
2656
2657 assert_ok!(Unique::set_mint_permission(
2658 origin2.clone(),
2659 collection_id,
2660 true
2661 ));
2662 assert_ok!(Unique::add_to_allow_list(
2663 origin2.clone(),
2664 collection_id,
2665 account(1)
2666 ));
2667
2668 let data = default_nft_data();
2669 create_test_item(collection_id, &data.into());
2670
2671 assert_ok!(Unique::set_meta_update_permission_flag(
2672 origin2.clone(),
2673 collection_id,
2674 MetaUpdatePermission::Admin,
2675 ));
2676
2677 let variable_data = b"test.".to_vec();
2678 assert_noop!(
2679 Unique::set_variable_meta_data(
2680 origin1,
2681 collection_id,
2682 TokenId(1),
2683 variable_data.try_into().unwrap()
2684 )
2685 .map_err(|e| e.error),
2686 CommonError::<Test>::NoPermission
2687 );
2688 });
2689}
26902473
2691#[test]2474#[test]
2692fn set_variable_meta_flag_after_freeze() {2475fn set_variable_meta_flag_after_freeze() {
2714 });2497 });
2715}2498}
2716
2717#[test]
2718fn set_variable_meta_data_on_nft_with_none_flag_neg() {
2719 new_test_ext().execute_with(|| {
2720 // default_limits();
2721
2722 let collection_id =
2723 create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));
2724 let origin1 = Origin::signed(1);
2725
2726 let data = default_nft_data();
2727 create_test_item(collection_id, &data.into());
2728
2729 assert_ok!(Unique::set_meta_update_permission_flag(
2730 origin1.clone(),
2731 collection_id,
2732 MetaUpdatePermission::None,
2733 ));
2734
2735 let variable_data = b"test.".to_vec();
2736 assert_noop!(
2737 Unique::set_variable_meta_data(
2738 origin1.clone(),
2739 collection_id,
2740 TokenId(1),
2741 variable_data.try_into().unwrap()
2742 )
2743 .map_err(|e| e.error),
2744 CommonError::<Test>::NoPermission
2745 );
2746 });
2747}
27482499
2749#[test]2500#[test]
2750fn collection_transfer_flag_works_neg() {2501fn collection_transfer_flag_works_neg() {
modifiedsmart_contracs/transfer/lib.rsdiffbeforeafterboth
58pub enum CreateItemData {58pub enum CreateItemData {
59 Nft {59 Nft {
60 const_data: Vec<u8>,60 const_data: Vec<u8>,
61 variable_data: Vec<u8>,
62 },61 },
63 Fungible {62 Fungible {
64 value: u128,63 value: u128,
65 },64 },
66 ReFungible {65 ReFungible {
67 const_data: Vec<u8>,66 const_data: Vec<u8>,
68 variable_data: Vec<u8>,
69 pieces: u128,67 pieces: u128,
70 },68 },
71}69}
88 fn approve(spender: DefaultAccountId, collection_id: u32, item_id: u32, amount: u128);86 fn approve(spender: DefaultAccountId, collection_id: u32, item_id: u32, amount: u128);
89 #[ink(extension = 4, returns_result = false)]87 #[ink(extension = 4, returns_result = false)]
90 fn transfer_from(owner: DefaultAccountId, recipient: DefaultAccountId, collection_id: u32, item_id: u32, amount: u128);88 fn transfer_from(owner: DefaultAccountId, recipient: DefaultAccountId, collection_id: u32, item_id: u32, amount: u128);
91 #[ink(extension = 5, returns_result = false)]
92 fn set_variable_meta_data(collection_id: u32, item_id: u32, data: Vec<u8>);
93 #[ink(extension = 6, returns_result = false)]89 #[ink(extension = 6, returns_result = false)]
94 fn toggle_allow_list(collection_id: u32, address: DefaultAccountId, allowlisted: bool);90 fn toggle_allow_list(collection_id: u32, address: DefaultAccountId, allowlisted: bool);
95}91}
144 .extension()140 .extension()
145 .transfer_from(owner, recipient, collection_id, item_id, amount);141 .transfer_from(owner, recipient, collection_id, item_id, amount);
146 }142 }
147 #[ink(message)]
148 pub fn set_variable_meta_data(&mut self, collection_id: u32, item_id: u32, data: Vec<u8>) {
149 let _ = self.env()
150 .extension()
151 .set_variable_meta_data(collection_id, item_id, data);
152 }
153 #[ink(message)]143 #[ink(message)]
154 pub fn toggle_allow_list(&mut self, collection_id: u32, address: AccountId, allowlisted: bool) {144 pub fn toggle_allow_list(&mut self, collection_id: u32, address: AccountId, allowlisted: bool) {
155 let _ = self.env()145 let _ = self.env()