difftreelog
refactor Remove variable data from tokens
in: master
23 files changed
client/rpc/src/lib.rsdiffbeforeafterboth--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -71,13 +71,6 @@
token: TokenId,
at: Option<BlockHash>,
) -> Result<Vec<u8>>;
- #[rpc(name = "unique_variableMetadata")]
- fn variable_metadata(
- &self,
- collection: CollectionId,
- token: TokenId,
- at: Option<BlockHash>,
- ) -> Result<Vec<u8>>;
#[rpc(name = "unique_collectionProperties")]
fn collection_properties(
@@ -279,7 +272,6 @@
);
pass_method!(topmost_token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>);
pass_method!(const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);
- pass_method!(variable_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);
pass_method!(collection_properties(
collection: CollectionId,
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -33,7 +33,7 @@
MAX_TOKEN_PREFIX_LENGTH, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, TokenId,
CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode, NFT_SPONSOR_TRANSFER_TIMEOUT,
FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT,
- CUSTOM_DATA_LIMIT, CollectionLimits, CustomDataLimit, CreateCollectionData, SponsorshipState,
+ CUSTOM_DATA_LIMIT, CollectionLimits, CreateCollectionData, SponsorshipState,
CreateItemExData, SponsoringRateLimit, budget::Budget, COLLECTION_FIELD_LIMIT, CollectionField,
PhantomType, Property, Properties, PropertiesPermissionMap, PropertyKey, PropertyPermission,
PropertiesError, PropertyKeyPermission, TokenData, TrySet,
@@ -312,8 +312,6 @@
CollectionTokenPrefixLimitExceeded,
/// Total collections bound exceeded.
TotalCollectionsLimitExceeded,
- /// variable_data exceeded data limit.
- TokenVariableDataLimitExceeded,
/// Exceeded max admin count
CollectionAdminCountExceeded,
/// Collection limit bounds per collection exceeded
@@ -1073,7 +1071,6 @@
fn approve() -> Weight;
fn transfer_from() -> Weight;
fn burn_from() -> Weight;
- fn set_variable_metadata(bytes: u32) -> Weight;
}
pub trait CommonCollectionOperations<T: Config> {
@@ -1163,13 +1160,6 @@
nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo;
- fn set_variable_metadata(
- &self,
- sender: T::CrossAccountId,
- token: TokenId,
- data: BoundedVec<u8, CustomDataLimit>,
- ) -> DispatchResultWithPostInfo;
-
fn check_nesting(
&self,
sender: T::CrossAccountId,
@@ -1185,7 +1175,6 @@
fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;
fn const_metadata(&self, token: TokenId) -> Vec<u8>;
- fn variable_metadata(&self, token: TokenId) -> Vec<u8>;
fn token_properties(&self, token_id: TokenId, keys: Vec<PropertyKey>) -> Vec<Property>;
/// Amount of unique collection tokens
fn total_supply(&self) -> u32;
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -16,12 +16,12 @@
use core::marker::PhantomData;
-use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};
+use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
use up_data_structs::{TokenId, CollectionId, CreateItemExData, budget::Budget};
use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
use sp_runtime::ArithmeticError;
use sp_std::{vec::Vec, vec};
-use up_data_structs::{CustomDataLimit, Property, PropertyKey, PropertyKeyPermission};
+use up_data_structs::{Property, PropertyKey, PropertyKeyPermission};
use crate::{
Allowance, Balance, Config, Error, FungibleHandle, Pallet, SelfWeightOf, weights::WeightInfo,
@@ -85,11 +85,6 @@
fn burn_from() -> Weight {
<SelfWeightOf<T>>::burn_from()
}
-
- fn set_variable_metadata(_bytes: u32) -> Weight {
- // Error
- 0
- }
}
impl<T: Config> CommonCollectionOperations<T> for FungibleHandle<T> {
@@ -287,15 +282,6 @@
fail!(<Error<T>>::SettingPropertiesNotAllowed)
}
- fn set_variable_metadata(
- &self,
- _sender: T::CrossAccountId,
- _token: TokenId,
- _data: BoundedVec<u8, CustomDataLimit>,
- ) -> DispatchResultWithPostInfo {
- fail!(<Error<T>>::FungibleItemsDontHaveData)
- }
-
fn check_nesting(
&self,
_sender: <T>::CrossAccountId,
@@ -330,9 +316,6 @@
None
}
fn const_metadata(&self, _token: TokenId) -> Vec<u8> {
- Vec::new()
- }
- fn variable_metadata(&self, _token: TokenId) -> Vec<u8> {
Vec::new()
}
pallets/nonfungible/Cargo.tomldiffbeforeafterboth--- a/pallets/nonfungible/Cargo.toml
+++ b/pallets/nonfungible/Cargo.toml
@@ -27,6 +27,7 @@
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
+struct-versioning = { path = "../../crates/struct-versioning" }
[features]
default = ["std"]
pallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/benchmarking.rs
+++ b/pallets/nonfungible/src/benchmarking.rs
@@ -28,10 +28,8 @@
fn create_max_item_data<T: Config>(owner: T::CrossAccountId) -> CreateItemData<T> {
let const_data = create_data::<CUSTOM_DATA_LIMIT>();
- let variable_data = create_data::<CUSTOM_DATA_LIMIT>();
CreateItemData::<T> {
const_data,
- variable_data,
owner,
}
}
@@ -125,14 +123,4 @@
let item = create_max_item(&collection, &owner, sender.clone())?;
<Pallet<T>>::set_allowance(&collection, &sender, item, Some(&burner))?;
}: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, &Unlimited)?}
-
- set_variable_metadata {
- let b in 0..CUSTOM_DATA_LIMIT;
- bench_init!{
- owner: sub; collection: collection(owner);
- owner: cross_from_sub; sender: cross_sub;
- };
- let item = create_max_item(&collection, &owner, sender.clone())?;
- let data = create_var_data(b).try_into().unwrap();
- }: {<Pallet<T>>::set_variable_metadata(&collection, &sender, item, data)?}
}
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -16,9 +16,9 @@
use core::marker::PhantomData;
-use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};
+use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight};
use up_data_structs::{
- TokenId, CustomDataLimit, CreateItemExData, CollectionId, budget::Budget, Property,
+ TokenId, CreateItemExData, CollectionId, budget::Budget, Property,
PropertyKey, PropertyKeyPermission,
};
use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
@@ -85,10 +85,6 @@
fn burn_from() -> Weight {
<SelfWeightOf<T>>::burn_from()
- }
-
- fn set_variable_metadata(bytes: u32) -> Weight {
- <SelfWeightOf<T>>::set_variable_metadata(bytes)
}
}
@@ -99,7 +95,6 @@
match data {
up_data_structs::CreateItemData::NFT(data) => Ok(CreateItemData::<T> {
const_data: data.const_data,
- variable_data: data.variable_data,
properties: data.properties,
owner: to.clone(),
}),
@@ -325,19 +320,6 @@
} else {
Ok(().into())
}
- }
-
- fn set_variable_metadata(
- &self,
- sender: T::CrossAccountId,
- token: TokenId,
- data: BoundedVec<u8, CustomDataLimit>,
- ) -> DispatchResultWithPostInfo {
- let len = data.len();
- with_weight(
- <Pallet<T>>::set_variable_metadata(self, &sender, token, data),
- <CommonWeights<T>>::set_variable_metadata(len as u32),
- )
}
fn check_nesting(
@@ -376,12 +358,6 @@
fn const_metadata(&self, token: TokenId) -> Vec<u8> {
<TokenData<T>>::get((self.id, token))
.map(|t| t.const_data)
- .unwrap_or_default()
- .into_inner()
- }
- fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
- <TokenData<T>>::get((self.id, token))
- .map(|t| t.variable_data)
.unwrap_or_default()
.into_inner()
}
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -24,7 +24,7 @@
use up_data_structs::{TokenId, SchemaVersion};
use pallet_evm_coder_substrate::dispatch_to_evm;
use sp_core::{H160, U256};
-use sp_std::{vec::Vec, vec};
+use sp_std::vec::Vec;
use pallet_common::{
erc::{CommonEvmHandler, PrecompileResult, CollectionPropertiesCall},
CollectionHandle,
@@ -274,7 +274,6 @@
&caller,
CreateItemData::<T> {
const_data: BoundedVec::default(),
- variable_data: BoundedVec::default(),
properties: BoundedVec::default(),
owner: to,
},
@@ -322,7 +321,6 @@
const_data: Vec::<u8>::from(token_uri)
.try_into()
.map_err(|_| "token uri is too long")?,
- variable_data: BoundedVec::default(),
properties: BoundedVec::default(),
owner: to,
},
@@ -387,37 +385,6 @@
.into())
}
- #[weight(<SelfWeightOf<T>>::set_variable_metadata(data.len() as u32))]
- fn set_variable_metadata(
- &mut self,
- caller: caller,
- token_id: uint256,
- data: bytes,
- ) -> Result<void> {
- let caller = T::CrossAccountId::from_eth(caller);
- let token = token_id.try_into()?;
-
- <Pallet<T>>::set_variable_metadata(
- self,
- &caller,
- token,
- data.try_into()
- .map_err(|_| "metadata size exceeded limit")?,
- )
- .map_err(dispatch_to_evm::<T>)?;
- Ok(())
- }
-
- fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {
- self.consume_store_reads(1)?;
- let token: TokenId = token_id.try_into()?;
-
- Ok(<TokenData<T>>::get((self.id, token))
- .ok_or("token not found")?
- .variable_data
- .into_inner())
- }
-
#[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]
fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
@@ -440,7 +407,6 @@
let data = (0..total_tokens)
.map(|_| CreateItemData::<T> {
const_data: BoundedVec::default(),
- variable_data: BoundedVec::default(),
properties: BoundedVec::default(),
owner: to.clone(),
})
@@ -484,7 +450,6 @@
const_data: Vec::<u8>::from(token_uri)
.try_into()
.map_err(|_| "token uri is too long")?,
- variable_data: vec![].try_into().unwrap(),
properties: BoundedVec::default(),
owner: to.clone(),
});
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -49,17 +49,22 @@
pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::account::Config>::CrossAccountId>;
pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
+#[struct_versioning::versioned(version = 2, upper)]
#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]
pub struct ItemData<CrossAccountId> {
pub const_data: BoundedVec<u8, CustomDataLimit>,
+
+ #[version(..2)]
pub variable_data: BoundedVec<u8, CustomDataLimit>,
+
pub owner: CrossAccountId,
}
#[frame_support::pallet]
pub mod pallet {
use super::*;
- use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};
+ use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};
+ use frame_system::pallet_prelude::*;
use up_data_structs::{CollectionId, TokenId};
use super::weights::WeightInfo;
@@ -78,7 +83,10 @@
type WeightInfo: WeightInfo;
}
+ const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
+
#[pallet::pallet]
+ #[pallet::storage_version(STORAGE_VERSION)]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
@@ -133,6 +141,19 @@
Value = T::CrossAccountId,
QueryKind = OptionQuery,
>;
+
+ #[pallet::hooks]
+ impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
+ fn on_runtime_upgrade() -> Weight {
+ if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {
+ <TokenData<T>>::translate_values::<ItemDataVersion1<T::CrossAccountId>, _>(|v| {
+ Some(<ItemDataVersion2<T::CrossAccountId>>::from(v))
+ })
+ }
+
+ 0
+ }
+ }
}
pub struct NonfungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);
@@ -577,7 +598,6 @@
(collection.id, token),
ItemData {
const_data: data.const_data,
- variable_data: data.variable_data,
owner: data.owner.clone(),
},
);
@@ -773,28 +793,6 @@
// =========
Self::burn(collection, from, token)
- }
-
- pub fn set_variable_metadata(
- collection: &NonfungibleHandle<T>,
- sender: &T::CrossAccountId,
- token: TokenId,
- data: BoundedVec<u8, CustomDataLimit>,
- ) -> DispatchResult {
- let token_data =
- <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
- collection.check_can_update_meta(sender, &token_data.owner)?;
-
- // =========
-
- <TokenData<T>>::insert(
- (collection.id, token),
- ItemData {
- variable_data: data,
- ..token_data
- },
- );
- Ok(())
}
pub fn check_nesting(
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -61,6 +61,24 @@
}
}
+// Selector: 56fd500b
+contract CollectionProperties is Dummy, ERC165 {
+ // Selector: setProperty(string,string) 62d9491f
+ function setProperty(string memory key, string memory value) public {
+ require(false, stub_error);
+ key;
+ value;
+ dummy = 0;
+ }
+
+ // Selector: deleteProperty(string) 34241914
+ function deleteProperty(string memory key) public {
+ require(false, stub_error);
+ key;
+ dummy = 0;
+ }
+}
+
// Selector: 58800161
contract ERC721 is Dummy, ERC165, ERC721Events {
// Selector: balanceOf(address) 70a08231
@@ -276,7 +294,7 @@
}
}
-// Selector: e562194d
+// Selector: d74d154f
contract ERC721UniqueExtensions is Dummy, ERC165 {
// Selector: transfer(address,uint256) a9059cbb
function transfer(address to, uint256 tokenId) public {
@@ -301,26 +319,6 @@
return 0;
}
- // Selector: setVariableMetadata(uint256,bytes) d4eac26d
- function setVariableMetadata(uint256 tokenId, bytes memory data) public {
- require(false, stub_error);
- tokenId;
- data;
- dummy = 0;
- }
-
- // Selector: getVariableMetadata(uint256) e6c5ce6f
- function getVariableMetadata(uint256 tokenId)
- public
- view
- returns (bytes memory)
- {
- require(false, stub_error);
- tokenId;
- dummy;
- return hex"";
- }
-
// Selector: mintBulk(address,uint256[]) 44a9945e
function mintBulk(address to, uint256[] memory tokenIds)
public
@@ -354,5 +352,6 @@
ERC721Enumerable,
ERC721UniqueExtensions,
ERC721Mintable,
- ERC721Burnable
+ ERC721Burnable,
+ CollectionProperties
{}
pallets/nonfungible/src/weights.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/weights.rs
+++ b/pallets/nonfungible/src/weights.rs
@@ -45,7 +45,6 @@
fn approve() -> Weight;
fn transfer_from() -> Weight;
fn burn_from() -> Weight;
- fn set_variable_metadata(b: u32, ) -> Weight;
}
/// Weights for pallet_nonfungible using the Substrate node and recommended hardware.
@@ -155,12 +154,6 @@
(27_580_000 as Weight)
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(5 as Weight))
- }
- // Storage: Nonfungible TokenData (r:1 w:1)
- fn set_variable_metadata(_b: u32, ) -> Weight {
- (7_700_000 as Weight)
- .saturating_add(T::DbWeight::get().reads(1 as Weight))
- .saturating_add(T::DbWeight::get().writes(1 as Weight))
}
}
@@ -270,11 +263,5 @@
(27_580_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(4 as Weight))
.saturating_add(RocksDbWeight::get().writes(5 as Weight))
- }
- // Storage: Nonfungible TokenData (r:1 w:1)
- fn set_variable_metadata(_b: u32, ) -> Weight {
- (7_700_000 as Weight)
- .saturating_add(RocksDbWeight::get().reads(1 as Weight))
- .saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
}
pallets/refungible/Cargo.tomldiffbeforeafterboth--- a/pallets/refungible/Cargo.toml
+++ b/pallets/refungible/Cargo.toml
@@ -24,6 +24,7 @@
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
+struct-versioning = { path = "../../crates/struct-versioning" }
[features]
default = ["std"]
pallets/refungible/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/refungible/src/benchmarking.rs
+++ b/pallets/refungible/src/benchmarking.rs
@@ -31,10 +31,8 @@
users: impl IntoIterator<Item = (CrossAccountId, u128)>,
) -> CreateRefungibleExData<CrossAccountId> {
let const_data = create_data::<CUSTOM_DATA_LIMIT>();
- let variable_data = create_data::<CUSTOM_DATA_LIMIT>();
CreateRefungibleExData {
const_data,
- variable_data,
users: users
.into_iter()
.collect::<BTreeMap<_, _>>()
@@ -203,14 +201,4 @@
let item = create_max_item(&collection, &owner, [(sender.clone(), 200)])?;
<Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;
}: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200, &Unlimited)?}
-
- set_variable_metadata {
- let b in 0..CUSTOM_DATA_LIMIT;
- bench_init!{
- owner: sub; collection: collection(owner);
- sender: cross_from_sub(owner);
- };
- let item = create_max_item(&collection, &sender, [(sender.clone(), 200)])?;
- let data = create_var_data(b).try_into().unwrap();
- }: {<Pallet<T>>::set_variable_metadata(&collection, &sender, item, data)?}
}
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -17,9 +17,9 @@
use core::marker::PhantomData;
use sp_std::collections::btree_map::BTreeMap;
-use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight, BoundedVec};
+use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight};
use up_data_structs::{
- CollectionId, TokenId, CustomDataLimit, CreateItemExData, CreateRefungibleExData,
+ CollectionId, TokenId, CreateItemExData, CreateRefungibleExData,
budget::Budget, Property, PropertyKey, PropertyKeyPermission,
};
use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
@@ -110,10 +110,6 @@
fn burn_from() -> Weight {
<SelfWeightOf<T>>::burn_from()
- }
-
- fn set_variable_metadata(bytes: u32) -> Weight {
- <SelfWeightOf<T>>::set_variable_metadata(bytes)
}
}
@@ -124,7 +120,6 @@
match data {
up_data_structs::CreateItemData::ReFungible(data) => Ok(CreateRefungibleExData {
const_data: data.const_data,
- variable_data: data.variable_data,
users: {
let mut out = BTreeMap::new();
out.insert(to.clone(), data.pieces);
@@ -306,19 +301,6 @@
fail!(<Error<T>>::SettingPropertiesNotAllowed)
}
- fn set_variable_metadata(
- &self,
- sender: T::CrossAccountId,
- token: TokenId,
- data: BoundedVec<u8, CustomDataLimit>,
- ) -> DispatchResultWithPostInfo {
- let len = data.len();
- with_weight(
- <Pallet<T>>::set_variable_metadata(self, &sender, token, data),
- <CommonWeights<T>>::set_variable_metadata(len as u32),
- )
- }
-
fn check_nesting(
&self,
_sender: <T>::CrossAccountId,
@@ -355,11 +337,6 @@
fn const_metadata(&self, token: TokenId) -> Vec<u8> {
<TokenData<T>>::get((self.id, token))
.const_data
- .into_inner()
- }
- fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
- <TokenData<T>>::get((self.id, token))
- .variable_data
.into_inner()
}
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -41,16 +41,20 @@
pub mod weights;
pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
+#[struct_versioning::versioned(version = 2, upper)]
#[derive(Encode, Decode, Default, TypeInfo, MaxEncodedLen)]
pub struct ItemData {
pub const_data: BoundedVec<u8, CustomDataLimit>,
+
+ #[version(..2)]
pub variable_data: BoundedVec<u8, CustomDataLimit>,
}
#[frame_support::pallet]
pub mod pallet {
use super::*;
- use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};
+ use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key, traits::StorageVersion};
+ use frame_system::pallet_prelude::*;
use up_data_structs::{CollectionId, TokenId};
use super::weights::WeightInfo;
@@ -73,7 +77,10 @@
type WeightInfo: WeightInfo;
}
+ const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);
+
#[pallet::pallet]
+ #[pallet::storage_version(STORAGE_VERSION)]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
@@ -146,6 +153,19 @@
Value = u128,
QueryKind = ValueQuery,
>;
+
+ #[pallet::hooks]
+ impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
+ fn on_runtime_upgrade() -> Weight {
+ if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {
+ <TokenData<T>>::translate_values::<ItemDataVersion1, _>(|v| {
+ Some(<ItemDataVersion2>::from(v))
+ })
+ }
+
+ 0
+ }
+ }
}
pub struct RefungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);
@@ -494,7 +514,6 @@
(collection.id, token_id),
ItemData {
const_data: token.const_data,
- variable_data: token.variable_data,
},
);
for (user, amount) in token.users.into_iter() {
@@ -643,31 +662,6 @@
if let Some(allowance) = allowance {
Self::set_allowance_unchecked(collection, from, spender, token, allowance);
}
- Ok(())
- }
-
- pub fn set_variable_metadata(
- collection: &RefungibleHandle<T>,
- sender: &T::CrossAccountId,
- token: TokenId,
- data: BoundedVec<u8, CustomDataLimit>,
- ) -> DispatchResult {
- collection.check_can_update_meta(
- sender,
- &T::CrossAccountId::from_sub(collection.owner.clone()),
- )?;
-
- let token_data = <TokenData<T>>::get((collection.id, token));
-
- // =========
-
- <TokenData<T>>::insert(
- (collection.id, token),
- ItemData {
- variable_data: data,
- ..token_data
- },
- );
Ok(())
}
pallets/refungible/src/weights.rsdiffbeforeafterboth--- a/pallets/refungible/src/weights.rs
+++ b/pallets/refungible/src/weights.rs
@@ -53,7 +53,6 @@
fn transfer_from_removing() -> Weight;
fn transfer_from_creating_removing() -> Weight;
fn burn_from() -> Weight;
- fn set_variable_metadata(b: u32, ) -> Weight;
}
/// Weights for pallet_refungible using the Substrate node and recommended hardware.
@@ -242,12 +241,6 @@
(42_043_000 as Weight)
.saturating_add(T::DbWeight::get().reads(5 as Weight))
.saturating_add(T::DbWeight::get().writes(7 as Weight))
- }
- // Storage: Refungible TokenData (r:1 w:1)
- fn set_variable_metadata(_b: u32, ) -> Weight {
- (7_364_000 as Weight)
- .saturating_add(T::DbWeight::get().reads(1 as Weight))
- .saturating_add(T::DbWeight::get().writes(1 as Weight))
}
}
@@ -436,11 +429,5 @@
(42_043_000 as Weight)
.saturating_add(RocksDbWeight::get().reads(5 as Weight))
.saturating_add(RocksDbWeight::get().writes(7 as Weight))
- }
- // Storage: Refungible TokenData (r:1 w:1)
- fn set_variable_metadata(_b: u32, ) -> Weight {
- (7_364_000 as Weight)
- .saturating_add(RocksDbWeight::get().reads(1 as Weight))
- .saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
}
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -38,7 +38,7 @@
CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,
MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,
AccessMode, CreateItemData, CollectionLimits, CollectionId, CollectionMode, TokenId,
- SchemaVersion, SponsorshipState, MetaUpdatePermission, CreateCollectionData, CustomDataLimit,
+ SchemaVersion, SponsorshipState, MetaUpdatePermission, CreateCollectionData,
CreateItemExData, budget, CollectionField, Property, PropertyKey, PropertyKeyPermission,
};
use pallet_evm::account::CrossAccountId;
@@ -238,9 +238,6 @@
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>;
//#endregion
- /// Variable metadata sponsoring
- /// Collection id (controlled?2), token id (controlled?2)
- pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
/// Approval sponsoring
pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;
pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;
@@ -333,7 +330,6 @@
<FungibleTransferBasket<T>>::remove_prefix(collection_id, None);
<ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);
- <VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);
<NftApproveBasket<T>>::remove_prefix(collection_id, None);
<FungibleApproveBasket<T>>::remove_prefix(collection_id, None);
<RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);
@@ -929,31 +925,6 @@
let budget = budget::Value::new(2);
dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))
- }
-
- /// Set off-chain data schema.
- ///
- /// # Permissions
- ///
- /// * Collection Owner
- /// * Collection Admin
- ///
- /// # Arguments
- ///
- /// * collection_id.
- ///
- /// * schema: String representing the offchain data schema.
- #[weight = T::CommonWeightInfo::set_variable_metadata(data.len() as u32)]
- #[transactional]
- pub fn set_variable_meta_data (
- origin,
- collection_id: CollectionId,
- item_id: TokenId,
- data: BoundedVec<u8, CustomDataLimit>,
- ) -> DispatchResultWithPostInfo {
- let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
-
- dispatch_call::<T, _>(collection_id, |d| d.set_variable_metadata(sender, item_id, data))
}
/// Set meta_update_permission value for particular collection
primitives/data-structs/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![cfg_attr(not(feature = "std"), no_std)]1819use core::{20 convert::{TryFrom, TryInto},21 fmt,22};23use frame_support::{24 storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},25 traits::Get,26};2728#[cfg(feature = "serde")]29use serde::{Serialize, Deserialize};3031use sp_core::U256;32use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};33use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};34use frame_support::{BoundedVec, traits::ConstU32};35use derivative::Derivative;36use scale_info::TypeInfo;3738mod bounded;39pub mod budget;40pub mod mapping;41mod migration;4243pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;44pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;45pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;4647pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {48 100_00049} else {50 1051};52pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {53 100_00054} else {55 1056};57pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {58 204859} else {60 1061};62pub const COLLECTION_ADMINS_LIMIT: u32 = 5;63pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;64pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {65 1_000_00066} else {67 1068};6970// Timeouts for item types in passed blocks71pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;72pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;73pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;7475pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;7677// Schema limits78pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;79pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;80pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;8182pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;8384pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;85pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;86pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;8788pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;89pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;90pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;9192// pub const MAX_PROPERTY_KEYS_OVERALL_LENGTH: u32 = MAX_PROPERTY_KEY_LENGTH * MAX_PROPERTIES_PER_ITEM;93pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;94pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;9596pub const MAX_COLLECTION_PROPERTIES_ENCODE_LEN: u32 =97 MAX_PROPERTIES_PER_ITEM * MAX_PROPERTY_KEY_LENGTH + MAX_COLLECTION_PROPERTIES_SIZE;9899pub struct MaxPropertiesPermissionsEncodeLen;100101impl Get<u32> for MaxPropertiesPermissionsEncodeLen {102 fn get() -> u32 {103 MAX_PROPERTIES_PER_ITEM * MAX_PROPERTY_KEY_LENGTH104 + <PropertyPermission as MaxEncodedLen>::max_encoded_len() as u32105 }106}107108/// How much items can be created per single109/// create_many call110pub const MAX_ITEMS_PER_BATCH: u32 = 200;111112pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;113114#[derive(115 Encode,116 Decode,117 PartialEq,118 Eq,119 PartialOrd,120 Ord,121 Clone,122 Copy,123 Debug,124 Default,125 TypeInfo,126 MaxEncodedLen,127)]128#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]129pub struct CollectionId(pub u32);130impl EncodeLike<u32> for CollectionId {}131impl EncodeLike<CollectionId> for u32 {}132133#[derive(134 Encode,135 Decode,136 PartialEq,137 Eq,138 PartialOrd,139 Ord,140 Clone,141 Copy,142 Debug,143 Default,144 TypeInfo,145 MaxEncodedLen,146)]147#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]148pub struct TokenId(pub u32);149impl EncodeLike<u32> for TokenId {}150impl EncodeLike<TokenId> for u32 {}151152impl TokenId {153 pub fn try_next(self) -> Result<TokenId, ArithmeticError> {154 self.0155 .checked_add(1)156 .ok_or(ArithmeticError::Overflow)157 .map(Self)158 }159}160161impl From<TokenId> for U256 {162 fn from(t: TokenId) -> Self {163 t.0.into()164 }165}166167impl TryFrom<U256> for TokenId {168 type Error = &'static str;169170 fn try_from(value: U256) -> Result<Self, Self::Error> {171 Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))172 }173}174175#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]176#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]177pub struct TokenData<CrossAccountId> {178 pub const_data: Vec<u8>,179 pub properties: Vec<Property>,180 pub owner: Option<CrossAccountId>,181}182183pub struct OverflowError;184impl From<OverflowError> for &'static str {185 fn from(_: OverflowError) -> Self {186 "overflow occured"187 }188}189190pub type DecimalPoints = u8;191192#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]193#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]194pub enum CollectionMode {195 NFT,196 // decimal points197 Fungible(DecimalPoints),198 ReFungible,199}200201impl CollectionMode {202 pub fn id(&self) -> u8 {203 match self {204 CollectionMode::NFT => 1,205 CollectionMode::Fungible(_) => 2,206 CollectionMode::ReFungible => 3,207 }208 }209}210211pub trait SponsoringResolve<AccountId, Call> {212 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;213}214215#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]216#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]217pub enum AccessMode {218 Normal,219 AllowList,220}221impl Default for AccessMode {222 fn default() -> Self {223 Self::Normal224 }225}226227#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]228#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]229pub enum SchemaVersion {230 ImageURL,231 Unique,232}233impl Default for SchemaVersion {234 fn default() -> Self {235 Self::ImageURL236 }237}238239#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]240#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]241pub struct Ownership<AccountId> {242 pub owner: AccountId,243 pub fraction: u128,244}245246#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]247#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]248pub enum SponsorshipState<AccountId> {249 /// The fees are applied to the transaction sender250 Disabled,251 Unconfirmed(AccountId),252 /// Transactions are sponsored by specified account253 Confirmed(AccountId),254}255256impl<AccountId> SponsorshipState<AccountId> {257 pub fn sponsor(&self) -> Option<&AccountId> {258 match self {259 Self::Confirmed(sponsor) => Some(sponsor),260 _ => None,261 }262 }263264 pub fn pending_sponsor(&self) -> Option<&AccountId> {265 match self {266 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),267 _ => None,268 }269 }270271 pub fn confirmed(&self) -> bool {272 matches!(self, Self::Confirmed(_))273 }274}275276impl<T> Default for SponsorshipState<T> {277 fn default() -> Self {278 Self::Disabled279 }280}281282/// Used in storage283#[struct_versioning::versioned(version = 2, upper)]284#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]285pub struct Collection<AccountId> {286 pub owner: AccountId,287 pub mode: CollectionMode,288 pub access: AccessMode,289 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,290 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,291 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,292 pub mint_mode: bool,293294 #[version(..2)]295 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,296297 pub schema_version: SchemaVersion,298 pub sponsorship: SponsorshipState<AccountId>,299300 #[version(..2)]301 pub limits: CollectionLimitsVersion1, // Collection private restrictions302 #[version(2.., upper(limits.into()))]303 pub limits: CollectionLimitsVersion2,304305 #[version(..2)]306 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,307308 #[version(..2)]309 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,310311 pub meta_update_permission: MetaUpdatePermission,312}313314/// Used in RPC calls315#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]316#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]317pub struct RpcCollection<AccountId> {318 pub owner: AccountId,319 pub mode: CollectionMode,320 pub access: AccessMode,321 pub name: Vec<u16>,322 pub description: Vec<u16>,323 pub token_prefix: Vec<u8>,324 pub mint_mode: bool,325 pub offchain_schema: Vec<u8>,326 pub schema_version: SchemaVersion,327 pub sponsorship: SponsorshipState<AccountId>,328 pub limits: CollectionLimits,329 pub const_on_chain_schema: Vec<u8>,330 pub meta_update_permission: MetaUpdatePermission,331 pub token_property_permissions: Vec<PropertyKeyPermission>,332 pub properties: Vec<Property>,333}334335#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]336#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]337pub enum CollectionField {338 ConstOnChainSchema,339 OffchainSchema,340}341342#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]343#[derivative(Debug, Default(bound = ""))]344pub struct CreateCollectionData<AccountId> {345 #[derivative(Default(value = "CollectionMode::NFT"))]346 pub mode: CollectionMode,347 pub access: Option<AccessMode>,348 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,349 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,350 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,351 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,352 pub schema_version: Option<SchemaVersion>,353 pub pending_sponsor: Option<AccountId>,354 pub limits: Option<CollectionLimits>,355 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,356 pub meta_update_permission: Option<MetaUpdatePermission>,357 pub token_property_permissions: CollectionPropertiesPermissionsVec,358 pub properties: CollectionPropertiesVec,359}360361pub type CollectionPropertiesPermissionsVec =362 BoundedVec<PropertyKeyPermission, MaxPropertiesPermissionsEncodeLen>;363364pub type CollectionPropertiesVec =365 BoundedVec<Property, ConstU32<MAX_COLLECTION_PROPERTIES_ENCODE_LEN>>;366367#[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}374375#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]376#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]377pub struct FungibleItemType {378 pub value: u128,379}380381#[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}388389/// All fields are wrapped in `Option`s, where None means chain default390#[struct_versioning::versioned(version = 2, upper)]391#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]392#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]393pub struct CollectionLimits {394 pub account_token_ownership_limit: Option<u32>,395 pub sponsored_data_size: Option<u32>,396 /// None - setVariableMetadata is not sponsored397 /// Some(v) - setVariableMetadata is sponsored398 /// if there is v block between txs399 pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,400 pub token_limit: Option<u32>,401402 // Timeouts for item types in passed blocks403 pub sponsor_transfer_timeout: Option<u32>,404 pub sponsor_approve_timeout: Option<u32>,405 pub owner_can_transfer: Option<bool>,406 pub owner_can_destroy: Option<bool>,407 pub transfers_enabled: Option<bool>,408409 #[version(2.., upper(None))]410 pub nesting_rule: Option<NestingRule>,411}412413impl CollectionLimits {414 pub fn account_token_ownership_limit(&self) -> u32 {415 self.account_token_ownership_limit416 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)417 .min(MAX_TOKEN_OWNERSHIP)418 }419 pub fn sponsored_data_size(&self) -> u32 {420 self.sponsored_data_size421 .unwrap_or(CUSTOM_DATA_LIMIT)422 .min(CUSTOM_DATA_LIMIT)423 }424 pub fn token_limit(&self) -> u32 {425 self.token_limit426 .unwrap_or(COLLECTION_TOKEN_LIMIT)427 .min(COLLECTION_TOKEN_LIMIT)428 }429 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {430 self.sponsor_transfer_timeout431 .unwrap_or(default)432 .min(MAX_SPONSOR_TIMEOUT)433 }434 pub fn sponsor_approve_timeout(&self) -> u32 {435 self.sponsor_approve_timeout436 .unwrap_or(SPONSOR_APPROVE_TIMEOUT)437 .min(MAX_SPONSOR_TIMEOUT)438 }439 pub fn owner_can_transfer(&self) -> bool {440 self.owner_can_transfer.unwrap_or(true)441 }442 pub fn owner_can_destroy(&self) -> bool {443 self.owner_can_destroy.unwrap_or(true)444 }445 pub fn transfers_enabled(&self) -> bool {446 self.transfers_enabled.unwrap_or(true)447 }448 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {449 match self450 .sponsored_data_rate_limit451 .unwrap_or(SponsoringRateLimit::SponsoringDisabled)452 {453 SponsoringRateLimit::SponsoringDisabled => None,454 SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),455 }456 }457 pub fn nesting_rule(&self) -> &NestingRule {458 static DEFAULT: NestingRule = NestingRule::Disabled;459 self.nesting_rule.as_ref().unwrap_or(&DEFAULT)460 }461}462463#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]464#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]465#[derivative(Debug)]466pub enum NestingRule {467 /// No one can nest tokens468 Disabled,469 /// Owner can nest any tokens470 Owner,471 /// Owner can nest tokens from specified collections472 OwnerRestricted(473 #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]474 #[derivative(Debug(format_with = "bounded::set_debug"))]475 BoundedBTreeSet<CollectionId, ConstU32<16>>,476 ),477}478479#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]480#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]481pub enum SponsoringRateLimit {482 SponsoringDisabled,483 Blocks(u32),484}485486#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]487#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]488#[derivative(Debug)]489pub struct CreateNftData {490 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]491 #[derivative(Debug(format_with = "bounded::vec_debug"))]492 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>,496497 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]498 #[derivative(Debug(format_with = "bounded::vec_debug"))]499 pub properties: CollectionPropertiesVec,500}501502#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]503#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]504pub struct CreateFungibleData {505 pub value: u128,506}507508#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]509#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]510#[derivative(Debug)]511pub struct CreateReFungibleData {512 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]513 #[derivative(Debug(format_with = "bounded::vec_debug"))]514 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,519}520521#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]522#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]523pub enum MetaUpdatePermission {524 ItemOwner,525 Admin,526 None,527}528529impl Default for MetaUpdatePermission {530 fn default() -> Self {531 Self::ItemOwner532 }533}534535#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]536#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]537pub enum CreateItemData {538 NFT(CreateNftData),539 Fungible(CreateFungibleData),540 ReFungible(CreateReFungibleData),541}542543#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]544#[derivative(Debug)]545pub struct CreateNftExData<CrossAccountId> {546 #[derivative(Debug(format_with = "bounded::vec_debug"))]547 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"))]551 pub properties: CollectionPropertiesVec,552 pub owner: CrossAccountId,553}554555#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]556#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]557pub struct CreateRefungibleExData<CrossAccountId> {558 #[derivative(Debug(format_with = "bounded::vec_debug"))]559 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"))]563 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,564}565566#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]567#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]568pub enum CreateItemExData<CrossAccountId> {569 NFT(570 #[derivative(Debug(format_with = "bounded::vec_debug"))]571 BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,572 ),573 Fungible(574 #[derivative(Debug(format_with = "bounded::map_debug"))]575 BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,576 ),577 /// Many tokens, each may have only one owner578 RefungibleMultipleItems(579 #[derivative(Debug(format_with = "bounded::vec_debug"))]580 BoundedVec<CreateRefungibleExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,581 ),582 /// Single token, which may have many owners583 RefungibleMultipleOwners(CreateRefungibleExData<CrossAccountId>),584}585586impl CreateItemData {587 pub fn data_size(&self) -> usize {588 match self {589 CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),590 CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),591 _ => 0,592 }593 }594}595596impl From<CreateNftData> for CreateItemData {597 fn from(item: CreateNftData) -> Self {598 CreateItemData::NFT(item)599 }600}601602impl From<CreateReFungibleData> for CreateItemData {603 fn from(item: CreateReFungibleData) -> Self {604 CreateItemData::ReFungible(item)605 }606}607608impl From<CreateFungibleData> for CreateItemData {609 fn from(item: CreateFungibleData) -> Self {610 CreateItemData::Fungible(item)611 }612}613614#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]615#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]616pub struct CollectionStats {617 pub created: u32,618 pub destroyed: u32,619 pub alive: u32,620}621622#[derive(Encode, Decode, PartialEq, Clone, Debug)]623pub struct PhantomType<T>(core::marker::PhantomData<T>);624625impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {626 type Identity = PhantomType<T>;627628 fn type_info() -> scale_info::Type {629 use scale_info::{630 Type, Path,631 build::{FieldsBuilder, UnnamedFields},632 type_params,633 };634 Type::builder()635 .path(Path::new("up_data_structs", "PhantomType"))636 .type_params(type_params!(T))637 .composite(<FieldsBuilder<UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()))638 }639}640impl<T> MaxEncodedLen for PhantomType<T> {641 fn max_encoded_len() -> usize {642 0643 }644}645646pub type PropertyKey = BoundedVec<u8, ConstU32<MAX_PROPERTY_KEY_LENGTH>>;647pub type PropertyValue = BoundedVec<u8, ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;648649#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]650#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]651pub struct PropertyPermission {652 pub mutable: bool,653 pub collection_admin: bool,654 pub token_owner: bool,655}656657impl PropertyPermission {658 pub fn none() -> Self {659 Self {660 mutable: true,661 collection_admin: false,662 token_owner: false,663 }664 }665}666667#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]668#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]669pub struct Property {670 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]671 pub key: PropertyKey,672673 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]674 pub value: PropertyValue,675}676677#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]678#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]679pub struct PropertyKeyPermission {680 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]681 pub key: PropertyKey,682683 pub permission: PropertyPermission,684}685686pub enum PropertiesError {687 NoSpaceForProperty,688 PropertyLimitReached,689 InvalidCharacterInPropertyKey,690 EmptyPropertyKey,691}692693pub trait TrySet: Sized {694 type Value;695696 fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError>;697698 fn try_set_from_iter<I>(&mut self, iter: I) -> Result<(), PropertiesError>699 where700 I: Iterator<Item = (PropertyKey, Self::Value)>,701 {702 for (key, value) in iter {703 self.try_set(key, value)?;704 }705706 Ok(())707 }708}709710#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]711#[derivative(Default(bound = ""))]712pub struct PropertiesMap<Value>(713 BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,714);715716impl<Value> PropertiesMap<Value> {717 pub fn new() -> Self {718 Self(BoundedBTreeMap::new())719 }720721 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {722 Self::check_property_key(key)?;723724 Ok(self.0.remove(key))725 }726727 pub fn get(&self, key: &PropertyKey) -> Option<&Value> {728 self.0.get(key)729 }730731 pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &Value)> {732 self.0.iter()733 }734735 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {736 if key.is_empty() {737 return Err(PropertiesError::EmptyPropertyKey);738 }739740 for byte in key.as_slice().iter() {741 match char::from_u32(*byte as u32) {742 Some(ch)743 if ch.is_ascii_alphanumeric()744 || ch == '_'745 || ch == '-' => { /* OK */ },746 _ => return Err(PropertiesError::InvalidCharacterInPropertyKey)747 }748 }749750 Ok(())751 }752}753754impl<Value> TrySet for PropertiesMap<Value> {755 type Value = Value;756757 fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {758 Self::check_property_key(&key)?;759760 self.0761 .try_insert(key, value)762 .map_err(|_| PropertiesError::PropertyLimitReached)?;763764 Ok(())765 }766}767768pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;769770#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, MaxEncodedLen)]771pub struct Properties {772 map: PropertiesMap<PropertyValue>,773 consumed_space: u32,774 space_limit: u32,775}776777impl Properties {778 pub fn new(space_limit: u32) -> Self {779 Self {780 map: PropertiesMap::new(),781 consumed_space: 0,782 space_limit,783 }784 }785786 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {787 let value = self.map.remove(key)?;788789 if let Some(ref value) = value {790 let value_len = value.len() as u32;791 self.consumed_space -= value_len;792 }793794 Ok(value)795 }796797 pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {798 self.map.get(key)799 }800801 pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &PropertyValue)> {802 self.map.iter()803 }804}805806impl TrySet for Properties {807 type Value = PropertyValue;808809 fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {810 let value_len = value.len();811812 if self.consumed_space as usize + value_len > self.space_limit as usize {813 return Err(PropertiesError::NoSpaceForProperty);814 }815816 self.map.try_set(key, value)?;817818 self.consumed_space += value_len as u32;819820 Ok(())821 }822}823824pub struct CollectionProperties;825826impl Get<Properties> for CollectionProperties {827 fn get() -> Properties {828 Properties::new(MAX_COLLECTION_PROPERTIES_SIZE)829 }830}831832pub struct TokenProperties;833834impl Get<Properties> for TokenProperties {835 fn get() -> Properties {836 Properties::new(MAX_TOKEN_PROPERTIES_SIZE)837 }838}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![cfg_attr(not(feature = "std"), no_std)]1819use core::{20 convert::{TryFrom, TryInto},21 fmt,22};23use frame_support::{24 storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},25 traits::Get,26};2728#[cfg(feature = "serde")]29use serde::{Serialize, Deserialize};3031use sp_core::U256;32use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};33use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};34use frame_support::{BoundedVec, traits::ConstU32};35use derivative::Derivative;36use scale_info::TypeInfo;3738mod bounded;39pub mod budget;40pub mod mapping;41mod migration;4243pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;44pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;45pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;4647pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {48 100_00049} else {50 1051};52pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {53 100_00054} else {55 1056};57pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {58 204859} else {60 1061};62pub const COLLECTION_ADMINS_LIMIT: u32 = 5;63pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;64pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {65 1_000_00066} else {67 1068};6970// Timeouts for item types in passed blocks71pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;72pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;73pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;7475pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;7677// Schema limits78pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;79pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;80pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;8182pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;8384pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;85pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;86pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;8788pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;89pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;90pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;9192// pub const MAX_PROPERTY_KEYS_OVERALL_LENGTH: u32 = MAX_PROPERTY_KEY_LENGTH * MAX_PROPERTIES_PER_ITEM;93pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;94pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;9596pub const MAX_COLLECTION_PROPERTIES_ENCODE_LEN: u32 =97 MAX_PROPERTIES_PER_ITEM * MAX_PROPERTY_KEY_LENGTH + MAX_COLLECTION_PROPERTIES_SIZE;9899pub struct MaxPropertiesPermissionsEncodeLen;100101impl Get<u32> for MaxPropertiesPermissionsEncodeLen {102 fn get() -> u32 {103 MAX_PROPERTIES_PER_ITEM * MAX_PROPERTY_KEY_LENGTH104 + <PropertyPermission as MaxEncodedLen>::max_encoded_len() as u32105 }106}107108/// How much items can be created per single109/// create_many call110pub const MAX_ITEMS_PER_BATCH: u32 = 200;111112pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;113114#[derive(115 Encode,116 Decode,117 PartialEq,118 Eq,119 PartialOrd,120 Ord,121 Clone,122 Copy,123 Debug,124 Default,125 TypeInfo,126 MaxEncodedLen,127)]128#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]129pub struct CollectionId(pub u32);130impl EncodeLike<u32> for CollectionId {}131impl EncodeLike<CollectionId> for u32 {}132133#[derive(134 Encode,135 Decode,136 PartialEq,137 Eq,138 PartialOrd,139 Ord,140 Clone,141 Copy,142 Debug,143 Default,144 TypeInfo,145 MaxEncodedLen,146)]147#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]148pub struct TokenId(pub u32);149impl EncodeLike<u32> for TokenId {}150impl EncodeLike<TokenId> for u32 {}151152impl TokenId {153 pub fn try_next(self) -> Result<TokenId, ArithmeticError> {154 self.0155 .checked_add(1)156 .ok_or(ArithmeticError::Overflow)157 .map(Self)158 }159}160161impl From<TokenId> for U256 {162 fn from(t: TokenId) -> Self {163 t.0.into()164 }165}166167impl TryFrom<U256> for TokenId {168 type Error = &'static str;169170 fn try_from(value: U256) -> Result<Self, Self::Error> {171 Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))172 }173}174175#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]176#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]177pub struct TokenData<CrossAccountId> {178 pub const_data: Vec<u8>,179 pub properties: Vec<Property>,180 pub owner: Option<CrossAccountId>,181}182183pub struct OverflowError;184impl From<OverflowError> for &'static str {185 fn from(_: OverflowError) -> Self {186 "overflow occured"187 }188}189190pub type DecimalPoints = u8;191192#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]193#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]194pub enum CollectionMode {195 NFT,196 // decimal points197 Fungible(DecimalPoints),198 ReFungible,199}200201impl CollectionMode {202 pub fn id(&self) -> u8 {203 match self {204 CollectionMode::NFT => 1,205 CollectionMode::Fungible(_) => 2,206 CollectionMode::ReFungible => 3,207 }208 }209}210211pub trait SponsoringResolve<AccountId, Call> {212 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;213}214215#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]216#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]217pub enum AccessMode {218 Normal,219 AllowList,220}221impl Default for AccessMode {222 fn default() -> Self {223 Self::Normal224 }225}226227#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]228#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]229pub enum SchemaVersion {230 ImageURL,231 Unique,232}233impl Default for SchemaVersion {234 fn default() -> Self {235 Self::ImageURL236 }237}238239#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]240#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]241pub struct Ownership<AccountId> {242 pub owner: AccountId,243 pub fraction: u128,244}245246#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]247#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]248pub enum SponsorshipState<AccountId> {249 /// The fees are applied to the transaction sender250 Disabled,251 Unconfirmed(AccountId),252 /// Transactions are sponsored by specified account253 Confirmed(AccountId),254}255256impl<AccountId> SponsorshipState<AccountId> {257 pub fn sponsor(&self) -> Option<&AccountId> {258 match self {259 Self::Confirmed(sponsor) => Some(sponsor),260 _ => None,261 }262 }263264 pub fn pending_sponsor(&self) -> Option<&AccountId> {265 match self {266 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),267 _ => None,268 }269 }270271 pub fn confirmed(&self) -> bool {272 matches!(self, Self::Confirmed(_))273 }274}275276impl<T> Default for SponsorshipState<T> {277 fn default() -> Self {278 Self::Disabled279 }280}281282/// Used in storage283#[struct_versioning::versioned(version = 2, upper)]284#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]285pub struct Collection<AccountId> {286 pub owner: AccountId,287 pub mode: CollectionMode,288 pub access: AccessMode,289 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,290 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,291 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,292 pub mint_mode: bool,293294 #[version(..2)]295 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,296297 pub schema_version: SchemaVersion,298 pub sponsorship: SponsorshipState<AccountId>,299300 #[version(..2)]301 pub limits: CollectionLimitsVersion1, // Collection private restrictions302 #[version(2.., upper(limits.into()))]303 pub limits: CollectionLimitsVersion2,304305 #[version(..2)]306 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,307308 #[version(..2)]309 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,310311 pub meta_update_permission: MetaUpdatePermission,312}313314/// Used in RPC calls315#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]316#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]317pub struct RpcCollection<AccountId> {318 pub owner: AccountId,319 pub mode: CollectionMode,320 pub access: AccessMode,321 pub name: Vec<u16>,322 pub description: Vec<u16>,323 pub token_prefix: Vec<u8>,324 pub mint_mode: bool,325 pub offchain_schema: Vec<u8>,326 pub schema_version: SchemaVersion,327 pub sponsorship: SponsorshipState<AccountId>,328 pub limits: CollectionLimits,329 pub const_on_chain_schema: Vec<u8>,330 pub meta_update_permission: MetaUpdatePermission,331 pub token_property_permissions: Vec<PropertyKeyPermission>,332 pub properties: Vec<Property>,333}334335#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]336#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]337pub enum CollectionField {338 ConstOnChainSchema,339 OffchainSchema,340}341342#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]343#[derivative(Debug, Default(bound = ""))]344pub struct CreateCollectionData<AccountId> {345 #[derivative(Default(value = "CollectionMode::NFT"))]346 pub mode: CollectionMode,347 pub access: Option<AccessMode>,348 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,349 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,350 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,351 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,352 pub schema_version: Option<SchemaVersion>,353 pub pending_sponsor: Option<AccountId>,354 pub limits: Option<CollectionLimits>,355 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,356 pub meta_update_permission: Option<MetaUpdatePermission>,357 pub token_property_permissions: CollectionPropertiesPermissionsVec,358 pub properties: CollectionPropertiesVec,359}360361pub type CollectionPropertiesPermissionsVec =362 BoundedVec<PropertyKeyPermission, MaxPropertiesPermissionsEncodeLen>;363364pub type CollectionPropertiesVec =365 BoundedVec<Property, ConstU32<MAX_COLLECTION_PROPERTIES_ENCODE_LEN>>;366367/// All fields are wrapped in `Option`s, where None means chain default368#[struct_versioning::versioned(version = 2, upper)]369#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]370#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]371pub struct CollectionLimits {372 pub account_token_ownership_limit: Option<u32>,373 pub sponsored_data_size: Option<u32>,374375 /// FIXME should we delete this or repurpose it?376 /// None - setVariableMetadata is not sponsored377 /// Some(v) - setVariableMetadata is sponsored378 /// if there is v block between txs379 pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,380 pub token_limit: Option<u32>,381382 // Timeouts for item types in passed blocks383 pub sponsor_transfer_timeout: Option<u32>,384 pub sponsor_approve_timeout: Option<u32>,385 pub owner_can_transfer: Option<bool>,386 pub owner_can_destroy: Option<bool>,387 pub transfers_enabled: Option<bool>,388389 #[version(2.., upper(None))]390 pub nesting_rule: Option<NestingRule>,391}392393impl CollectionLimits {394 pub fn account_token_ownership_limit(&self) -> u32 {395 self.account_token_ownership_limit396 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)397 .min(MAX_TOKEN_OWNERSHIP)398 }399 pub fn sponsored_data_size(&self) -> u32 {400 self.sponsored_data_size401 .unwrap_or(CUSTOM_DATA_LIMIT)402 .min(CUSTOM_DATA_LIMIT)403 }404 pub fn token_limit(&self) -> u32 {405 self.token_limit406 .unwrap_or(COLLECTION_TOKEN_LIMIT)407 .min(COLLECTION_TOKEN_LIMIT)408 }409 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {410 self.sponsor_transfer_timeout411 .unwrap_or(default)412 .min(MAX_SPONSOR_TIMEOUT)413 }414 pub fn sponsor_approve_timeout(&self) -> u32 {415 self.sponsor_approve_timeout416 .unwrap_or(SPONSOR_APPROVE_TIMEOUT)417 .min(MAX_SPONSOR_TIMEOUT)418 }419 pub fn owner_can_transfer(&self) -> bool {420 self.owner_can_transfer.unwrap_or(true)421 }422 pub fn owner_can_destroy(&self) -> bool {423 self.owner_can_destroy.unwrap_or(true)424 }425 pub fn transfers_enabled(&self) -> bool {426 self.transfers_enabled.unwrap_or(true)427 }428 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {429 match self430 .sponsored_data_rate_limit431 .unwrap_or(SponsoringRateLimit::SponsoringDisabled)432 {433 SponsoringRateLimit::SponsoringDisabled => None,434 SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),435 }436 }437 pub fn nesting_rule(&self) -> &NestingRule {438 static DEFAULT: NestingRule = NestingRule::Disabled;439 self.nesting_rule.as_ref().unwrap_or(&DEFAULT)440 }441}442443#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]444#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]445#[derivative(Debug)]446pub enum NestingRule {447 /// No one can nest tokens448 Disabled,449 /// Owner can nest any tokens450 Owner,451 /// Owner can nest tokens from specified collections452 OwnerRestricted(453 #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]454 #[derivative(Debug(format_with = "bounded::set_debug"))]455 BoundedBTreeSet<CollectionId, ConstU32<16>>,456 ),457}458459#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]460#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]461pub enum SponsoringRateLimit {462 SponsoringDisabled,463 Blocks(u32),464}465466#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]467#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]468#[derivative(Debug)]469pub struct CreateNftData {470 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]471 #[derivative(Debug(format_with = "bounded::vec_debug"))]472 pub const_data: BoundedVec<u8, CustomDataLimit>,473474 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]475 #[derivative(Debug(format_with = "bounded::vec_debug"))]476 pub properties: CollectionPropertiesVec,477}478479#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]480#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]481pub struct CreateFungibleData {482 pub value: u128,483}484485#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]486#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]487#[derivative(Debug)]488pub struct CreateReFungibleData {489 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]490 #[derivative(Debug(format_with = "bounded::vec_debug"))]491 pub const_data: BoundedVec<u8, CustomDataLimit>,492 pub pieces: u128,493}494495#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]496#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]497pub enum MetaUpdatePermission {498 ItemOwner,499 Admin,500 None,501}502503impl Default for MetaUpdatePermission {504 fn default() -> Self {505 Self::ItemOwner506 }507}508509#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]510#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]511pub enum CreateItemData {512 NFT(CreateNftData),513 Fungible(CreateFungibleData),514 ReFungible(CreateReFungibleData),515}516517#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]518#[derivative(Debug)]519pub struct CreateNftExData<CrossAccountId> {520 #[derivative(Debug(format_with = "bounded::vec_debug"))]521 pub const_data: BoundedVec<u8, CustomDataLimit>,522 #[derivative(Debug(format_with = "bounded::vec_debug"))]523 pub properties: CollectionPropertiesVec,524 pub owner: CrossAccountId,525}526527#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]528#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]529pub struct CreateRefungibleExData<CrossAccountId> {530 #[derivative(Debug(format_with = "bounded::vec_debug"))]531 pub const_data: BoundedVec<u8, CustomDataLimit>,532 #[derivative(Debug(format_with = "bounded::map_debug"))]533 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,534}535536#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]537#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]538pub enum CreateItemExData<CrossAccountId> {539 NFT(540 #[derivative(Debug(format_with = "bounded::vec_debug"))]541 BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,542 ),543 Fungible(544 #[derivative(Debug(format_with = "bounded::map_debug"))]545 BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,546 ),547 /// Many tokens, each may have only one owner548 RefungibleMultipleItems(549 #[derivative(Debug(format_with = "bounded::vec_debug"))]550 BoundedVec<CreateRefungibleExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,551 ),552 /// Single token, which may have many owners553 RefungibleMultipleOwners(CreateRefungibleExData<CrossAccountId>),554}555556impl CreateItemData {557 pub fn data_size(&self) -> usize {558 match self {559 CreateItemData::NFT(data) => data.const_data.len(),560 CreateItemData::ReFungible(data) => data.const_data.len(),561 _ => 0,562 }563 }564}565566impl From<CreateNftData> for CreateItemData {567 fn from(item: CreateNftData) -> Self {568 CreateItemData::NFT(item)569 }570}571572impl From<CreateReFungibleData> for CreateItemData {573 fn from(item: CreateReFungibleData) -> Self {574 CreateItemData::ReFungible(item)575 }576}577578impl From<CreateFungibleData> for CreateItemData {579 fn from(item: CreateFungibleData) -> Self {580 CreateItemData::Fungible(item)581 }582}583584#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]585#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]586pub struct CollectionStats {587 pub created: u32,588 pub destroyed: u32,589 pub alive: u32,590}591592#[derive(Encode, Decode, PartialEq, Clone, Debug)]593pub struct PhantomType<T>(core::marker::PhantomData<T>);594595impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {596 type Identity = PhantomType<T>;597598 fn type_info() -> scale_info::Type {599 use scale_info::{600 Type, Path,601 build::{FieldsBuilder, UnnamedFields},602 type_params,603 };604 Type::builder()605 .path(Path::new("up_data_structs", "PhantomType"))606 .type_params(type_params!(T))607 .composite(<FieldsBuilder<UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()))608 }609}610impl<T> MaxEncodedLen for PhantomType<T> {611 fn max_encoded_len() -> usize {612 0613 }614}615616pub type PropertyKey = BoundedVec<u8, ConstU32<MAX_PROPERTY_KEY_LENGTH>>;617pub type PropertyValue = BoundedVec<u8, ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;618619#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]620#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]621pub struct PropertyPermission {622 pub mutable: bool,623 pub collection_admin: bool,624 pub token_owner: bool,625}626627impl PropertyPermission {628 pub fn none() -> Self {629 Self {630 mutable: true,631 collection_admin: false,632 token_owner: false,633 }634 }635}636637#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]638#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]639pub struct Property {640 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]641 pub key: PropertyKey,642643 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]644 pub value: PropertyValue,645}646647#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]648#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]649pub struct PropertyKeyPermission {650 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]651 pub key: PropertyKey,652653 pub permission: PropertyPermission,654}655656pub enum PropertiesError {657 NoSpaceForProperty,658 PropertyLimitReached,659 InvalidCharacterInPropertyKey,660 EmptyPropertyKey,661}662663pub trait TrySet: Sized {664 type Value;665666 fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError>;667668 fn try_set_from_iter<I>(&mut self, iter: I) -> Result<(), PropertiesError>669 where670 I: Iterator<Item = (PropertyKey, Self::Value)>,671 {672 for (key, value) in iter {673 self.try_set(key, value)?;674 }675676 Ok(())677 }678}679680#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]681#[derivative(Default(bound = ""))]682pub struct PropertiesMap<Value>(683 BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,684);685686impl<Value> PropertiesMap<Value> {687 pub fn new() -> Self {688 Self(BoundedBTreeMap::new())689 }690691 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {692 Self::check_property_key(key)?;693694 Ok(self.0.remove(key))695 }696697 pub fn get(&self, key: &PropertyKey) -> Option<&Value> {698 self.0.get(key)699 }700701 pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &Value)> {702 self.0.iter()703 }704705 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {706 if key.is_empty() {707 return Err(PropertiesError::EmptyPropertyKey);708 }709710 for byte in key.as_slice().iter() {711 match char::from_u32(*byte as u32) {712 Some(ch)713 if ch.is_ascii_alphanumeric()714 || ch == '_'715 || ch == '-' => { /* OK */ },716 _ => return Err(PropertiesError::InvalidCharacterInPropertyKey)717 }718 }719720 Ok(())721 }722}723724impl<Value> TrySet for PropertiesMap<Value> {725 type Value = Value;726727 fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {728 Self::check_property_key(&key)?;729730 self.0731 .try_insert(key, value)732 .map_err(|_| PropertiesError::PropertyLimitReached)?;733734 Ok(())735 }736}737738pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;739740#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, MaxEncodedLen)]741pub struct Properties {742 map: PropertiesMap<PropertyValue>,743 consumed_space: u32,744 space_limit: u32,745}746747impl Properties {748 pub fn new(space_limit: u32) -> Self {749 Self {750 map: PropertiesMap::new(),751 consumed_space: 0,752 space_limit,753 }754 }755756 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {757 let value = self.map.remove(key)?;758759 if let Some(ref value) = value {760 let value_len = value.len() as u32;761 self.consumed_space -= value_len;762 }763764 Ok(value)765 }766767 pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {768 self.map.get(key)769 }770771 pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &PropertyValue)> {772 self.map.iter()773 }774}775776impl TrySet for Properties {777 type Value = PropertyValue;778779 fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {780 let value_len = value.len();781782 if self.consumed_space as usize + value_len > self.space_limit as usize {783 return Err(PropertiesError::NoSpaceForProperty);784 }785786 self.map.try_set(key, value)?;787788 self.consumed_space += value_len as u32;789790 Ok(())791 }792}793794pub struct CollectionProperties;795796impl Get<Properties> for CollectionProperties {797 fn get() -> Properties {798 Properties::new(MAX_COLLECTION_PROPERTIES_SIZE)799 }800}801802pub struct TokenProperties;803804impl Get<Properties> for TokenProperties {805 fn get() -> Properties {806 Properties::new(MAX_TOKEN_PROPERTIES_SIZE)807 }808}primitives/rpc/src/lib.rsdiffbeforeafterboth--- a/primitives/rpc/src/lib.rs
+++ b/primitives/rpc/src/lib.rs
@@ -42,7 +42,6 @@
fn token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>>;
fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>>;
fn const_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>>;
- fn variable_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>>;
fn collection_properties(collection: CollectionId, properties: Vec<Vec<u8>>) -> Result<Vec<Property>>;
runtime/common/src/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -32,9 +32,6 @@
fn const_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>, DispatchError> {
dispatch_unique_runtime!(collection.const_metadata(token))
}
- fn variable_metadata(collection: CollectionId, token: TokenId) -> Result<Vec<u8>, DispatchError> {
- dispatch_unique_runtime!(collection.variable_metadata(token))
- }
fn collection_properties(
collection: CollectionId,
runtime/common/src/sponsoring.rsdiffbeforeafterboth--- a/runtime/common/src/sponsoring.rs
+++ b/runtime/common/src/sponsoring.rs
@@ -21,7 +21,7 @@
storage::{StorageMap, StorageDoubleMap, StorageNMap},
};
use up_data_structs::{
- CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,
+ CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId, CollectionMode,
CreateItemData,
};
@@ -30,7 +30,7 @@
use pallet_evm::account::CrossAccountId;
use pallet_unique::{
Call as UniqueCall, Config as UniqueConfig, FungibleApproveBasket, RefungibleApproveBasket,
- NftApproveBasket, VariableMetaDataBasket, CreateItemBasket, ReFungibleTransferBasket,
+ NftApproveBasket, CreateItemBasket, ReFungibleTransferBasket,
FungibleTransferBasket, NftTransferBasket,
};
use pallet_fungible::Config as FungibleConfig;
@@ -139,64 +139,7 @@
Some(())
}
-
-pub fn withdraw_set_variable_meta_data<T: Config>(
- who: &T::CrossAccountId,
- collection: &CollectionHandle<T>,
- item_id: &TokenId,
- data: &[u8],
-) -> Option<()> {
- // TODO: make it work for admins
- if collection.meta_update_permission != MetaUpdatePermission::ItemOwner {
- return None;
- }
- // preliminary sponsoring correctness check
- match collection.mode {
- CollectionMode::NFT => {
- let owner = pallet_nonfungible::TokenData::<T>::get((collection.id, item_id))?.owner;
- if !owner.conv_eq(who) {
- return None;
- }
- }
- CollectionMode::Fungible(_) => {
- if item_id != &TokenId::default() {
- return None;
- }
- if <pallet_fungible::Balance<T>>::get((collection.id, who)) == 0 {
- return None;
- }
- }
- CollectionMode::ReFungible => {
- if !<pallet_refungible::Owned<T>>::get((collection.id, who, item_id)) {
- return None;
- }
- }
- }
- // Can't sponsor fungible collection, this tx will be rejected
- // as invalid
- if matches!(collection.mode, CollectionMode::Fungible(_)) {
- return None;
- }
- if data.len() > collection.limits.sponsored_data_size() as usize {
- return None;
- }
-
- let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
- let limit = collection.limits.sponsored_data_rate_limit()?;
-
- if let Some(last_tx_block) = VariableMetaDataBasket::<T>::get(collection.id, item_id) {
- let timeout = last_tx_block + limit.into();
- if block_number < timeout {
- return None;
- }
- }
-
- <VariableMetaDataBasket<T>>::insert(collection.id, item_id, block_number);
-
- Some(())
-}
-
pub fn withdraw_approve<T: Config>(
collection: &CollectionHandle<T>,
who: &T::AccountId,
@@ -290,20 +233,6 @@
} => {
let (sponsor, collection) = load(*collection_id)?;
withdraw_approve::<T>(&collection, who, item_id).map(|()| sponsor)
- }
- UniqueCall::set_variable_meta_data {
- collection_id,
- item_id,
- data,
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_set_variable_meta_data::<T>(
- &T::CrossAccountId::from_sub(who.clone()),
- &collection,
- item_id,
- data,
- )
- .map(|()| sponsor)
}
_ => None,
}
runtime/common/src/weights.rsdiffbeforeafterboth--- a/runtime/common/src/weights.rs
+++ b/runtime/common/src/weights.rs
@@ -86,10 +86,6 @@
dispatch_weight::<T>() + max_weight_of!(transfer_from())
}
- fn set_variable_metadata(bytes: u32) -> Weight {
- dispatch_weight::<T>() + max_weight_of!(set_variable_metadata(bytes))
- }
-
fn burn_from() -> Weight {
dispatch_weight::<T>() + max_weight_of!(burn_from())
}
runtime/tests/src/tests.rsdiffbeforeafterboth--- a/runtime/tests/src/tests.rs
+++ b/runtime/tests/src/tests.rs
@@ -47,7 +47,6 @@
fn default_nft_data() -> CreateNftData {
CreateNftData {
const_data: vec![1, 2, 3].try_into().unwrap(),
- variable_data: vec![3, 2, 1].try_into().unwrap(),
}
}
@@ -58,7 +57,6 @@
fn default_re_fungible_data() -> CreateReFungibleData {
CreateReFungibleData {
const_data: vec![1, 2, 3].try_into().unwrap(),
- variable_data: vec![3, 2, 1].try_into().unwrap(),
pieces: 1023,
}
}
@@ -215,7 +213,6 @@
let item = <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1)).unwrap();
assert_eq!(item.const_data, data.const_data.into_inner());
- assert_eq!(item.variable_data, data.variable_data.into_inner());
});
}
@@ -247,7 +244,6 @@
))
.unwrap();
assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
- assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
}
});
}
@@ -263,7 +259,6 @@
let balance =
<pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));
assert_eq!(item.const_data, data.const_data.into_inner());
- assert_eq!(item.variable_data, data.variable_data.into_inner());
assert_eq!(balance, 1023);
});
}
@@ -299,7 +294,6 @@
let balance =
<pallet_refungible::Balance<Test>>::get((CollectionId(1), TokenId(1), account(1)));
assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
- assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
assert_eq!(balance, 1023);
}
});
@@ -413,7 +407,6 @@
create_test_item(collection_id, &data.clone().into());
let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));
assert_eq!(item.const_data, data.const_data.into_inner());
- assert_eq!(item.variable_data, data.variable_data.into_inner());
assert_eq!(
<pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),
1
@@ -2427,117 +2420,6 @@
}
#[test]
-fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let origin1 = Origin::signed(1);
-
- let data = default_nft_data();
- create_test_item(CollectionId(1), &data.into());
-
- let variable_data = b"test data".to_vec();
- assert_ok!(Unique::set_variable_meta_data(
- origin1,
- collection_id,
- TokenId(1),
- variable_data.clone().try_into().unwrap()
- ));
-
- assert_eq!(
- <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))
- .unwrap()
- .variable_data,
- variable_data
- );
- });
-}
-
-#[test]
-fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
- let origin1 = Origin::signed(1);
-
- let data = default_re_fungible_data();
- create_test_item(collection_id, &data.into());
-
- let variable_data = b"test data".to_vec();
- assert_ok!(Unique::set_variable_meta_data(
- origin1,
- collection_id,
- TokenId(1),
- variable_data.clone().try_into().unwrap()
- ));
-
- assert_eq!(
- <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1))).variable_data,
- variable_data
- );
- });
-}
-
-#[test]
-fn set_variable_meta_data_on_fungible_token_fails() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
- let origin1 = Origin::signed(1);
-
- let data = default_fungible_data();
- create_test_item(collection_id, &data.into());
-
- let variable_data = b"test data".to_vec();
- assert_noop!(
- Unique::set_variable_meta_data(
- origin1,
- collection_id,
- TokenId(0),
- variable_data.try_into().unwrap()
- )
- .map_err(|e| e.error),
- <pallet_fungible::Error<Test>>::FungibleItemsDontHaveData
- );
- });
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_item_owner_permission_flag() {
- new_test_ext().execute_with(|| {
- //default_limits();
-
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let origin1 = Origin::signed(1);
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
-
- assert_ok!(Unique::set_meta_update_permission_flag(
- origin1.clone(),
- collection_id,
- MetaUpdatePermission::ItemOwner,
- ));
-
- let variable_data = b"ten chars.".to_vec();
- assert_ok!(Unique::set_variable_meta_data(
- origin1,
- collection_id,
- TokenId(1),
- variable_data.clone().try_into().unwrap()
- ));
-
- assert_eq!(
- <pallet_nonfungible::TokenData<Test>>::get((collection_id, TokenId(1)))
- .unwrap()
- .variable_data,
- variable_data
- );
- });
-}
-
-#[test]
fn collection_transfer_flag_works() {
new_test_ext().execute_with(|| {
let origin1 = Origin::signed(1);
@@ -2590,105 +2472,6 @@
}
#[test]
-fn set_variable_meta_data_on_nft_with_admin_flag() {
- new_test_ext().execute_with(|| {
- // default_limits();
-
- let collection_id =
- create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));
-
- let origin1 = Origin::signed(1);
- let origin2 = Origin::signed(2);
-
- assert_ok!(Unique::set_mint_permission(
- origin2.clone(),
- collection_id,
- true
- ));
- assert_ok!(Unique::add_to_allow_list(
- origin2.clone(),
- collection_id,
- account(1)
- ));
-
- assert_ok!(Unique::add_collection_admin(
- origin2.clone(),
- collection_id,
- account(1)
- ));
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
-
- assert_ok!(Unique::set_meta_update_permission_flag(
- origin2.clone(),
- collection_id,
- MetaUpdatePermission::Admin,
- ));
-
- let variable_data = b"test.".to_vec();
- assert_ok!(Unique::set_variable_meta_data(
- origin1,
- collection_id,
- TokenId(1),
- variable_data.clone().try_into().unwrap()
- ));
-
- assert_eq!(
- <pallet_nonfungible::TokenData<Test>>::get((collection_id, 1))
- .unwrap()
- .variable_data,
- variable_data
- );
- });
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_admin_flag_neg() {
- new_test_ext().execute_with(|| {
- // default_limits();
-
- let collection_id =
- create_test_collection_for_owner(&CollectionMode::NFT, 2, CollectionId(1));
-
- let origin1 = Origin::signed(1);
- let origin2 = Origin::signed(2);
-
- assert_ok!(Unique::set_mint_permission(
- origin2.clone(),
- collection_id,
- true
- ));
- assert_ok!(Unique::add_to_allow_list(
- origin2.clone(),
- collection_id,
- account(1)
- ));
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
-
- assert_ok!(Unique::set_meta_update_permission_flag(
- origin2.clone(),
- collection_id,
- MetaUpdatePermission::Admin,
- ));
-
- let variable_data = b"test.".to_vec();
- assert_noop!(
- Unique::set_variable_meta_data(
- origin1,
- collection_id,
- TokenId(1),
- variable_data.try_into().unwrap()
- )
- .map_err(|e| e.error),
- CommonError::<Test>::NoPermission
- );
- });
-}
-
-#[test]
fn set_variable_meta_flag_after_freeze() {
new_test_ext().execute_with(|| {
// default_limits();
@@ -2710,38 +2493,6 @@
MetaUpdatePermission::Admin
),
CommonError::<Test>::MetadataFlagFrozen
- );
- });
-}
-
-#[test]
-fn set_variable_meta_data_on_nft_with_none_flag_neg() {
- new_test_ext().execute_with(|| {
- // default_limits();
-
- let collection_id =
- create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));
- let origin1 = Origin::signed(1);
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
-
- assert_ok!(Unique::set_meta_update_permission_flag(
- origin1.clone(),
- collection_id,
- MetaUpdatePermission::None,
- ));
-
- let variable_data = b"test.".to_vec();
- assert_noop!(
- Unique::set_variable_meta_data(
- origin1.clone(),
- collection_id,
- TokenId(1),
- variable_data.try_into().unwrap()
- )
- .map_err(|e| e.error),
- CommonError::<Test>::NoPermission
);
});
}
smart_contracs/transfer/lib.rsdiffbeforeafterboth--- a/smart_contracs/transfer/lib.rs
+++ b/smart_contracs/transfer/lib.rs
@@ -58,14 +58,12 @@
pub enum CreateItemData {
Nft {
const_data: Vec<u8>,
- variable_data: Vec<u8>,
},
Fungible {
value: u128,
},
ReFungible {
const_data: Vec<u8>,
- variable_data: Vec<u8>,
pieces: u128,
},
}
@@ -88,8 +86,6 @@
fn approve(spender: DefaultAccountId, collection_id: u32, item_id: u32, amount: u128);
#[ink(extension = 4, returns_result = false)]
fn transfer_from(owner: DefaultAccountId, recipient: DefaultAccountId, collection_id: u32, item_id: u32, amount: u128);
- #[ink(extension = 5, returns_result = false)]
- fn set_variable_meta_data(collection_id: u32, item_id: u32, data: Vec<u8>);
#[ink(extension = 6, returns_result = false)]
fn toggle_allow_list(collection_id: u32, address: DefaultAccountId, allowlisted: bool);
}
@@ -143,12 +139,6 @@
let _ = self.env()
.extension()
.transfer_from(owner, recipient, collection_id, item_id, amount);
- }
- #[ink(message)]
- pub fn set_variable_meta_data(&mut self, collection_id: u32, item_id: u32, data: Vec<u8>) {
- let _ = self.env()
- .extension()
- .set_variable_meta_data(collection_id, item_id, data);
}
#[ink(message)]
pub fn toggle_allow_list(&mut self, collection_id: u32, address: AccountId, allowlisted: bool) {