difftreelog
refactor move ChainLimits to runtime config
in: master
6 files changed
node/cli/src/chain_spec.rsdiffbeforeafterboth--- a/node/cli/src/chain_spec.rs
+++ b/node/cli/src/chain_spec.rs
@@ -202,18 +202,6 @@
nft_item_id: vec![],
fungible_item_id: vec![],
refungible_item_id: vec![],
- chain_limit: ChainLimits {
- collection_numbers_limit: 100000,
- account_token_ownership_limit: 1000000,
- collections_admins_limit: 5,
- custom_data_limit: 2048,
- nft_sponsor_transfer_timeout: 15,
- fungible_sponsor_transfer_timeout: 15,
- refungible_sponsor_transfer_timeout: 15,
- offchain_schema_limit: 1024,
- variable_on_chain_schema_limit: 1024,
- const_on_chain_schema_limit: 1024,
- },
},
parachain_info: nft_runtime::ParachainInfoConfig { parachain_id: id },
aura: nft_runtime::AuraConfig {
pallets/nft/src/eth/sponsoring.rsdiffbeforeafterboth--- a/pallets/nft/src/eth/sponsoring.rs
+++ b/pallets/nft/src/eth/sponsoring.rs
@@ -1,12 +1,13 @@
//! Implements EVM sponsoring logic via OnChargeEVMTransaction
use crate::{
- ChainLimit, Collection, CollectionById, Config, FungibleTransferBasket, NftTransferBasket,
- eth::{account::EvmBackwardsAddressMapping, map_eth_to_id},
+ Collection, CollectionById, Config, FungibleTransferBasket, NftTransferBasket,
+ eth::{account::EvmBackwardsAddressMapping, map_eth_to_id}, limit,
};
use evm_coder::{Call, abi::AbiReader};
use frame_support::{
- storage::{StorageMap, StorageDoubleMap, StorageValue},
+ storage::{StorageMap, StorageDoubleMap},
+ traits::Get,
};
use sp_core::H160;
use sp_std::prelude::*;
@@ -43,7 +44,7 @@
let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
collection_limits.sponsor_transfer_timeout
} else {
- ChainLimit::get().nft_sponsor_transfer_timeout
+ <limit!(T, NftSponsorTransferTimeout)>::get()
};
let mut sponsor = true;
@@ -74,7 +75,7 @@
let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
collection_limits.sponsor_transfer_timeout
} else {
- ChainLimit::get().fungible_sponsor_transfer_timeout
+ <limit!(T, FungibleSponsorTransferTimeout)>::get()
};
let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -31,7 +31,7 @@
StorageValue, transactional,
};
-use frame_system::{self as system, ensure_signed, ensure_root};
+use frame_system::{self as system, ensure_signed};
use sp_core::H160;
use sp_std::vec;
use sp_runtime::sp_std::prelude::Vec;
@@ -243,6 +243,15 @@
<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,
>;
type TreasuryAccountId: Get<Self::AccountId>;
+ type ChainLimits: ChainLimits;
+}
+
+pub type ChainLimitsOf<T> = <T as Config>::ChainLimits;
+#[macro_export]
+macro_rules! limit {
+ ($config:ty, $limit:ident) => {
+ <$crate::ChainLimitsOf<$config> as nft_data_structs::ChainLimits>::$limit
+ }
}
// # Used definitions
@@ -280,10 +289,6 @@
ItemListIndex: map hasher(blake2_128_concat) CollectionId => TokenId;
//#endregion
- //#region Chain limits struct
- pub ChainLimit get(fn chain_limit) config(): ChainLimits;
- //#endregion
-
//#region Bound counters
/// Amount of collections destroyed, used for total amount tracking with
/// CreatedCollectionCount
@@ -485,14 +490,12 @@
CollectionMode::Fungible(points) => points,
_ => 0
};
-
- let chain_limit = ChainLimit::get();
let created_count = CreatedCollectionCount::get();
let destroyed_count = DestroyedCollectionCount::get();
// bound Total number of collections
- ensure!(created_count - destroyed_count < chain_limit.collection_numbers_limit, Error::<T>::TotalCollectionsLimitExceeded);
+ ensure!(created_count - destroyed_count < <limit!(T, CollectionNumberLimit)>::get(), Error::<T>::TotalCollectionsLimitExceeded);
// check params
ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);
@@ -508,7 +511,7 @@
CreatedCollectionCount::put(next_id);
let limits = CollectionLimits {
- sponsored_data_size: chain_limit.custom_data_limit,
+ sponsored_data_size: <limit!(T, CustomDataLimit)>::get(),
..Default::default()
};
@@ -737,8 +740,7 @@
match admin_arr.binary_search(&new_admin_id) {
Ok(_) => {},
Err(idx) => {
- let limits = ChainLimit::get();
- ensure!(admin_arr.len() < limits.collections_admins_limit as usize, Error::<T>::CollectionAdminsLimitExceeded);
+ ensure!(admin_arr.len() < <limit!(T, CollectionAdminsLimit)>::get() as usize, Error::<T>::CollectionAdminsLimitExceeded);
admin_arr.insert(idx, new_admin_id);
<AdminList<T>>::insert(collection_id, admin_arr);
}
@@ -862,7 +864,7 @@
#[weight = <T as Config>::WeightInfo::create_item(data.data_size())]
#[transactional]
- pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResult {
+ pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData<ChainLimitsOf<T>>) -> DispatchResult {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let collection = Self::get_collection(collection_id)?;
@@ -893,7 +895,7 @@
.map(|data| { data.data_size() })
.sum())]
#[transactional]
- pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResult {
+ pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData<ChainLimitsOf<T>>>) -> DispatchResult {
ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -1138,7 +1140,7 @@
Self::check_owner_or_admin_permissions(&target_collection, &sender)?;
// check schema limit
- ensure!(schema.len() as u32 <= ChainLimit::get().offchain_schema_limit, "");
+ ensure!(schema.len() as u32 <= <limit!(T, OffchainSchemaLimit)>::get(), "");
target_collection.offchain_schema = schema;
target_collection.save()
@@ -1168,7 +1170,7 @@
Self::check_owner_or_admin_permissions(&target_collection, &sender)?;
// check schema limit
- ensure!(schema.len() as u32 <= ChainLimit::get().const_on_chain_schema_limit, "");
+ ensure!(schema.len() as u32 <= <limit!(T, ConstOnChainSchemaLimit)>::get(), "");
target_collection.const_on_chain_schema = schema;
target_collection.save()
@@ -1198,25 +1200,10 @@
Self::check_owner_or_admin_permissions(&target_collection, &sender)?;
// check schema limit
- ensure!(schema.len() as u32 <= ChainLimit::get().variable_on_chain_schema_limit, "");
+ ensure!(schema.len() as u32 <= <limit!(T, VariableOnChainSchemaLimit)>::get(), "");
target_collection.variable_on_chain_schema = schema;
target_collection.save()
- }
-
- // Sudo permissions function
- #[weight = <T as Config>::WeightInfo::set_chain_limits()]
- #[transactional]
- pub fn set_chain_limits(
- origin,
- limits: ChainLimits
- ) -> DispatchResult {
-
- #[cfg(not(feature = "runtime-benchmarks"))]
- ensure_root(origin)?;
-
- <ChainLimit>::put(limits);
- Ok(())
}
#[weight = <T as Config>::WeightInfo::set_collection_limits()]
@@ -1230,12 +1217,11 @@
let mut target_collection = Self::get_collection(collection_id)?;
Self::check_owner_permissions(&target_collection, sender.as_sub())?;
let old_limits = &target_collection.limits;
- let chain_limits = ChainLimit::get();
// collection bounds
ensure!(new_limits.sponsor_transfer_timeout <= MAX_SPONSOR_TIMEOUT &&
new_limits.account_token_ownership_limit <= MAX_TOKEN_OWNERSHIP &&
- new_limits.sponsored_data_size <= chain_limits.custom_data_limit,
+ new_limits.sponsored_data_size <= <ChainLimitsOf<T> as ChainLimits>::CustomDataLimit::get(),
Error::<T>::CollectionLimitBoundsExceeded);
// token_limit check prev
@@ -1260,7 +1246,7 @@
sender: &T::CrossAccountId,
collection: &CollectionHandle<T>,
owner: &T::CrossAccountId,
- data: CreateItemData,
+ data: CreateItemData<ChainLimitsOf<T>>,
) -> DispatchResult {
Self::can_create_items_in_collection(collection, sender, owner, 1)?;
Self::validate_create_item_args(collection, &data)?;
@@ -1471,7 +1457,7 @@
Self::token_exists(collection, item_id)?;
ensure!(
- ChainLimit::get().custom_data_limit >= data.len() as u32,
+ <limit!(T, CustomDataLimit)>::get() >= data.len() as u32,
Error::<T>::TokenVariableDataLimitExceeded
);
@@ -1498,7 +1484,7 @@
sender: &T::CrossAccountId,
collection: &CollectionHandle<T>,
owner: &T::CrossAccountId,
- items_data: Vec<CreateItemData>,
+ items_data: Vec<CreateItemData<ChainLimitsOf<T>>>,
) -> DispatchResult {
Self::can_create_items_in_collection(collection, sender, owner, items_data.len() as u32)?;
@@ -1612,18 +1598,18 @@
fn validate_create_item_args(
target_collection: &CollectionHandle<T>,
- data: &CreateItemData,
+ data: &CreateItemData<ChainLimitsOf<T>>,
) -> DispatchResult {
match target_collection.mode {
CollectionMode::NFT => {
if let CreateItemData::NFT(data) = data {
// check sizes
ensure!(
- ChainLimit::get().custom_data_limit >= data.const_data.len() as u32,
+ <limit!(T, CustomDataLimit)>::get() >= data.const_data.len() as u32,
Error::<T>::TokenConstDataLimitExceeded
);
ensure!(
- ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32,
+ <limit!(T, CustomDataLimit)>::get() >= data.variable_data.len() as u32,
Error::<T>::TokenVariableDataLimitExceeded
);
} else {
@@ -1640,11 +1626,11 @@
if let CreateItemData::ReFungible(data) = data {
// check sizes
ensure!(
- ChainLimit::get().custom_data_limit >= data.const_data.len() as u32,
+ <limit!(T, CustomDataLimit)>::get() >= data.const_data.len() as u32,
Error::<T>::TokenConstDataLimitExceeded
);
ensure!(
- ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32,
+ <limit!(T, CustomDataLimit)>::get() >= data.variable_data.len() as u32,
Error::<T>::TokenVariableDataLimitExceeded
);
@@ -1669,7 +1655,7 @@
fn create_item_no_validation(
collection: &CollectionHandle<T>,
owner: &T::CrossAccountId,
- data: CreateItemData,
+ data: CreateItemData<ChainLimitsOf<T>>,
) -> DispatchResult {
match data {
CreateItemData::NFT(data) => {
@@ -2292,7 +2278,7 @@
// bound Owned tokens by a single address
let count = <AccountItemCount<T>>::get(owner.as_sub());
ensure!(
- count < ChainLimit::get().account_token_ownership_limit,
+ count < <limit!(T, AccountTokenOwnershipLimit)>::get(),
Error::<T>::AddressOwnershipLimitExceeded
);
pallets/nft/src/sponsorship.rsdiffbeforeafterboth--- a/pallets/nft/src/sponsorship.rs
+++ b/pallets/nft/src/sponsorship.rs
@@ -1,13 +1,13 @@
use crate::{
Config, Call, CollectionById, CreateItemBasket, VariableMetaDataBasket,
- ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket, ChainLimit,
- CreateItemData, CollectionMode,
+ ReFungibleTransferBasket, FungibleTransferBasket, NftTransferBasket,
+ CreateItemData, CollectionMode, limit,
};
use core::marker::PhantomData;
use up_sponsorship::SponsorshipHandler;
use frame_support::{
- traits::IsSubType,
- storage::{StorageMap, StorageDoubleMap, StorageValue},
+ traits::{IsSubType, Get},
+ storage::{StorageMap, StorageDoubleMap},
};
use nft_data_structs::{TokenId, CollectionId};
@@ -16,7 +16,7 @@
pub fn withdraw_create_item(
who: &T::AccountId,
collection_id: &CollectionId,
- _properties: &CreateItemData,
+ _properties: &CreateItemData<T::ChainLimits>,
) -> Option<T::AccountId> {
let collection = CollectionById::<T>::get(collection_id)?;
@@ -47,7 +47,6 @@
item_id: &TokenId,
) -> Option<T::AccountId> {
let collection = CollectionById::<T>::get(collection_id)?;
- let limits = ChainLimit::get();
let mut sponsor_transfer = false;
if collection.sponsorship.confirmed() {
@@ -62,7 +61,7 @@
let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
collection_limits.sponsor_transfer_timeout
} else {
- limits.nft_sponsor_transfer_timeout
+ <limit!(T, NftSponsorTransferTimeout)>::get()
};
let mut sponsored = true;
@@ -84,7 +83,7 @@
let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
collection_limits.sponsor_transfer_timeout
} else {
- limits.fungible_sponsor_transfer_timeout
+ <limit!(T, FungibleSponsorTransferTimeout)>::get()
};
let block_number = <frame_system::Pallet<T>>::block_number() as T::BlockNumber;
@@ -107,7 +106,7 @@
let limit: u32 = if collection_limits.sponsor_transfer_timeout > 0 {
collection_limits.sponsor_transfer_timeout
} else {
- limits.refungible_sponsor_transfer_timeout
+ <limit!(T, ReFungibleSponsorTransferTimeout)>::get()
};
let mut sponsored = true;
primitives/nft/src/lib.rsdiffbeforeafterboth1#![cfg_attr(not(feature = "std"), no_std)]23#[cfg(feature = "serde")]4pub use serde::{Serialize, Deserialize};56use sp_runtime::sp_std::prelude::Vec;7use codec::{Decode, Encode};8use max_encoded_len::MaxEncodedLen;9pub use frame_support::{10 BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error,11 dispatch::DispatchResult,12 ensure, fail, parameter_types,13 traits::{14 Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,15 Randomness, IsSubType, WithdrawReasons,16 },17 weights::{18 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},19 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,20 WeightToFeePolynomial, DispatchClass,21 },22 StorageValue, transactional,23};24use derivative::Derivative;2526pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;27pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;28pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;29pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;3031// TODO: Somehow use ChainLimits for BoundedVec len calculation?32// Do we need ChainLimits anyway, if we can change them via forkless upgrades?33parameter_types! {34pub const MaxDataSize: u32 = 2048;35// TODO: This limit isn't checked for substrate create_multiple_items call36pub const MaxItemsPerBatch: u32 = 200;37}3839pub type CollectionId = u32;40pub type TokenId = u32;41pub type DecimalPoints = u8;4243#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]44#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]45pub enum CollectionMode {46 Invalid,47 NFT,48 // decimal points49 Fungible(DecimalPoints),50 ReFungible,51}5253impl Default for CollectionMode {54 fn default() -> Self {55 Self::Invalid56 }57}5859impl CollectionMode {60 pub fn id(&self) -> u8 {61 match self {62 CollectionMode::Invalid => 0,63 CollectionMode::NFT => 1,64 CollectionMode::Fungible(_) => 2,65 CollectionMode::ReFungible => 3,66 }67 }68}6970pub trait SponsoringResolve<AccountId, Call> {71 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;72}7374#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]75#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]76pub enum AccessMode {77 Normal,78 WhiteList,79}80impl Default for AccessMode {81 fn default() -> Self {82 Self::Normal83 }84}8586#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]87#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]88pub enum SchemaVersion {89 ImageURL,90 Unique,91}92impl Default for SchemaVersion {93 fn default() -> Self {94 Self::ImageURL95 }96}9798#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]99#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]100pub struct Ownership<AccountId> {101 pub owner: AccountId,102 pub fraction: u128,103}104105#[derive(Encode, Decode, Debug, Clone, PartialEq)]106#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]107pub enum SponsorshipState<AccountId> {108 /// The fees are applied to the transaction sender109 Disabled,110 Unconfirmed(AccountId),111 /// Transactions are sponsored by specified account112 Confirmed(AccountId),113}114115impl<AccountId> SponsorshipState<AccountId> {116 pub fn sponsor(&self) -> Option<&AccountId> {117 match self {118 Self::Confirmed(sponsor) => Some(sponsor),119 _ => None,120 }121 }122123 pub fn pending_sponsor(&self) -> Option<&AccountId> {124 match self {125 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),126 _ => None,127 }128 }129130 pub fn confirmed(&self) -> bool {131 matches!(self, Self::Confirmed(_))132 }133}134135impl<T> Default for SponsorshipState<T> {136 fn default() -> Self {137 Self::Disabled138 }139}140141#[derive(Encode, Decode, Clone, PartialEq)]142#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]143pub struct Collection<T: frame_system::Config> {144 pub owner: T::AccountId,145 pub mode: CollectionMode,146 pub access: AccessMode,147 pub decimal_points: DecimalPoints,148 pub name: Vec<u16>, // 64 include null escape char149 pub description: Vec<u16>, // 256 include null escape char150 pub token_prefix: Vec<u8>, // 16 include null escape char151 pub mint_mode: bool,152 pub offchain_schema: Vec<u8>,153 pub schema_version: SchemaVersion,154 pub sponsorship: SponsorshipState<T::AccountId>,155 pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions156 pub variable_on_chain_schema: Vec<u8>, //157 pub const_on_chain_schema: Vec<u8>, //158 pub transfers_enabled: bool,159}160161#[derive(Encode, Decode, Debug, Clone, PartialEq)]162#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]163pub struct NftItemType<AccountId> {164 pub owner: AccountId,165 pub const_data: Vec<u8>,166 pub variable_data: Vec<u8>,167}168169#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]170#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]171pub struct FungibleItemType {172 pub value: u128,173}174175#[derive(Encode, Decode, Debug, Clone, PartialEq)]176#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]177pub struct ReFungibleItemType<AccountId> {178 pub owner: Vec<Ownership<AccountId>>,179 pub const_data: Vec<u8>,180 pub variable_data: Vec<u8>,181}182183#[derive(Encode, Decode, Debug, Clone, PartialEq)]184#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]185pub struct CollectionLimits<BlockNumber: Encode + Decode> {186 pub account_token_ownership_limit: u32,187 pub sponsored_data_size: u32,188 /// None - setVariableMetadata is not sponsored189 /// Some(v) - setVariableMetadata is sponsored190 /// if there is v block between txs191 pub sponsored_data_rate_limit: Option<BlockNumber>,192 pub token_limit: u32,193194 // Timeouts for item types in passed blocks195 pub sponsor_transfer_timeout: u32,196 pub owner_can_transfer: bool,197 pub owner_can_destroy: bool,198}199200impl<BlockNumber: Encode + Decode> Default for CollectionLimits<BlockNumber> {201 fn default() -> Self {202 Self {203 account_token_ownership_limit: 10_000_000,204 token_limit: u32::max_value(),205 sponsored_data_size: u32::MAX,206 sponsored_data_rate_limit: None,207 sponsor_transfer_timeout: 14400,208 owner_can_transfer: true,209 owner_can_destroy: true,210 }211 }212}213214#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]215#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]216pub struct ChainLimits {217 pub collection_numbers_limit: u32,218 pub account_token_ownership_limit: u32,219 pub collections_admins_limit: u64,220 pub custom_data_limit: u32,221222 // Timeouts for item types in passed blocks223 pub nft_sponsor_transfer_timeout: u32,224 pub fungible_sponsor_transfer_timeout: u32,225 pub refungible_sponsor_transfer_timeout: u32,226227 // Schema limits228 pub offchain_schema_limit: u32,229 pub variable_on_chain_schema_limit: u32,230 pub const_on_chain_schema_limit: u32,231}232233/// BoundedVec doesn't supports serde234#[cfg(feature = "serde1")]235mod bounded_serde {236 use core::convert::TryFrom;237 use frame_support::{BoundedVec, traits::Get};238 use serde::{239 ser::{self, Serialize},240 de::{self, Deserialize, Error},241 };242 use sp_std::vec::Vec;243244 pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>245 where246 D: ser::Serializer,247 V: Serialize,248 {249 let vec: &Vec<_> = &value;250 vec.serialize(serializer)251 }252253 pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>254 where255 D: de::Deserializer<'de>,256 V: de::Deserialize<'de>,257 S: Get<u32>,258 {259 // TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec?260 let vec = <Vec<V>>::deserialize(deserializer)?;261 let len = vec.len();262 TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))263 }264}265266#[derive(Encode, Decode, MaxEncodedLen, Default, Derivative, Clone, PartialEq)]267#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]268#[derivative(Debug)]269pub struct CreateNftData {270 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]271 #[derivative(Debug = "ignore")]272 pub const_data: BoundedVec<u8, MaxDataSize>,273 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]274 #[derivative(Debug = "ignore")]275 pub variable_data: BoundedVec<u8, MaxDataSize>,276}277278#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq)]279#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]280pub struct CreateFungibleData {281 pub value: u128,282}283284#[derive(Encode, Decode, MaxEncodedLen, Default, Derivative, Clone, PartialEq)]285#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]286#[derivative(Debug)]287pub struct CreateReFungibleData {288 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]289 #[derivative(Debug = "ignore")]290 pub const_data: BoundedVec<u8, MaxDataSize>,291 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]292 #[derivative(Debug = "ignore")]293 pub variable_data: BoundedVec<u8, MaxDataSize>,294 pub pieces: u128,295}296297#[derive(Encode, Decode, MaxEncodedLen, Debug, Clone, PartialEq)]298#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]299pub enum CreateItemData {300 NFT(CreateNftData),301 Fungible(CreateFungibleData),302 ReFungible(CreateReFungibleData),303}304305impl CreateItemData {306 pub fn data_size(&self) -> usize {307 match self {308 CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),309 CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),310 _ => 0,311 }312 }313}314315impl From<CreateNftData> for CreateItemData {316 fn from(item: CreateNftData) -> Self {317 CreateItemData::NFT(item)318 }319}320321impl From<CreateReFungibleData> for CreateItemData {322 fn from(item: CreateReFungibleData) -> Self {323 CreateItemData::ReFungible(item)324 }325}326327impl From<CreateFungibleData> for CreateItemData {328 fn from(item: CreateFungibleData) -> Self {329 CreateItemData::Fungible(item)330 }331}1#![cfg_attr(not(feature = "std"), no_std)]23#[cfg(feature = "serde")]4pub use serde::{Serialize, Deserialize};56use sp_runtime::sp_std::prelude::Vec;7use codec::{Decode, Encode};8use max_encoded_len::MaxEncodedLen;9pub use frame_support::{10 BoundedVec, construct_runtime, decl_event, decl_module, decl_storage, decl_error,11 dispatch::DispatchResult,12 ensure, fail, parameter_types,13 traits::{14 Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,15 Randomness, IsSubType, WithdrawReasons,16 },17 weights::{18 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},19 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,20 WeightToFeePolynomial, DispatchClass,21 },22 StorageValue, transactional,23};24use derivative::Derivative;2526pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;27pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;28pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;29pub const MAX_TOKEN_OWNERSHIP: u32 = 10_000_000;3031pub type CollectionId = u32;32pub type TokenId = u32;33pub type DecimalPoints = u8;3435#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]36#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]37pub enum CollectionMode {38 Invalid,39 NFT,40 // decimal points41 Fungible(DecimalPoints),42 ReFungible,43}4445impl Default for CollectionMode {46 fn default() -> Self {47 Self::Invalid48 }49}5051impl CollectionMode {52 pub fn id(&self) -> u8 {53 match self {54 CollectionMode::Invalid => 0,55 CollectionMode::NFT => 1,56 CollectionMode::Fungible(_) => 2,57 CollectionMode::ReFungible => 3,58 }59 }60}6162pub trait SponsoringResolve<AccountId, Call> {63 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;64}6566#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]67#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]68pub enum AccessMode {69 Normal,70 WhiteList,71}72impl Default for AccessMode {73 fn default() -> Self {74 Self::Normal75 }76}7778#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq)]79#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]80pub enum SchemaVersion {81 ImageURL,82 Unique,83}84impl Default for SchemaVersion {85 fn default() -> Self {86 Self::ImageURL87 }88}8990#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]91#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]92pub struct Ownership<AccountId> {93 pub owner: AccountId,94 pub fraction: u128,95}9697#[derive(Encode, Decode, Debug, Clone, PartialEq)]98#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]99pub enum SponsorshipState<AccountId> {100 /// The fees are applied to the transaction sender101 Disabled,102 Unconfirmed(AccountId),103 /// Transactions are sponsored by specified account104 Confirmed(AccountId),105}106107impl<AccountId> SponsorshipState<AccountId> {108 pub fn sponsor(&self) -> Option<&AccountId> {109 match self {110 Self::Confirmed(sponsor) => Some(sponsor),111 _ => None,112 }113 }114115 pub fn pending_sponsor(&self) -> Option<&AccountId> {116 match self {117 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),118 _ => None,119 }120 }121122 pub fn confirmed(&self) -> bool {123 matches!(self, Self::Confirmed(_))124 }125}126127impl<T> Default for SponsorshipState<T> {128 fn default() -> Self {129 Self::Disabled130 }131}132133#[derive(Encode, Decode, Clone, PartialEq)]134#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]135pub struct Collection<T: frame_system::Config> {136 pub owner: T::AccountId,137 pub mode: CollectionMode,138 pub access: AccessMode,139 pub decimal_points: DecimalPoints,140 pub name: Vec<u16>, // 64 include null escape char141 pub description: Vec<u16>, // 256 include null escape char142 pub token_prefix: Vec<u8>, // 16 include null escape char143 pub mint_mode: bool,144 pub offchain_schema: Vec<u8>,145 pub schema_version: SchemaVersion,146 pub sponsorship: SponsorshipState<T::AccountId>,147 pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions148 pub variable_on_chain_schema: Vec<u8>, //149 pub const_on_chain_schema: Vec<u8>, //150 pub transfers_enabled: bool,151}152153#[derive(Encode, Decode, Debug, Clone, PartialEq)]154#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]155pub struct NftItemType<AccountId> {156 pub owner: AccountId,157 pub const_data: Vec<u8>,158 pub variable_data: Vec<u8>,159}160161#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]162#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]163pub struct FungibleItemType {164 pub value: u128,165}166167#[derive(Encode, Decode, Debug, Clone, PartialEq)]168#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]169pub struct ReFungibleItemType<AccountId> {170 pub owner: Vec<Ownership<AccountId>>,171 pub const_data: Vec<u8>,172 pub variable_data: Vec<u8>,173}174175#[derive(Encode, Decode, Debug, Clone, PartialEq)]176#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]177pub struct CollectionLimits<BlockNumber: Encode + Decode> {178 pub account_token_ownership_limit: u32,179 pub sponsored_data_size: u32,180 /// None - setVariableMetadata is not sponsored181 /// Some(v) - setVariableMetadata is sponsored182 /// if there is v block between txs183 pub sponsored_data_rate_limit: Option<BlockNumber>,184 pub token_limit: u32,185186 // Timeouts for item types in passed blocks187 pub sponsor_transfer_timeout: u32,188 pub owner_can_transfer: bool,189 pub owner_can_destroy: bool,190}191192impl<BlockNumber: Encode + Decode> Default for CollectionLimits<BlockNumber> {193 fn default() -> Self {194 Self {195 account_token_ownership_limit: 10_000_000,196 token_limit: u32::max_value(),197 sponsored_data_size: u32::MAX,198 sponsored_data_rate_limit: None,199 sponsor_transfer_timeout: 14400,200 owner_can_transfer: true,201 owner_can_destroy: true,202 }203 }204}205206pub trait ChainLimits {207 type CollectionNumberLimit: Get<u32>;208 type AccountTokenOwnershipLimit: Get<u32>;209 type CollectionAdminsLimit: Get<u64>;210 type CustomDataLimit: Get<u32>;211212 // Timeouts for item types in passed blocks213 type NftSponsorTransferTimeout: Get<u32>;214 type FungibleSponsorTransferTimeout: Get<u32>;215 type ReFungibleSponsorTransferTimeout: Get<u32>;216217 // Schema limits218 type OffchainSchemaLimit: Get<u32>;219 type VariableOnChainSchemaLimit: Get<u32>;220 type ConstOnChainSchemaLimit: Get<u32>;221222 /// How much items can be created per single223 /// create_many call224 type MaxItemsPerBatch: Get<u32>;225}226227/// BoundedVec doesn't supports serde228#[cfg(feature = "serde1")]229mod bounded_serde {230 use core::convert::TryFrom;231 use frame_support::{BoundedVec, traits::Get};232 use serde::{233 ser::{self, Serialize},234 de::{self, Deserialize, Error},235 };236 use sp_std::vec::Vec;237238 pub fn serialize<D, V, S>(value: &BoundedVec<V, S>, serializer: D) -> Result<D::Ok, D::Error>239 where240 D: ser::Serializer,241 V: Serialize,242 {243 let vec: &Vec<_> = &value;244 vec.serialize(serializer)245 }246247 pub fn deserialize<'de, D, V, S>(deserializer: D) -> Result<BoundedVec<V, S>, D::Error>248 where249 D: de::Deserializer<'de>,250 V: de::Deserialize<'de>,251 S: Get<u32>,252 {253 // TODO: Implement custom visitor, which will limit vec size at parse time? Will serde only be used by chainspec?254 let vec = <Vec<V>>::deserialize(deserializer)?;255 let len = vec.len();256 TryFrom::try_from(vec).map_err(|_| D::Error::invalid_length(len, &"lesser size"))257 }258}259260#[derive(Encode, Decode, MaxEncodedLen, Default, Derivative)]261#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]262#[derivative(Debug(bound = ""), PartialEq(bound = ""), Clone(bound = ""))]263pub struct CreateNftData<T: ChainLimits> {264 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]265 #[derivative(Debug = "ignore")]266 pub const_data: BoundedVec<u8, T::CustomDataLimit>,267 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]268 #[derivative(Debug = "ignore")]269 pub variable_data: BoundedVec<u8, T::CustomDataLimit>,270}271272#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq)]273#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]274pub struct CreateFungibleData {275 pub value: u128,276}277278#[derive(Encode, Decode, MaxEncodedLen, Default, Derivative)]279#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]280#[derivative(Debug(bound = ""), PartialEq(bound = ""), Clone(bound = ""))]281pub struct CreateReFungibleData<T: ChainLimits> {282 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]283 #[derivative(Debug = "ignore")]284 pub const_data: BoundedVec<u8, T::CustomDataLimit>,285 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]286 #[derivative(Debug = "ignore")]287 pub variable_data: BoundedVec<u8, T::CustomDataLimit>,288 pub pieces: u128,289}290291#[derive(Encode, Decode, MaxEncodedLen, Derivative)]292#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]293#[derivative(Debug(bound = ""), PartialEq(bound = ""), Clone(bound = ""))]294pub enum CreateItemData<T: ChainLimits> {295 NFT(CreateNftData<T>),296 Fungible(CreateFungibleData),297 ReFungible(CreateReFungibleData<T>),298}299300impl<T: ChainLimits> CreateItemData<T> {301 pub fn data_size(&self) -> usize {302 match self {303 CreateItemData::NFT(data) => data.variable_data.len() + data.const_data.len(),304 CreateItemData::ReFungible(data) => data.variable_data.len() + data.const_data.len(),305 _ => 0,306 }307 }308}309310impl<T: ChainLimits> From<CreateNftData<T>> for CreateItemData<T> {311 fn from(item: CreateNftData<T>) -> Self {312 CreateItemData::NFT(item)313 }314}315316impl<T: ChainLimits> From<CreateReFungibleData<T>> for CreateItemData<T> {317 fn from(item: CreateReFungibleData<T>) -> Self {318 CreateItemData::ReFungible(item)319 }320}321322impl<T: ChainLimits> From<CreateFungibleData> for CreateItemData<T> {323 fn from(item: CreateFungibleData) -> Self {324 CreateItemData::Fungible(item)325 }326}runtime/src/lib.rsdiffbeforeafterboth--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -683,6 +683,35 @@
}
parameter_types! {
+ pub const CollectionNumberLimit: u32 = 100000;
+ pub const AccountTokenOwnershipLimit: u32 = 1000000;
+ pub const CollectionAdminsLimit: u64 = 5;
+ pub const CustomDataLimit: u32 = 2048;
+ pub const NftSponsorTransferTimeout: u32 = 5;
+ pub const FungibleSponsorTransferTimeout: u32 = 5;
+ pub const ReFungibleSponsorTransferTimeout: u32 = 5;
+ pub const OffchainSchemaLimit: u32 = 1024;
+ pub const VariableOnChainSchemaLimit: u32 = 1024;
+ pub const ConstOnChainSchemaLimit: u32 = 1024;
+ pub const MaxItemsPerBatch: u32 = 200;
+}
+
+pub struct ChainLimits;
+impl nft_data_structs::ChainLimits for ChainLimits {
+ type CollectionNumberLimit = CollectionNumberLimit;
+ type AccountTokenOwnershipLimit = AccountTokenOwnershipLimit;
+ type CollectionAdminsLimit = CollectionAdminsLimit;
+ type CustomDataLimit = CustomDataLimit;
+ type NftSponsorTransferTimeout = NftSponsorTransferTimeout;
+ type FungibleSponsorTransferTimeout = FungibleSponsorTransferTimeout;
+ type ReFungibleSponsorTransferTimeout = ReFungibleSponsorTransferTimeout;
+ type OffchainSchemaLimit = OffchainSchemaLimit;
+ type VariableOnChainSchemaLimit = VariableOnChainSchemaLimit;
+ type ConstOnChainSchemaLimit = ConstOnChainSchemaLimit;
+ type MaxItemsPerBatch = MaxItemsPerBatch;
+}
+
+parameter_types! {
pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();
pub const CollectionCreationPrice: Balance = 100 * UNIQUE;
}
@@ -699,6 +728,7 @@
type Currency = Balances;
type CollectionCreationPrice = CollectionCreationPrice;
type TreasuryAccountId = TreasuryAccountId;
+ type ChainLimits = ChainLimits;
}
parameter_types! {