difftreelog
feat check nesting rule
in: master
10 files changed
pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-use up_data_structs::{CollectionId, TokenId};
+use up_data_structs::CollectionId;
use sp_core::H160;
// 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 1
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -345,6 +345,13 @@
/// Not sufficient founds to perform action
NotSufficientFounds,
+
+ /// Collection has nesting disabled
+ NestingIsDisabled,
+ /// Only owner may nest tokens under this collection
+ OnlyOwnerAllowedToNest,
+ /// Only tokens from specific collections may nest tokens under this
+ SourceCollectionIsNotAllowedToNest,
}
#[pallet::storage]
@@ -400,8 +407,6 @@
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_runtime_upgrade() -> Weight {
- let mut weight = 0;
-
if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {
use up_data_structs::{CollectionVersion1, CollectionVersion2};
<CollectionById<T>>::translate_values::<CollectionVersion1<T::AccountId>, _>(|v| {
@@ -409,7 +414,7 @@
});
}
- weight
+ 0
}
}
}
@@ -774,6 +779,13 @@
data: BoundedVec<u8, CustomDataLimit>,
) -> DispatchResultWithPostInfo;
+ fn nest_token(
+ &self,
+ sender: T::CrossAccountId,
+ from: (CollectionId, TokenId),
+ under: TokenId,
+ ) -> DispatchResult;
+
fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;
fn token_exists(&self, token: TokenId) -> bool;
fn last_token_id(&self) -> TokenId;
pallets/fungible/src/common.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/>.1617use core::marker::PhantomData;1819use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};20use up_data_structs::{TokenId, CreateItemExData};21use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};22use sp_runtime::ArithmeticError;23use sp_std::{vec::Vec, vec};24use up_data_structs::CustomDataLimit;2526use crate::{27 Allowance, Balance, Config, Error, FungibleHandle, Pallet, SelfWeightOf, weights::WeightInfo,28};2930pub struct CommonWeights<T: Config>(PhantomData<T>);31impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {32 fn create_item() -> Weight {33 <SelfWeightOf<T>>::create_item()34 }3536 fn create_multiple_items(_amount: u32) -> Weight {37 Self::create_item()38 }3940 fn create_multiple_items_ex(data: &CreateItemExData<T::CrossAccountId>) -> Weight {41 match data {42 CreateItemExData::Fungible(f) => {43 <SelfWeightOf<T>>::create_multiple_items_ex(f.len() as u32)44 }45 _ => 0,46 }47 }4849 fn burn_item() -> Weight {50 <SelfWeightOf<T>>::burn_item()51 }5253 fn transfer() -> Weight {54 <SelfWeightOf<T>>::transfer()55 }5657 fn approve() -> Weight {58 <SelfWeightOf<T>>::approve()59 }6061 fn transfer_from() -> Weight {62 <SelfWeightOf<T>>::transfer_from()63 }6465 fn burn_from() -> Weight {66 <SelfWeightOf<T>>::burn_from()67 }6869 fn set_variable_metadata(_bytes: u32) -> Weight {70 // Error71 072 }73}7475impl<T: Config> CommonCollectionOperations<T> for FungibleHandle<T> {76 fn create_item(77 &self,78 sender: T::CrossAccountId,79 to: T::CrossAccountId,80 data: up_data_structs::CreateItemData,81 ) -> DispatchResultWithPostInfo {82 match data {83 up_data_structs::CreateItemData::Fungible(data) => with_weight(84 <Pallet<T>>::create_item(self, &sender, (to, data.value)),85 <CommonWeights<T>>::create_item(),86 ),87 _ => fail!(<Error<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),88 }89 }9091 fn create_multiple_items(92 &self,93 sender: T::CrossAccountId,94 to: T::CrossAccountId,95 data: Vec<up_data_structs::CreateItemData>,96 ) -> DispatchResultWithPostInfo {97 let mut sum: u128 = 0;98 for data in data {99 match data {100 up_data_structs::CreateItemData::Fungible(data) => {101 sum = sum102 .checked_add(data.value)103 .ok_or(ArithmeticError::Overflow)?;104 }105 _ => fail!(<Error<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),106 }107 }108109 with_weight(110 <Pallet<T>>::create_item(self, &sender, (to, sum)),111 <CommonWeights<T>>::create_item(),112 )113 }114115 fn create_multiple_items_ex(116 &self,117 sender: <T>::CrossAccountId,118 data: up_data_structs::CreateItemExData<<T>::CrossAccountId>,119 ) -> DispatchResultWithPostInfo {120 let weight = <CommonWeights<T>>::create_multiple_items_ex(&data);121 let data = match data {122 up_data_structs::CreateItemExData::Fungible(f) => f,123 _ => fail!(<Error<T>>::NotFungibleDataUsedToMintFungibleCollectionToken),124 };125126 with_weight(127 <Pallet<T>>::create_multiple_items(self, &sender, data.into_inner()),128 weight,129 )130 }131132 fn burn_item(133 &self,134 sender: T::CrossAccountId,135 token: TokenId,136 amount: u128,137 ) -> DispatchResultWithPostInfo {138 ensure!(139 token == TokenId::default(),140 <Error<T>>::FungibleItemsHaveNoId141 );142143 with_weight(144 <Pallet<T>>::burn(self, &sender, amount),145 <CommonWeights<T>>::burn_item(),146 )147 }148149 fn transfer(150 &self,151 from: T::CrossAccountId,152 to: T::CrossAccountId,153 token: TokenId,154 amount: u128,155 ) -> DispatchResultWithPostInfo {156 ensure!(157 token == TokenId::default(),158 <Error<T>>::FungibleItemsHaveNoId159 );160161 with_weight(162 <Pallet<T>>::transfer(self, &from, &to, amount),163 <CommonWeights<T>>::transfer(),164 )165 }166167 fn approve(168 &self,169 sender: T::CrossAccountId,170 spender: T::CrossAccountId,171 token: TokenId,172 amount: u128,173 ) -> DispatchResultWithPostInfo {174 ensure!(175 token == TokenId::default(),176 <Error<T>>::FungibleItemsHaveNoId177 );178179 with_weight(180 <Pallet<T>>::set_allowance(self, &sender, &spender, amount),181 <CommonWeights<T>>::approve(),182 )183 }184185 fn transfer_from(186 &self,187 sender: T::CrossAccountId,188 from: T::CrossAccountId,189 to: T::CrossAccountId,190 token: TokenId,191 amount: u128,192 ) -> DispatchResultWithPostInfo {193 ensure!(194 token == TokenId::default(),195 <Error<T>>::FungibleItemsHaveNoId196 );197198 with_weight(199 <Pallet<T>>::transfer_from(self, &sender, &from, &to, amount),200 <CommonWeights<T>>::transfer_from(),201 )202 }203204 fn burn_from(205 &self,206 sender: T::CrossAccountId,207 from: T::CrossAccountId,208 token: TokenId,209 amount: u128,210 ) -> DispatchResultWithPostInfo {211 ensure!(212 token == TokenId::default(),213 <Error<T>>::FungibleItemsHaveNoId214 );215216 with_weight(217 <Pallet<T>>::burn_from(self, &sender, &from, amount),218 <CommonWeights<T>>::burn_from(),219 )220 }221222 fn set_variable_metadata(223 &self,224 _sender: T::CrossAccountId,225 _token: TokenId,226 _data: BoundedVec<u8, CustomDataLimit>,227 ) -> DispatchResultWithPostInfo {228 fail!(<Error<T>>::FungibleItemsDontHaveData)229 }230231 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {232 if <Balance<T>>::get((self.id, account)) != 0 {233 vec![TokenId::default()]234 } else {235 vec![]236 }237 }238239 fn token_exists(&self, token: TokenId) -> bool {240 token == TokenId::default()241 }242243 fn last_token_id(&self) -> TokenId {244 TokenId::default()245 }246247 fn token_owner(&self, _token: TokenId) -> Option<T::CrossAccountId> {248 None249 }250 fn const_metadata(&self, _token: TokenId) -> Vec<u8> {251 Vec::new()252 }253 fn variable_metadata(&self, _token: TokenId) -> Vec<u8> {254 Vec::new()255 }256257 fn collection_tokens(&self) -> u32 {258 1259 }260261 fn account_balance(&self, account: T::CrossAccountId) -> u32 {262 if <Balance<T>>::get((self.id, account)) != 0 {263 1264 } else {265 0266 }267 }268269 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {270 if token != TokenId::default() {271 return 0;272 }273 <Balance<T>>::get((self.id, account))274 }275276 fn allowance(277 &self,278 sender: T::CrossAccountId,279 spender: T::CrossAccountId,280 token: TokenId,281 ) -> u128 {282 if token != TokenId::default() {283 return 0;284 }285 <Allowance<T>>::get((self.id, sender, spender))286 }287}pallets/fungible/src/lib.rsdiffbeforeafterboth--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -18,9 +18,14 @@
use core::ops::Deref;
use frame_support::{ensure};
-use up_data_structs::{AccessMode, CollectionId, TokenId, CreateCollectionData};
-use pallet_common::{Error as CommonError, Event as CommonEvent, Pallet as PalletCommon};
use pallet_evm::account::CrossAccountId;
+use up_data_structs::{
+ AccessMode, CollectionId, TokenId, CreateCollectionData, mapping::TokenAddressMapping,
+};
+use pallet_common::{
+ Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,
+ CollectionHandle, dispatch::CollectionDispatch,
+};
use pallet_evm_coder_substrate::WithRecorder;
use sp_core::H160;
use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
@@ -52,6 +57,8 @@
FungibleItemsHaveNoId,
/// Tried to set data for fungible item
FungibleItemsDontHaveData,
+ /// Fungible token does not support nested
+ FungibleDisallowsNesting,
}
#[pallet::config]
@@ -207,7 +214,15 @@
None
};
- // =========
+ if let Some(target) = T::CrossTokenAddressMapping::address_to_token(to) {
+ let handle = <CollectionHandle<T>>::try_get(target.0)?;
+ let dispatch = T::CollectionDispatch::dispatch(handle);
+ let dispatch = dispatch.as_dyn();
+
+ // =========
+
+ dispatch.nest_token(from.clone(), (collection.id, TokenId::default()), target.1)?;
+ }
if let Some(balance_to) = balance_to {
// from != to
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -17,7 +17,7 @@
use core::marker::PhantomData;
use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, BoundedVec};
-use up_data_structs::{TokenId, CustomDataLimit, CreateItemExData};
+use up_data_structs::{TokenId, CustomDataLimit, CreateItemExData, CollectionId};
use pallet_common::{CommonCollectionOperations, CommonWeightInfo, with_weight};
use sp_runtime::DispatchError;
use sp_std::vec::Vec;
@@ -237,6 +237,15 @@
)
}
+ fn nest_token(
+ &self,
+ sender: T::CrossAccountId,
+ (from, _): (CollectionId, TokenId),
+ under: TokenId,
+ ) -> sp_runtime::DispatchResult {
+ <Pallet<T>>::nest_token(self, sender, from, under)
+ }
+
fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {
<Owned<T>>::iter_prefix((self.id, account))
.map(|(id, _)| id)
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -17,12 +17,16 @@
#![cfg_attr(not(feature = "std"), no_std)]
use erc::ERC721Events;
-use frame_support::{BoundedVec, ensure};
+use frame_support::{BoundedVec, ensure, fail};
use up_data_structs::{
AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData, CreateNftExData,
+ mapping::TokenAddressMapping, NestingRule,
};
-use pallet_common::{Error as CommonError, Pallet as PalletCommon, Event as CommonEvent};
use pallet_evm::account::CrossAccountId;
+use pallet_common::{
+ Error as CommonError, Pallet as PalletCommon, Event as CommonEvent,
+ CollectionHandle, dispatch::CollectionDispatch,
+};
use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
use sp_core::H160;
use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
@@ -282,8 +286,16 @@
None
};
- // =========
+ if let Some(target) = T::CrossTokenAddressMapping::address_to_token(to) {
+ let handle = <CollectionHandle<T>>::try_get(target.0)?;
+ let dispatch = T::CollectionDispatch::dispatch(handle);
+ let dispatch = dispatch.as_dyn();
+
+ // =========
+ dispatch.nest_token(from.clone(), (collection.id, token), target.1)?;
+ }
+
<TokenData<T>>::insert(
(collection.id, token),
ItemData {
@@ -567,6 +579,40 @@
Ok(())
}
+ pub fn nest_token(
+ handle: &NonfungibleHandle<T>,
+ sender: T::CrossAccountId,
+ from: CollectionId,
+ under: TokenId,
+ ) -> DispatchResult {
+ fn ensure_sender_allowed<T: Config>(
+ collection: CollectionId,
+ token: TokenId,
+ sender: T::CrossAccountId,
+ ) -> DispatchResult {
+ ensure!(
+ <TokenData<T>>::get((collection, token))
+ .ok_or(<CommonError<T>>::TokenNotFound)?
+ .owner
+ .conv_eq(&sender),
+ <CommonError<T>>::OnlyOwnerAllowedToNest,
+ );
+ Ok(())
+ }
+ match handle.limits.nesting_rule() {
+ NestingRule::Disabled => fail!(<CommonError<T>>::NestingIsDisabled),
+ NestingRule::Owner => ensure_sender_allowed::<T>(from, under, sender)?,
+ NestingRule::OwnerRestricted(whitelist) => {
+ ensure!(
+ whitelist.contains(&from),
+ <CommonError<T>>::SourceCollectionIsNotAllowedToNest
+ );
+ ensure_sender_allowed::<T>(from, under, sender)?
+ }
+ }
+ Ok(())
+ }
+
/// Delegated to `create_multiple_items`
pub fn create_item(
collection: &NonfungibleHandle<T>,
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -243,6 +243,15 @@
)
}
+ fn nest_token(
+ &self,
+ _sender: <T>::CrossAccountId,
+ _from: (up_data_structs::CollectionId, TokenId),
+ _under: TokenId,
+ ) -> sp_runtime::DispatchResult {
+ fail!(<Error<T>>::RefungibleDisallowsNesting)
+ }
+
fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {
<Owned<T>>::iter_prefix((self.id, account))
.map(|(id, _)| id)
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -19,10 +19,13 @@
use frame_support::{ensure, BoundedVec};
use up_data_structs::{
AccessMode, CollectionId, CustomDataLimit, MAX_REFUNGIBLE_PIECES, TokenId,
- CreateCollectionData, CreateRefungibleExData,
+ CreateCollectionData, CreateRefungibleExData, mapping::TokenAddressMapping,
};
-use pallet_common::{Error as CommonError, Event as CommonEvent, Pallet as PalletCommon};
use pallet_evm::account::CrossAccountId;
+use pallet_common::{
+ Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,
+ CollectionHandle, dispatch::CollectionDispatch,
+};
use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
use core::ops::Deref;
@@ -56,6 +59,8 @@
NotRefungibleDataUsedToMintFungibleCollectionToken,
/// Maximum refungibility exceeded
WrongRefungiblePieces,
+ /// Refungible token can't nest other tokens
+ RefungibleDisallowsNesting,
}
#[pallet::config]
@@ -338,7 +343,15 @@
None
};
- // =========
+ if let Some(target) = T::CrossTokenAddressMapping::address_to_token(to) {
+ let handle = <CollectionHandle<T>>::try_get(target.0)?;
+ let dispatch = T::CollectionDispatch::dispatch(handle);
+ let dispatch = dispatch.as_dyn();
+
+ // =========
+
+ dispatch.nest_token(from.clone(), (collection.id, token), target.1)?;
+ }
if let Some(balance_to) = balance_to {
// from != to
primitives/data-structs/src/bounded.rsdiffbeforeafterboth--- /dev/null
+++ b/primitives/data-structs/src/bounded.rs
@@ -0,0 +1,138 @@
+use core::fmt;
+use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet};
+use sp_std::vec::Vec;
+
+use frame_support::{
+ BoundedVec,
+ storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},
+};
+
+/// BoundedVec doesn't supports serde
+#[cfg(feature = "serde1")]
+pub mod vec_serde {
+ use core::convert::TryFrom;
+ use frame_support::{BoundedVec, traits::Get};
+ use serde::{
+ ser::{self, Serialize},
+ de::{self, Deserialize, Error},
+ };
+ use sp_std::vec::Vec;
+
+ pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>
+ where
+ D: ser::Serializer,
+ V: Serialize,
+ {
+ (value as &Vec<_>).serialize(serializer)
+ }
+
+ pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ V: de::Deserialize<'de>,
+ S: Get<u32>,
+ {
+ // TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec?
+ let vec = <Vec<V>>::deserialize(deserializer)?;
+ let len = vec.len();
+ TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))
+ }
+}
+
+pub fn vec_debug<V, S>(v: &BoundedVec<V, S>, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
+where
+ V: fmt::Debug,
+{
+ use core::fmt::Debug;
+ (&v as &Vec<V>).fmt(f)
+}
+
+#[cfg(feature = "serde1")]
+#[allow(dead_code)]
+pub mod map_serde {
+ use core::convert::TryFrom;
+ use sp_std::collections::btree_map::BTreeMap;
+ use frame_support::{traits::Get, storage::bounded_btree_map::BoundedBTreeMap};
+ use serde::{
+ ser::{self, Serialize},
+ de::{self, Deserialize, Error},
+ };
+ pub fn serialize<D, K, V, S>(
+ value: &BoundedBTreeMap<K, V, S>,
+ serializer: D,
+ ) -> Result<D::Ok, D::Error>
+ where
+ D: ser::Serializer,
+ K: Serialize + Ord,
+ V: Serialize,
+ {
+ (value as &BTreeMap<_, _>).serialize(serializer)
+ }
+
+ pub fn deserialize<'de, D, K, V, S>(
+ deserializer: D,
+ ) -> Result<BoundedBTreeMap<K, V, S>, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ K: de::Deserialize<'de> + Ord,
+ V: de::Deserialize<'de>,
+ S: Get<u32>,
+ {
+ let map = <BTreeMap<K, V>>::deserialize(deserializer)?;
+ let len = map.len();
+ TryFrom::try_from(map).map_err(|_| D::Error::invalid_length(len, &"lesser size"))
+ }
+}
+
+pub fn map_debug<K, V, S>(
+ v: &BoundedBTreeMap<K, V, S>,
+ f: &mut fmt::Formatter,
+) -> Result<(), fmt::Error>
+where
+ K: fmt::Debug + Ord,
+ V: fmt::Debug,
+{
+ use core::fmt::Debug;
+ (&v as &BTreeMap<K, V>).fmt(f)
+}
+
+#[cfg(feature = "serde1")]
+#[allow(dead_code)]
+pub mod set_serde {
+ use core::convert::TryFrom;
+ use sp_std::collections::btree_set::BTreeSet;
+ use frame_support::{traits::Get, storage::bounded_btree_set::BoundedBTreeSet};
+ use serde::{
+ ser::{self, Serialize},
+ de::{self, Deserialize, Error},
+ };
+ pub fn serialize<D, K, S>(
+ value: &BoundedBTreeSet<K, S>,
+ serializer: D,
+ ) -> Result<D::Ok, D::Error>
+ where
+ D: ser::Serializer,
+ K: Serialize + Ord,
+ {
+ (value as &BTreeSet<_>).serialize(serializer)
+ }
+
+ pub fn deserialize<'de, D, K, S>(deserializer: D) -> Result<BoundedBTreeSet<K, S>, D::Error>
+ where
+ D: de::Deserializer<'de>,
+ K: de::Deserialize<'de> + Ord,
+ S: Get<u32>,
+ {
+ let map = <BTreeSet<K>>::deserialize(deserializer)?;
+ let len = map.len();
+ TryFrom::try_from(map).map_err(|_| D::Error::invalid_length(len, &"lesser size"))
+ }
+}
+
+pub fn set_debug<K, S>(v: &BoundedBTreeSet<K, S>, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
+where
+ K: fmt::Debug + Ord,
+{
+ use core::fmt::Debug;
+ (&v as &BTreeSet<K>).fmt(f)
+}
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -22,9 +22,7 @@
};
use frame_support::{
storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},
- traits::ConstU16,
};
-use sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet};
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
@@ -36,6 +34,7 @@
use derivative::Derivative;
use scale_info::TypeInfo;
+mod bounded;
pub mod mapping;
mod migration;
@@ -255,14 +254,14 @@
pub owner: AccountId,
pub mode: CollectionMode,
pub access: AccessMode,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,
pub mint_mode: bool,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,
pub schema_version: SchemaVersion,
pub sponsorship: SponsorshipState<AccountId>,
@@ -272,9 +271,9 @@
#[version(2.., upper(limits.into()))]
pub limits: CollectionLimitsVersion2,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,
pub meta_update_permission: MetaUpdatePermission,
}
@@ -286,20 +285,20 @@
#[derivative(Default(value = "CollectionMode::NFT"))]
pub mode: CollectionMode,
pub access: Option<AccessMode>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,
pub schema_version: Option<SchemaVersion>,
pub pending_sponsor: Option<AccountId>,
pub limits: Option<CollectionLimits>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,
pub meta_update_permission: Option<MetaUpdatePermission>,
}
@@ -410,8 +409,8 @@
Owner,
/// Owner can nest tokens from specified collections
OwnerRestricted(
- #[cfg_attr(feature = "serde1", serde(with = "bounded_set_serde"))]
- #[derivative(Debug(format_with = "bounded_set_debug"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]
+ #[derivative(Debug(format_with = "bounded::set_debug"))]
BoundedBTreeSet<CollectionId, ConstU32<16>>,
),
}
@@ -421,150 +420,17 @@
pub enum SponsoringRateLimit {
SponsoringDisabled,
Blocks(u32),
-}
-
-/// BoundedVec doesn't supports serde
-#[cfg(feature = "serde1")]
-mod bounded_serde {
- use core::convert::TryFrom;
- use frame_support::{BoundedVec, traits::Get};
- use serde::{
- ser::{self, Serialize},
- de::{self, Deserialize, Error},
- };
- use sp_std::vec::Vec;
-
- pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>
- where
- D: ser::Serializer,
- V: Serialize,
- {
- (value as &Vec<_>).serialize(serializer)
- }
-
- pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>
- where
- D: de::Deserializer<'de>,
- V: de::Deserialize<'de>,
- S: Get<u32>,
- {
- // TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec?
- let vec = <Vec<V>>::deserialize(deserializer)?;
- let len = vec.len();
- TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))
- }
-}
-
-fn bounded_debug<V, S>(v: &BoundedVec<V, S>, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
-where
- V: fmt::Debug,
-{
- use core::fmt::Debug;
- (&v as &Vec<V>).fmt(f)
-}
-
-#[cfg(feature = "serde1")]
-#[allow(dead_code)]
-mod bounded_map_serde {
- use core::convert::TryFrom;
- use sp_std::collections::btree_map::BTreeMap;
- use frame_support::{traits::Get, storage::bounded_btree_map::BoundedBTreeMap};
- use serde::{
- ser::{self, Serialize},
- de::{self, Deserialize, Error},
- };
- pub fn serialize<D, K, V, S>(
- value: &BoundedBTreeMap<K, V, S>,
- serializer: D,
- ) -> Result<D::Ok, D::Error>
- where
- D: ser::Serializer,
- K: Serialize + Ord,
- V: Serialize,
- {
- (value as &BTreeMap<_, _>).serialize(serializer)
- }
-
- pub fn deserialize<'de, D, K, V, S>(
- deserializer: D,
- ) -> Result<BoundedBTreeMap<K, V, S>, D::Error>
- where
- D: de::Deserializer<'de>,
- K: de::Deserialize<'de> + Ord,
- V: de::Deserialize<'de>,
- S: Get<u32>,
- {
- let map = <BTreeMap<K, V>>::deserialize(deserializer)?;
- let len = map.len();
- TryFrom::try_from(map).map_err(|_| D::Error::invalid_length(len, &"lesser size"))
- }
-}
-
-fn bounded_map_debug<K, V, S>(
- v: &BoundedBTreeMap<K, V, S>,
- f: &mut fmt::Formatter,
-) -> Result<(), fmt::Error>
-where
- K: fmt::Debug + Ord,
- V: fmt::Debug,
-{
- use core::fmt::Debug;
- (&v as &BTreeMap<K, V>).fmt(f)
-}
-
-#[cfg(feature = "serde1")]
-#[allow(dead_code)]
-mod bounded_set_serde {
- use core::convert::TryFrom;
- use sp_std::collections::btree_set::BTreeSet;
- use frame_support::{traits::Get, storage::bounded_btree_set::BoundedBTreeSet};
- use serde::{
- ser::{self, Serialize},
- de::{self, Deserialize, Error},
- };
- pub fn serialize<D, K, S>(
- value: &BoundedBTreeSet<K, S>,
- serializer: D,
- ) -> Result<D::Ok, D::Error>
- where
- D: ser::Serializer,
- K: Serialize + Ord,
- {
- (value as &BTreeSet<_>).serialize(serializer)
- }
-
- pub fn deserialize<'de, D, K, S>(deserializer: D) -> Result<BoundedBTreeSet<K, S>, D::Error>
- where
- D: de::Deserializer<'de>,
- K: de::Deserialize<'de> + Ord,
- S: Get<u32>,
- {
- let map = <BTreeSet<K>>::deserialize(deserializer)?;
- let len = map.len();
- TryFrom::try_from(map).map_err(|_| D::Error::invalid_length(len, &"lesser size"))
- }
}
-fn bounded_set_debug<K, S>(
- v: &BoundedBTreeSet<K, S>,
- f: &mut fmt::Formatter,
-) -> Result<(), fmt::Error>
-where
- K: fmt::Debug + Ord,
-{
- use core::fmt::Debug;
- (&v as &BTreeSet<K>).fmt(f)
-}
-
#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
#[derivative(Debug)]
pub struct CreateNftData {
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
pub const_data: BoundedVec<u8, CustomDataLimit>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
pub variable_data: BoundedVec<u8, CustomDataLimit>,
}
@@ -578,11 +444,11 @@
#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
#[derivative(Debug)]
pub struct CreateReFungibleData {
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
pub const_data: BoundedVec<u8, CustomDataLimit>,
- #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
pub variable_data: BoundedVec<u8, CustomDataLimit>,
pub pieces: u128,
}
@@ -612,9 +478,9 @@
#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
#[derivative(Debug)]
pub struct CreateNftExData<CrossAccountId> {
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
pub const_data: BoundedVec<u8, CustomDataLimit>,
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
pub variable_data: BoundedVec<u8, CustomDataLimit>,
pub owner: CrossAccountId,
}
@@ -622,11 +488,11 @@
#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]
pub struct CreateRefungibleExData<CrossAccountId> {
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
pub const_data: BoundedVec<u8, CustomDataLimit>,
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
pub variable_data: BoundedVec<u8, CustomDataLimit>,
- #[derivative(Debug(format_with = "bounded_map_debug"))]
+ #[derivative(Debug(format_with = "bounded::map_debug"))]
pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
}
@@ -634,16 +500,16 @@
#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]
pub enum CreateItemExData<CrossAccountId> {
NFT(
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,
),
Fungible(
- #[derivative(Debug(format_with = "bounded_map_debug"))]
+ #[derivative(Debug(format_with = "bounded::map_debug"))]
BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
),
/// Many tokens, each may have only one owner
RefungibleMultipleItems(
- #[derivative(Debug(format_with = "bounded_debug"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
BoundedVec<CreateRefungibleExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,
),
/// Single token, which may have many owners