difftreelog
Merge pull request #273 from UniqueNetwork/feature/CORE-269
in: master
3 files changed
pallets/common/src/lib.rsdiffbeforeafterboth1#![cfg_attr(not(feature = "std"), no_std)]23use core::ops::{Deref, DerefMut};4use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};5use sp_std::vec::Vec;6use account::CrossAccountId;7use frame_support::{8 dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo},9 ensure, fail,10 traits::{Imbalance, Get, Currency},11 BoundedVec,12};13use pallet_evm::GasWeightMapping;14use up_data_structs::{15 COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement,16 MAX_TOKEN_PREFIX_LENGTH, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, Pays, PostDispatchInfo,17 TokenId, Weight, WithdrawReasons, CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode,18 NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,19 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT, CUSTOM_DATA_LIMIT, CollectionLimits,20 CustomDataLimit, CreateCollectionData, SponsorshipState,21};22pub use pallet::*;23use sp_core::H160;24use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};25pub mod account;26#[cfg(feature = "runtime-benchmarks")]27pub mod benchmarking;28pub mod erc;29pub mod eth;3031#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]32pub struct CollectionHandle<T: Config> {33 pub id: CollectionId,34 collection: Collection<T::AccountId>,35 pub recorder: SubstrateRecorder<T>,36}37impl<T: Config> WithRecorder<T> for CollectionHandle<T> {38 fn recorder(&self) -> &SubstrateRecorder<T> {39 &self.recorder40 }41 fn into_recorder(self) -> SubstrateRecorder<T> {42 self.recorder43 }44}45impl<T: Config> CollectionHandle<T> {46 pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {47 <CollectionById<T>>::get(id).map(|collection| Self {48 id,49 collection,50 recorder: SubstrateRecorder::new(eth::collection_id_to_address(id), gas_limit),51 })52 }53 pub fn new(id: CollectionId) -> Option<Self> {54 Self::new_with_gas_limit(id, u64::MAX)55 }56 pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {57 Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)58 }59 pub fn log_mirrored(&self, log: impl evm_coder::ToLog) {60 self.recorder.log_mirrored(log)61 }62 pub fn log_direct(&self, log: impl evm_coder::ToLog) {63 self.recorder.log_direct(log)64 }65 pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {66 self.recorder67 .consume_gas(T::GasWeightMapping::weight_to_gas(68 <T as frame_system::Config>::DbWeight::get()69 .read70 .saturating_mul(reads),71 ))72 }73 pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {74 self.recorder75 .consume_gas(T::GasWeightMapping::weight_to_gas(76 <T as frame_system::Config>::DbWeight::get()77 .write78 .saturating_mul(writes),79 ))80 }81 pub fn submit_logs(self) {82 self.recorder.submit_logs()83 }84 pub fn save(self) -> DispatchResult {85 self.recorder.submit_logs();86 <CollectionById<T>>::insert(self.id, self.collection);87 Ok(())88 }89}90impl<T: Config> Deref for CollectionHandle<T> {91 type Target = Collection<T::AccountId>;9293 fn deref(&self) -> &Self::Target {94 &self.collection95 }96}9798impl<T: Config> DerefMut for CollectionHandle<T> {99 fn deref_mut(&mut self) -> &mut Self::Target {100 &mut self.collection101 }102}103104impl<T: Config> CollectionHandle<T> {105 pub fn check_is_owner(&self, subject: &T::CrossAccountId) -> DispatchResult {106 ensure!(*subject.as_sub() == self.owner, <Error<T>>::NoPermission);107 Ok(())108 }109 pub fn is_owner_or_admin(&self, subject: &T::CrossAccountId) -> bool {110 *subject.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, subject))111 }112 pub fn check_is_owner_or_admin(&self, subject: &T::CrossAccountId) -> DispatchResult {113 ensure!(self.is_owner_or_admin(subject), <Error<T>>::NoPermission);114 Ok(())115 }116 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {117 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)118 }119 pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {120 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)121 }122 pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {123 ensure!(124 <Allowlist<T>>::get((self.id, user)),125 <Error<T>>::AddressNotInAllowlist126 );127 Ok(())128 }129130 pub fn check_can_update_meta(131 &self,132 subject: &T::CrossAccountId,133 item_owner: &T::CrossAccountId,134 ) -> DispatchResult {135 match self.meta_update_permission {136 MetaUpdatePermission::ItemOwner => {137 ensure!(subject == item_owner, <Error<T>>::NoPermission);138 Ok(())139 }140 MetaUpdatePermission::Admin => self.check_is_owner_or_admin(subject),141 MetaUpdatePermission::None => fail!(<Error<T>>::NoPermission),142 }143 }144}145146#[frame_support::pallet]147pub mod pallet {148 use super::*;149 use frame_support::{Blake2_128Concat, pallet_prelude::*, storage::Key};150 use account::CrossAccountId;151 use frame_support::traits::Currency;152 use up_data_structs::TokenId;153 use scale_info::TypeInfo;154155 #[pallet::config]156 pub trait Config: frame_system::Config + pallet_evm_coder_substrate::Config + TypeInfo {157 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;158159 type CrossAccountId: CrossAccountId<Self::AccountId>;160161 type EvmAddressMapping: pallet_evm::AddressMapping<Self::AccountId>;162 type EvmBackwardsAddressMapping: up_evm_mapping::EvmBackwardsAddressMapping<Self::AccountId>;163164 type Currency: Currency<Self::AccountId>;165 type CollectionCreationPrice: Get<166 <<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,167 >;168 type TreasuryAccountId: Get<Self::AccountId>;169 }170171 #[pallet::pallet]172 #[pallet::generate_store(pub(super) trait Store)]173 pub struct Pallet<T>(_);174175 #[pallet::extra_constants]176 impl<T: Config> Pallet<T> {177 pub fn collection_admins_limit() -> u32 {178 COLLECTION_ADMINS_LIMIT179 }180 }181182 #[pallet::event]183 #[pallet::generate_deposit(pub fn deposit_event)]184 pub enum Event<T: Config> {185 /// New collection was created186 ///187 /// # Arguments188 ///189 /// * collection_id: Globally unique identifier of newly created collection.190 ///191 /// * mode: [CollectionMode] converted into u8.192 ///193 /// * account_id: Collection owner.194 CollectionCreated(CollectionId, u8, T::AccountId),195196 /// New collection was destroyed197 ///198 /// # Arguments199 ///200 /// * collection_id: Globally unique identifier of collection.201 CollectionDestroyed(CollectionId),202203 /// New item was created.204 ///205 /// # Arguments206 ///207 /// * collection_id: Id of the collection where item was created.208 ///209 /// * item_id: Id of an item. Unique within the collection.210 ///211 /// * recipient: Owner of newly created item212 ///213 /// * amount: Always 1 for NFT214 ItemCreated(CollectionId, TokenId, T::CrossAccountId, u128),215216 /// Collection item was burned.217 ///218 /// # Arguments219 ///220 /// * collection_id.221 ///222 /// * item_id: Identifier of burned NFT.223 ///224 /// * owner: which user has destroyed its tokens225 ///226 /// * amount: Always 1 for NFT227 ItemDestroyed(CollectionId, TokenId, T::CrossAccountId, u128),228229 /// Item was transferred230 ///231 /// * collection_id: Id of collection to which item is belong232 ///233 /// * item_id: Id of an item234 ///235 /// * sender: Original owner of item236 ///237 /// * recipient: New owner of item238 ///239 /// * amount: Always 1 for NFT240 Transfer(241 CollectionId,242 TokenId,243 T::CrossAccountId,244 T::CrossAccountId,245 u128,246 ),247248 /// * collection_id249 ///250 /// * item_id251 ///252 /// * sender253 ///254 /// * spender255 ///256 /// * amount257 Approved(258 CollectionId,259 TokenId,260 T::CrossAccountId,261 T::CrossAccountId,262 u128,263 ),264 }265266 #[pallet::error]267 pub enum Error<T> {268 /// This collection does not exist.269 CollectionNotFound,270 /// Sender parameter and item owner must be equal.271 MustBeTokenOwner,272 /// No permission to perform action273 NoPermission,274 /// Collection is not in mint mode.275 PublicMintingNotAllowed,276 /// Address is not in allow list.277 AddressNotInAllowlist,278279 /// Collection name can not be longer than 63 char.280 CollectionNameLimitExceeded,281 /// Collection description can not be longer than 255 char.282 CollectionDescriptionLimitExceeded,283 /// Token prefix can not be longer than 15 char.284 CollectionTokenPrefixLimitExceeded,285 /// Total collections bound exceeded.286 TotalCollectionsLimitExceeded,287 /// variable_data exceeded data limit.288 TokenVariableDataLimitExceeded,289 /// Exceeded max admin count290 CollectionAdminCountExceeded,291 /// Collection limit bounds per collection exceeded292 CollectionLimitBoundsExceeded,293 /// Tried to enable permissions which are only permitted to be disabled294 OwnerPermissionsCantBeReverted,295296 /// Collection settings not allowing items transferring297 TransferNotAllowed,298 /// Account token limit exceeded per collection299 AccountTokenLimitExceeded,300 /// Collection token limit exceeded301 CollectionTokenLimitExceeded,302 /// Metadata flag frozen303 MetadataFlagFrozen,304305 /// Item not exists.306 TokenNotFound,307 /// Item balance not enough.308 TokenValueTooLow,309 /// Requested value more than approved.310 ApprovedValueTooLow,311 /// Tried to approve more than owned312 CantApproveMoreThanOwned,313314 /// Can't transfer tokens to ethereum zero address315 AddressIsZero,316 /// Target collection doesn't supports this operation317 UnsupportedOperation,318 }319320 #[pallet::storage]321 pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;322 #[pallet::storage]323 pub type DestroyedCollectionCount<T> =324 StorageValue<Value = CollectionId, QueryKind = ValueQuery>;325326 /// Collection info327 #[pallet::storage]328 pub type CollectionById<T> = StorageMap<329 Hasher = Blake2_128Concat,330 Key = CollectionId,331 Value = Collection<<T as frame_system::Config>::AccountId>,332 QueryKind = OptionQuery,333 >;334335 #[pallet::storage]336 pub type AdminAmount<T> = StorageMap<337 Hasher = Blake2_128Concat,338 Key = CollectionId,339 Value = u32,340 QueryKind = ValueQuery,341 >;342343 /// List of collection admins344 #[pallet::storage]345 pub type IsAdmin<T: Config> = StorageNMap<346 Key = (347 Key<Blake2_128Concat, CollectionId>,348 Key<Blake2_128Concat, T::CrossAccountId>,349 ),350 Value = bool,351 QueryKind = ValueQuery,352 >;353354 /// Allowlisted collection users355 #[pallet::storage]356 pub type Allowlist<T: Config> = StorageNMap<357 Key = (358 Key<Blake2_128Concat, CollectionId>,359 Key<Blake2_128Concat, T::CrossAccountId>,360 ),361 Value = bool,362 QueryKind = ValueQuery,363 >;364365 /// Not used by code, exists only to provide some types to metadata366 #[pallet::storage]367 pub type DummyStorageValue<T> =368 StorageValue<Value = (CollectionStats, CollectionId, TokenId), QueryKind = OptionQuery>;369}370371impl<T: Config> Pallet<T> {372 /// Ethereum receiver 0x0000000000000000000000000000000000000000 is reserved, and shouldn't own tokens373 pub fn ensure_correct_receiver(receiver: &T::CrossAccountId) -> DispatchResult {374 ensure!(375 &T::CrossAccountId::from_eth(H160([0; 20])) != receiver,376 <Error<T>>::AddressIsZero377 );378 Ok(())379 }380 pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {381 <IsAdmin<T>>::iter_prefix((collection,))382 .map(|(a, _)| a)383 .collect()384 }385 pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {386 <Allowlist<T>>::iter_prefix((collection,))387 .map(|(a, _)| a)388 .collect()389 }390 pub fn allowed(collection: CollectionId, user: T::CrossAccountId) -> bool {391 <Allowlist<T>>::get((collection, user))392 }393 pub fn collection_stats() -> CollectionStats {394 let created = <CreatedCollectionCount<T>>::get();395 let destroyed = <DestroyedCollectionCount<T>>::get();396 CollectionStats {397 created: created.0,398 destroyed: destroyed.0,399 alive: created.0 - destroyed.0,400 }401 }402}403404impl<T: Config> Pallet<T> {405 pub fn init_collection(406 owner: T::AccountId,407 data: CreateCollectionData<T::AccountId>,408 ) -> Result<CollectionId, DispatchError> {409 {410 ensure!(411 data.token_prefix.len() <= MAX_TOKEN_PREFIX_LENGTH as usize,412 Error::<T>::CollectionTokenPrefixLimitExceeded413 );414 }415416 let created_count = <CreatedCollectionCount<T>>::get()417 .0418 .checked_add(1)419 .ok_or(ArithmeticError::Overflow)?;420 let destroyed_count = <DestroyedCollectionCount<T>>::get().0;421 let id = CollectionId(created_count);422423 // bound Total number of collections424 ensure!(425 created_count - destroyed_count <= COLLECTION_NUMBER_LIMIT,426 <Error<T>>::TotalCollectionsLimitExceeded427 );428429 // =========430431 let collection = Collection {432 owner: owner.clone(),433 name: data.name,434 mode: data.mode.clone(),435 mint_mode: false,436 access: data.access.unwrap_or_default(),437 description: data.description,438 token_prefix: data.token_prefix,439 offchain_schema: data.offchain_schema,440 schema_version: data.schema_version.unwrap_or_default(),441 sponsorship: data442 .pending_sponsor443 .map(SponsorshipState::Unconfirmed)444 .unwrap_or_default(),445 variable_on_chain_schema: data.variable_on_chain_schema,446 const_on_chain_schema: data.const_on_chain_schema,447 limits: data448 .limits449 .map(|limits| Self::clamp_limits(data.mode.clone(), &Default::default(), limits))450 .unwrap_or_else(|| Ok(CollectionLimits::default()))?,451 meta_update_permission: data.meta_update_permission.unwrap_or_default(),452 };453454 // Take a (non-refundable) deposit of collection creation455 {456 let mut imbalance =457 <<<T as Config>::Currency as Currency<T::AccountId>>::PositiveImbalance>::zero();458 imbalance.subsume(459 <<T as Config>::Currency as Currency<T::AccountId>>::deposit_creating(460 &T::TreasuryAccountId::get(),461 T::CollectionCreationPrice::get(),462 ),463 );464 <T as Config>::Currency::settle(465 &owner,466 imbalance,467 WithdrawReasons::TRANSFER,468 ExistenceRequirement::KeepAlive,469 )470 .map_err(|_| Error::<T>::NoPermission)?;471 }472473 <CreatedCollectionCount<T>>::put(created_count);474 <Pallet<T>>::deposit_event(Event::CollectionCreated(id, data.mode.id(), owner.clone()));475 <CollectionById<T>>::insert(id, collection);476 Ok(id)477 }478479 pub fn destroy_collection(480 collection: CollectionHandle<T>,481 sender: &T::CrossAccountId,482 ) -> DispatchResult {483 ensure!(484 collection.limits.owner_can_destroy(),485 <Error<T>>::NoPermission,486 );487 collection.check_is_owner(sender)?;488489 let destroyed_collections = <DestroyedCollectionCount<T>>::get()490 .0491 .checked_add(1)492 .ok_or(ArithmeticError::Overflow)?;493494 // =========495496 <DestroyedCollectionCount<T>>::put(destroyed_collections);497 <CollectionById<T>>::remove(collection.id);498 <AdminAmount<T>>::remove(collection.id);499 <IsAdmin<T>>::remove_prefix((collection.id,), None);500 <Allowlist<T>>::remove_prefix((collection.id,), None);501502 <Pallet<T>>::deposit_event(Event::CollectionDestroyed(collection.id));503 Ok(())504 }505506 pub fn toggle_allowlist(507 collection: &CollectionHandle<T>,508 sender: &T::CrossAccountId,509 user: &T::CrossAccountId,510 allowed: bool,511 ) -> DispatchResult {512 collection.check_is_owner_or_admin(sender)?;513514 // =========515516 if allowed {517 <Allowlist<T>>::insert((collection.id, user), true);518 } else {519 <Allowlist<T>>::remove((collection.id, user));520 }521522 Ok(())523 }524525 pub fn toggle_admin(526 collection: &CollectionHandle<T>,527 sender: &T::CrossAccountId,528 user: &T::CrossAccountId,529 admin: bool,530 ) -> DispatchResult {531 collection.check_is_owner_or_admin(sender)?;532533 let was_admin = <IsAdmin<T>>::get((collection.id, user));534 if was_admin == admin {535 return Ok(());536 }537 let amount = <AdminAmount<T>>::get(collection.id);538539 if admin {540 let amount = amount541 .checked_add(1)542 .ok_or(<Error<T>>::CollectionAdminCountExceeded)?;543 ensure!(544 amount <= Self::collection_admins_limit(),545 <Error<T>>::CollectionAdminCountExceeded,546 );547548 // =========549550 <AdminAmount<T>>::insert(collection.id, amount);551 <IsAdmin<T>>::insert((collection.id, user), true);552 } else {553 <AdminAmount<T>>::insert(collection.id, amount.saturating_sub(1));554 <IsAdmin<T>>::remove((collection.id, user));555 }556557 Ok(())558 }559560 pub fn clamp_limits(561 mode: CollectionMode,562 old_limit: &CollectionLimits,563 mut new_limit: CollectionLimits,564 ) -> Result<CollectionLimits, DispatchError> {565 macro_rules! limit_default {566 ($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{567 $(568 if let Some($new) = $new.$field {569 let $old = $old.$field($($arg)?);570 let _ = $new;571 let _ = $old;572 $check573 } else {574 $new.$field = $old.$field575 }576 )*577 }};578 }579580 limit_default!(old_limit, new_limit,581 account_token_ownership_limit => ensure!(582 new_limit <= MAX_TOKEN_OWNERSHIP,583 <Error<T>>::CollectionLimitBoundsExceeded,584 ),585 sponsor_transfer_timeout(match mode {586 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,587 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,588 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,589 }) => ensure!(590 new_limit <= MAX_SPONSOR_TIMEOUT,591 <Error<T>>::CollectionLimitBoundsExceeded,592 ),593 sponsored_data_size => ensure!(594 new_limit <= CUSTOM_DATA_LIMIT,595 <Error<T>>::CollectionLimitBoundsExceeded,596 ),597 token_limit => ensure!(598 old_limit >= new_limit && new_limit > 0,599 <Error<T>>::CollectionTokenLimitExceeded600 ),601 owner_can_transfer => ensure!(602 old_limit || !new_limit,603 <Error<T>>::OwnerPermissionsCantBeReverted,604 ),605 owner_can_destroy => ensure!(606 old_limit || !new_limit,607 <Error<T>>::OwnerPermissionsCantBeReverted,608 ),609 sponsored_data_rate_limit => {},610 transfers_enabled => {},611 );612 Ok(new_limit)613 }614}615616#[macro_export]617macro_rules! unsupported {618 () => {619 Err(<Error<T>>::UnsupportedOperation.into())620 };621}622623/// Worst cases624pub trait CommonWeightInfo {625 fn create_item() -> Weight;626 fn create_multiple_items(amount: u32) -> Weight;627 fn burn_item() -> Weight;628 fn transfer() -> Weight;629 fn approve() -> Weight;630 fn transfer_from() -> Weight;631 fn burn_from() -> Weight;632 fn set_variable_metadata(bytes: u32) -> Weight;633}634635pub trait CommonCollectionOperations<T: Config> {636 fn create_item(637 &self,638 sender: T::CrossAccountId,639 to: T::CrossAccountId,640 data: CreateItemData,641 ) -> DispatchResultWithPostInfo;642 fn create_multiple_items(643 &self,644 sender: T::CrossAccountId,645 to: T::CrossAccountId,646 data: Vec<CreateItemData>,647 ) -> DispatchResultWithPostInfo;648 fn burn_item(649 &self,650 sender: T::CrossAccountId,651 token: TokenId,652 amount: u128,653 ) -> DispatchResultWithPostInfo;654655 fn transfer(656 &self,657 sender: T::CrossAccountId,658 to: T::CrossAccountId,659 token: TokenId,660 amount: u128,661 ) -> DispatchResultWithPostInfo;662 fn approve(663 &self,664 sender: T::CrossAccountId,665 spender: T::CrossAccountId,666 token: TokenId,667 amount: u128,668 ) -> DispatchResultWithPostInfo;669 fn transfer_from(670 &self,671 sender: T::CrossAccountId,672 from: T::CrossAccountId,673 to: T::CrossAccountId,674 token: TokenId,675 amount: u128,676 ) -> DispatchResultWithPostInfo;677 fn burn_from(678 &self,679 sender: T::CrossAccountId,680 from: T::CrossAccountId,681 token: TokenId,682 amount: u128,683 ) -> DispatchResultWithPostInfo;684685 fn set_variable_metadata(686 &self,687 sender: T::CrossAccountId,688 token: TokenId,689 data: BoundedVec<u8, CustomDataLimit>,690 ) -> DispatchResultWithPostInfo;691692 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;693 fn token_exists(&self, token: TokenId) -> bool;694 fn last_token_id(&self) -> TokenId;695696 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;697 fn const_metadata(&self, token: TokenId) -> Vec<u8>;698 fn variable_metadata(&self, token: TokenId) -> Vec<u8>;699700 /// How many tokens collection contains (Applicable to nonfungible/refungible)701 fn collection_tokens(&self) -> u32;702 /// Amount of different tokens account has (Applicable to nonfungible/refungible)703 fn account_balance(&self, account: T::CrossAccountId) -> u32;704 /// Amount of specific token account have (Applicable to fungible/refungible)705 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;706 fn allowance(707 &self,708 sender: T::CrossAccountId,709 spender: T::CrossAccountId,710 token: TokenId,711 ) -> u128;712}713714// Flexible enough for implementing CommonCollectionOperations715pub fn with_weight(res: DispatchResult, weight: Weight) -> DispatchResultWithPostInfo {716 let post_info = PostDispatchInfo {717 actual_weight: Some(weight),718 pays_fee: Pays::Yes,719 };720 match res {721 Ok(()) => Ok(post_info),722 Err(error) => Err(DispatchErrorWithPostInfo { post_info, error }),723 }724}primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -64,7 +64,7 @@
// Schema limits
pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;
pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;
-pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 1048576;
+pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;
pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;
pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;
runtime/src/lib.rsdiffbeforeafterboth--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -250,8 +250,13 @@
pub const SS58Prefix: u8 = 42;
}
+/*
+8880 - Unique
+8881 - Quartz
+8882 - Opal
+*/
parameter_types! {
- pub const ChainId: u64 = 8888;
+ pub const ChainId: u64 = 8882;
}
pub struct FixedFee;
@@ -874,7 +879,7 @@
parameter_types! {
pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account();
- pub const CollectionCreationPrice: Balance = 100 * UNIQUE;
+ pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
}
impl pallet_common::Config for Runtime {