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.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -228,6 +228,15 @@
fail!(<Error<T>>::FungibleItemsDontHaveData)
}
+ fn nest_token(
+ &self,
+ _sender: <T>::CrossAccountId,
+ _from: (up_data_structs::CollectionId, TokenId),
+ _under: TokenId,
+ ) -> sp_runtime::DispatchResult {
+ fail!(<Error<T>>::FungibleDisallowsNesting)
+ }
+
fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {
if <Balance<T>>::get((self.id, account)) != 0 {
vec![TokenId::default()]
pallets/fungible/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::ops::Deref;20use frame_support::{ensure};21use up_data_structs::{AccessMode, CollectionId, TokenId, CreateCollectionData};22use pallet_common::{Error as CommonError, Event as CommonEvent, Pallet as PalletCommon};23use pallet_evm::account::CrossAccountId;24use pallet_evm_coder_substrate::WithRecorder;25use sp_core::H160;26use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};27use sp_std::collections::btree_map::BTreeMap;2829pub use pallet::*;3031use crate::erc::ERC20Events;32#[cfg(feature = "runtime-benchmarks")]33pub mod benchmarking;34pub mod common;35pub mod erc;36pub mod weights;3738pub type CreateItemData<T> = (<T as pallet_evm::account::Config>::CrossAccountId, u128);39pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;4041#[frame_support::pallet]42pub mod pallet {43 use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};44 use up_data_structs::CollectionId;45 use super::weights::WeightInfo;4647 #[pallet::error]48 pub enum Error<T> {49 /// Not Fungible item data used to mint in Fungible collection.50 NotFungibleDataUsedToMintFungibleCollectionToken,51 /// Not default id passed as TokenId argument52 FungibleItemsHaveNoId,53 /// Tried to set data for fungible item54 FungibleItemsDontHaveData,55 }5657 #[pallet::config]58 pub trait Config: frame_system::Config + pallet_common::Config {59 type WeightInfo: WeightInfo;60 }6162 #[pallet::pallet]63 #[pallet::generate_store(pub(super) trait Store)]64 pub struct Pallet<T>(_);6566 #[pallet::storage]67 pub type TotalSupply<T: Config> =68 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u128, QueryKind = ValueQuery>;6970 #[pallet::storage]71 pub type Balance<T: Config> = StorageNMap<72 Key = (73 Key<Twox64Concat, CollectionId>,74 Key<Blake2_128Concat, T::CrossAccountId>,75 ),76 Value = u128,77 QueryKind = ValueQuery,78 >;7980 #[pallet::storage]81 pub type Allowance<T: Config> = StorageNMap<82 Key = (83 Key<Twox64Concat, CollectionId>,84 Key<Blake2_128, T::CrossAccountId>,85 Key<Blake2_128Concat, T::CrossAccountId>,86 ),87 Value = u128,88 QueryKind = ValueQuery,89 >;90}9192pub struct FungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);93impl<T: Config> FungibleHandle<T> {94 pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {95 Self(inner)96 }97 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {98 self.099 }100}101impl<T: Config> WithRecorder<T> for FungibleHandle<T> {102 fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {103 self.0.recorder()104 }105 fn into_recorder(self) -> pallet_evm_coder_substrate::SubstrateRecorder<T> {106 self.0.into_recorder()107 }108}109impl<T: Config> Deref for FungibleHandle<T> {110 type Target = pallet_common::CollectionHandle<T>;111112 fn deref(&self) -> &Self::Target {113 &self.0114 }115}116117impl<T: Config> Pallet<T> {118 pub fn init_collection(119 owner: T::AccountId,120 data: CreateCollectionData<T::AccountId>,121 ) -> Result<CollectionId, DispatchError> {122 <PalletCommon<T>>::init_collection(owner, data)123 }124 pub fn destroy_collection(125 collection: FungibleHandle<T>,126 sender: &T::CrossAccountId,127 ) -> DispatchResult {128 let id = collection.id;129130 // =========131132 PalletCommon::destroy_collection(collection.0, sender)?;133134 <TotalSupply<T>>::remove(id);135 <Balance<T>>::remove_prefix((id,), None);136 <Allowance<T>>::remove_prefix((id,), None);137 Ok(())138 }139140 pub fn burn(141 collection: &FungibleHandle<T>,142 owner: &T::CrossAccountId,143 amount: u128,144 ) -> DispatchResult {145 let total_supply = <TotalSupply<T>>::get(collection.id)146 .checked_sub(amount)147 .ok_or(<CommonError<T>>::TokenValueTooLow)?;148149 let balance = <Balance<T>>::get((collection.id, owner))150 .checked_sub(amount)151 .ok_or(<CommonError<T>>::TokenValueTooLow)?;152153 if collection.access == AccessMode::AllowList {154 collection.check_allowlist(owner)?;155 }156157 // =========158159 if balance == 0 {160 <Balance<T>>::remove((collection.id, owner));161 } else {162 <Balance<T>>::insert((collection.id, owner), balance);163 }164 <TotalSupply<T>>::insert(collection.id, total_supply);165166 collection.log_mirrored(ERC20Events::Transfer {167 from: *owner.as_eth(),168 to: H160::default(),169 value: amount.into(),170 });171 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(172 collection.id,173 TokenId::default(),174 owner.clone(),175 amount,176 ));177 Ok(())178 }179180 pub fn transfer(181 collection: &FungibleHandle<T>,182 from: &T::CrossAccountId,183 to: &T::CrossAccountId,184 amount: u128,185 ) -> DispatchResult {186 ensure!(187 collection.limits.transfers_enabled(),188 <CommonError<T>>::TransferNotAllowed,189 );190191 if collection.access == AccessMode::AllowList {192 collection.check_allowlist(from)?;193 collection.check_allowlist(to)?;194 }195 <PalletCommon<T>>::ensure_correct_receiver(to)?;196197 let balance_from = <Balance<T>>::get((collection.id, from))198 .checked_sub(amount)199 .ok_or(<CommonError<T>>::TokenValueTooLow)?;200 let balance_to = if from != to {201 Some(202 <Balance<T>>::get((collection.id, to))203 .checked_add(amount)204 .ok_or(ArithmeticError::Overflow)?,205 )206 } else {207 None208 };209210 // =========211212 if let Some(balance_to) = balance_to {213 // from != to214 if balance_from == 0 {215 <Balance<T>>::remove((collection.id, from));216 } else {217 <Balance<T>>::insert((collection.id, from), balance_from);218 }219 <Balance<T>>::insert((collection.id, to), balance_to);220 }221222 collection.log_mirrored(ERC20Events::Transfer {223 from: *from.as_eth(),224 to: *to.as_eth(),225 value: amount.into(),226 });227 <PalletCommon<T>>::deposit_event(CommonEvent::Transfer(228 collection.id,229 TokenId::default(),230 from.clone(),231 to.clone(),232 amount,233 ));234 Ok(())235 }236237 pub fn create_multiple_items(238 collection: &FungibleHandle<T>,239 sender: &T::CrossAccountId,240 data: BTreeMap<T::CrossAccountId, u128>,241 ) -> DispatchResult {242 if !collection.is_owner_or_admin(sender) {243 ensure!(244 collection.mint_mode,245 <CommonError<T>>::PublicMintingNotAllowed246 );247 collection.check_allowlist(sender)?;248249 for (owner, _) in data.iter() {250 collection.check_allowlist(owner)?;251 }252 }253254 let total_supply = data255 .iter()256 .map(|(_, v)| *v)257 .try_fold(<TotalSupply<T>>::get(collection.id), |acc, v| {258 acc.checked_add(v)259 })260 .ok_or(ArithmeticError::Overflow)?;261262 let mut balances = data;263 for (k, v) in balances.iter_mut() {264 *v = <Balance<T>>::get((collection.id, &k))265 .checked_add(*v)266 .ok_or(ArithmeticError::Overflow)?;267 }268269 // =========270271 <TotalSupply<T>>::insert(collection.id, total_supply);272 for (user, amount) in balances {273 <Balance<T>>::insert((collection.id, &user), amount);274275 collection.log_mirrored(ERC20Events::Transfer {276 from: H160::default(),277 to: *user.as_eth(),278 value: amount.into(),279 });280 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(281 collection.id,282 TokenId::default(),283 user.clone(),284 amount,285 ));286 }287288 Ok(())289 }290291 fn set_allowance_unchecked(292 collection: &FungibleHandle<T>,293 owner: &T::CrossAccountId,294 spender: &T::CrossAccountId,295 amount: u128,296 ) {297 if amount == 0 {298 <Allowance<T>>::remove((collection.id, owner, spender));299 } else {300 <Allowance<T>>::insert((collection.id, owner, spender), amount);301 }302303 collection.log_mirrored(ERC20Events::Approval {304 owner: *owner.as_eth(),305 spender: *spender.as_eth(),306 value: amount.into(),307 });308 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(309 collection.id,310 TokenId(0),311 owner.clone(),312 spender.clone(),313 amount,314 ));315 }316317 pub fn set_allowance(318 collection: &FungibleHandle<T>,319 owner: &T::CrossAccountId,320 spender: &T::CrossAccountId,321 amount: u128,322 ) -> DispatchResult {323 if collection.access == AccessMode::AllowList {324 collection.check_allowlist(owner)?;325 collection.check_allowlist(spender)?;326 }327328 if <Balance<T>>::get((collection.id, owner)) < amount {329 ensure!(330 collection.ignores_owned_amount(owner),331 <CommonError<T>>::CantApproveMoreThanOwned332 );333 }334335 // =========336337 Self::set_allowance_unchecked(collection, owner, spender, amount);338 Ok(())339 }340341 pub fn transfer_from(342 collection: &FungibleHandle<T>,343 spender: &T::CrossAccountId,344 from: &T::CrossAccountId,345 to: &T::CrossAccountId,346 amount: u128,347 ) -> DispatchResult {348 if spender.conv_eq(from) {349 return Self::transfer(collection, from, to, amount);350 }351 if collection.access == AccessMode::AllowList {352 // `from`, `to` checked in [`transfer`]353 collection.check_allowlist(spender)?;354 }355356 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);357 if allowance.is_none() {358 ensure!(359 collection.ignores_allowance(spender),360 <CommonError<T>>::ApprovedValueTooLow361 );362 }363364 // =========365366 Self::transfer(collection, from, to, amount)?;367 if let Some(allowance) = allowance {368 Self::set_allowance_unchecked(collection, from, spender, allowance);369 }370 Ok(())371 }372373 pub fn burn_from(374 collection: &FungibleHandle<T>,375 spender: &T::CrossAccountId,376 from: &T::CrossAccountId,377 amount: u128,378 ) -> DispatchResult {379 if spender.conv_eq(from) {380 return Self::burn(collection, from, amount);381 }382 if collection.access == AccessMode::AllowList {383 // `from` checked in [`burn`]384 collection.check_allowlist(spender)?;385 }386387 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);388 if allowance.is_none() {389 ensure!(390 collection.ignores_allowance(spender),391 <CommonError<T>>::ApprovedValueTooLow392 );393 }394395 // =========396397 Self::burn(collection, from, amount)?;398 if let Some(allowance) = allowance {399 Self::set_allowance_unchecked(collection, from, spender, allowance);400 }401 Ok(())402 }403404 /// Delegated to `create_multiple_items`405 pub fn create_item(406 collection: &FungibleHandle<T>,407 sender: &T::CrossAccountId,408 data: CreateItemData<T>,409 ) -> DispatchResult {410 Self::create_multiple_items(collection, sender, [(data.0, data.1)].into_iter().collect())411 }412}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::ops::Deref;20use frame_support::{ensure};21use pallet_evm::account::CrossAccountId;22use up_data_structs::{23 AccessMode, CollectionId, TokenId, CreateCollectionData, mapping::TokenAddressMapping,24};25use pallet_common::{26 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,27 CollectionHandle, dispatch::CollectionDispatch,28};29use pallet_evm_coder_substrate::WithRecorder;30use sp_core::H160;31use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};32use sp_std::collections::btree_map::BTreeMap;3334pub use pallet::*;3536use crate::erc::ERC20Events;37#[cfg(feature = "runtime-benchmarks")]38pub mod benchmarking;39pub mod common;40pub mod erc;41pub mod weights;4243pub type CreateItemData<T> = (<T as pallet_evm::account::Config>::CrossAccountId, u128);44pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;4546#[frame_support::pallet]47pub mod pallet {48 use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};49 use up_data_structs::CollectionId;50 use super::weights::WeightInfo;5152 #[pallet::error]53 pub enum Error<T> {54 /// Not Fungible item data used to mint in Fungible collection.55 NotFungibleDataUsedToMintFungibleCollectionToken,56 /// Not default id passed as TokenId argument57 FungibleItemsHaveNoId,58 /// Tried to set data for fungible item59 FungibleItemsDontHaveData,60 /// Fungible token does not support nested61 FungibleDisallowsNesting,62 }6364 #[pallet::config]65 pub trait Config: frame_system::Config + pallet_common::Config {66 type WeightInfo: WeightInfo;67 }6869 #[pallet::pallet]70 #[pallet::generate_store(pub(super) trait Store)]71 pub struct Pallet<T>(_);7273 #[pallet::storage]74 pub type TotalSupply<T: Config> =75 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u128, QueryKind = ValueQuery>;7677 #[pallet::storage]78 pub type Balance<T: Config> = StorageNMap<79 Key = (80 Key<Twox64Concat, CollectionId>,81 Key<Blake2_128Concat, T::CrossAccountId>,82 ),83 Value = u128,84 QueryKind = ValueQuery,85 >;8687 #[pallet::storage]88 pub type Allowance<T: Config> = StorageNMap<89 Key = (90 Key<Twox64Concat, CollectionId>,91 Key<Blake2_128, T::CrossAccountId>,92 Key<Blake2_128Concat, T::CrossAccountId>,93 ),94 Value = u128,95 QueryKind = ValueQuery,96 >;97}9899pub struct FungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);100impl<T: Config> FungibleHandle<T> {101 pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {102 Self(inner)103 }104 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {105 self.0106 }107}108impl<T: Config> WithRecorder<T> for FungibleHandle<T> {109 fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {110 self.0.recorder()111 }112 fn into_recorder(self) -> pallet_evm_coder_substrate::SubstrateRecorder<T> {113 self.0.into_recorder()114 }115}116impl<T: Config> Deref for FungibleHandle<T> {117 type Target = pallet_common::CollectionHandle<T>;118119 fn deref(&self) -> &Self::Target {120 &self.0121 }122}123124impl<T: Config> Pallet<T> {125 pub fn init_collection(126 owner: T::AccountId,127 data: CreateCollectionData<T::AccountId>,128 ) -> Result<CollectionId, DispatchError> {129 <PalletCommon<T>>::init_collection(owner, data)130 }131 pub fn destroy_collection(132 collection: FungibleHandle<T>,133 sender: &T::CrossAccountId,134 ) -> DispatchResult {135 let id = collection.id;136137 // =========138139 PalletCommon::destroy_collection(collection.0, sender)?;140141 <TotalSupply<T>>::remove(id);142 <Balance<T>>::remove_prefix((id,), None);143 <Allowance<T>>::remove_prefix((id,), None);144 Ok(())145 }146147 pub fn burn(148 collection: &FungibleHandle<T>,149 owner: &T::CrossAccountId,150 amount: u128,151 ) -> DispatchResult {152 let total_supply = <TotalSupply<T>>::get(collection.id)153 .checked_sub(amount)154 .ok_or(<CommonError<T>>::TokenValueTooLow)?;155156 let balance = <Balance<T>>::get((collection.id, owner))157 .checked_sub(amount)158 .ok_or(<CommonError<T>>::TokenValueTooLow)?;159160 if collection.access == AccessMode::AllowList {161 collection.check_allowlist(owner)?;162 }163164 // =========165166 if balance == 0 {167 <Balance<T>>::remove((collection.id, owner));168 } else {169 <Balance<T>>::insert((collection.id, owner), balance);170 }171 <TotalSupply<T>>::insert(collection.id, total_supply);172173 collection.log_mirrored(ERC20Events::Transfer {174 from: *owner.as_eth(),175 to: H160::default(),176 value: amount.into(),177 });178 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(179 collection.id,180 TokenId::default(),181 owner.clone(),182 amount,183 ));184 Ok(())185 }186187 pub fn transfer(188 collection: &FungibleHandle<T>,189 from: &T::CrossAccountId,190 to: &T::CrossAccountId,191 amount: u128,192 ) -> DispatchResult {193 ensure!(194 collection.limits.transfers_enabled(),195 <CommonError<T>>::TransferNotAllowed,196 );197198 if collection.access == AccessMode::AllowList {199 collection.check_allowlist(from)?;200 collection.check_allowlist(to)?;201 }202 <PalletCommon<T>>::ensure_correct_receiver(to)?;203204 let balance_from = <Balance<T>>::get((collection.id, from))205 .checked_sub(amount)206 .ok_or(<CommonError<T>>::TokenValueTooLow)?;207 let balance_to = if from != to {208 Some(209 <Balance<T>>::get((collection.id, to))210 .checked_add(amount)211 .ok_or(ArithmeticError::Overflow)?,212 )213 } else {214 None215 };216217 if let Some(target) = T::CrossTokenAddressMapping::address_to_token(to) {218 let handle = <CollectionHandle<T>>::try_get(target.0)?;219 let dispatch = T::CollectionDispatch::dispatch(handle);220 let dispatch = dispatch.as_dyn();221222 // =========223224 dispatch.nest_token(from.clone(), (collection.id, TokenId::default()), target.1)?;225 }226227 if let Some(balance_to) = balance_to {228 // from != to229 if balance_from == 0 {230 <Balance<T>>::remove((collection.id, from));231 } else {232 <Balance<T>>::insert((collection.id, from), balance_from);233 }234 <Balance<T>>::insert((collection.id, to), balance_to);235 }236237 collection.log_mirrored(ERC20Events::Transfer {238 from: *from.as_eth(),239 to: *to.as_eth(),240 value: amount.into(),241 });242 <PalletCommon<T>>::deposit_event(CommonEvent::Transfer(243 collection.id,244 TokenId::default(),245 from.clone(),246 to.clone(),247 amount,248 ));249 Ok(())250 }251252 pub fn create_multiple_items(253 collection: &FungibleHandle<T>,254 sender: &T::CrossAccountId,255 data: BTreeMap<T::CrossAccountId, u128>,256 ) -> DispatchResult {257 if !collection.is_owner_or_admin(sender) {258 ensure!(259 collection.mint_mode,260 <CommonError<T>>::PublicMintingNotAllowed261 );262 collection.check_allowlist(sender)?;263264 for (owner, _) in data.iter() {265 collection.check_allowlist(owner)?;266 }267 }268269 let total_supply = data270 .iter()271 .map(|(_, v)| *v)272 .try_fold(<TotalSupply<T>>::get(collection.id), |acc, v| {273 acc.checked_add(v)274 })275 .ok_or(ArithmeticError::Overflow)?;276277 let mut balances = data;278 for (k, v) in balances.iter_mut() {279 *v = <Balance<T>>::get((collection.id, &k))280 .checked_add(*v)281 .ok_or(ArithmeticError::Overflow)?;282 }283284 // =========285286 <TotalSupply<T>>::insert(collection.id, total_supply);287 for (user, amount) in balances {288 <Balance<T>>::insert((collection.id, &user), amount);289290 collection.log_mirrored(ERC20Events::Transfer {291 from: H160::default(),292 to: *user.as_eth(),293 value: amount.into(),294 });295 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(296 collection.id,297 TokenId::default(),298 user.clone(),299 amount,300 ));301 }302303 Ok(())304 }305306 fn set_allowance_unchecked(307 collection: &FungibleHandle<T>,308 owner: &T::CrossAccountId,309 spender: &T::CrossAccountId,310 amount: u128,311 ) {312 if amount == 0 {313 <Allowance<T>>::remove((collection.id, owner, spender));314 } else {315 <Allowance<T>>::insert((collection.id, owner, spender), amount);316 }317318 collection.log_mirrored(ERC20Events::Approval {319 owner: *owner.as_eth(),320 spender: *spender.as_eth(),321 value: amount.into(),322 });323 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(324 collection.id,325 TokenId(0),326 owner.clone(),327 spender.clone(),328 amount,329 ));330 }331332 pub fn set_allowance(333 collection: &FungibleHandle<T>,334 owner: &T::CrossAccountId,335 spender: &T::CrossAccountId,336 amount: u128,337 ) -> DispatchResult {338 if collection.access == AccessMode::AllowList {339 collection.check_allowlist(owner)?;340 collection.check_allowlist(spender)?;341 }342343 if <Balance<T>>::get((collection.id, owner)) < amount {344 ensure!(345 collection.ignores_owned_amount(owner),346 <CommonError<T>>::CantApproveMoreThanOwned347 );348 }349350 // =========351352 Self::set_allowance_unchecked(collection, owner, spender, amount);353 Ok(())354 }355356 pub fn transfer_from(357 collection: &FungibleHandle<T>,358 spender: &T::CrossAccountId,359 from: &T::CrossAccountId,360 to: &T::CrossAccountId,361 amount: u128,362 ) -> DispatchResult {363 if spender.conv_eq(from) {364 return Self::transfer(collection, from, to, amount);365 }366 if collection.access == AccessMode::AllowList {367 // `from`, `to` checked in [`transfer`]368 collection.check_allowlist(spender)?;369 }370371 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);372 if allowance.is_none() {373 ensure!(374 collection.ignores_allowance(spender),375 <CommonError<T>>::ApprovedValueTooLow376 );377 }378379 // =========380381 Self::transfer(collection, from, to, amount)?;382 if let Some(allowance) = allowance {383 Self::set_allowance_unchecked(collection, from, spender, allowance);384 }385 Ok(())386 }387388 pub fn burn_from(389 collection: &FungibleHandle<T>,390 spender: &T::CrossAccountId,391 from: &T::CrossAccountId,392 amount: u128,393 ) -> DispatchResult {394 if spender.conv_eq(from) {395 return Self::burn(collection, from, amount);396 }397 if collection.access == AccessMode::AllowList {398 // `from` checked in [`burn`]399 collection.check_allowlist(spender)?;400 }401402 let allowance = <Allowance<T>>::get((collection.id, from, spender)).checked_sub(amount);403 if allowance.is_none() {404 ensure!(405 collection.ignores_allowance(spender),406 <CommonError<T>>::ApprovedValueTooLow407 );408 }409410 // =========411412 Self::burn(collection, from, amount)?;413 if let Some(allowance) = allowance {414 Self::set_allowance_unchecked(collection, from, spender, allowance);415 }416 Ok(())417 }418419 /// Delegated to `create_multiple_items`420 pub fn create_item(421 collection: &FungibleHandle<T>,422 sender: &T::CrossAccountId,423 data: CreateItemData<T>,424 ) -> DispatchResult {425 Self::create_multiple_items(collection, sender, [(data.0, data.1)].into_iter().collect())426 }427}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