git.delta.rocks / unique-network / refs/commits / d54d8c2c28b6

difftreelog

refactor(refungible) merge TokenData

Yaroslav Bolyukin2021-10-22parent: #ed4e1ec.patch.diff
in: master

2 files changed

modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
before · pallets/refungible/src/common.rs
1use core::marker::PhantomData;23use sp_std::collections::btree_map::BTreeMap;4use frame_support::{dispatch::DispatchResultWithPostInfo, fail, weights::Weight};5use nft_data_structs::TokenId;6use pallet_common::{7	CommonCollectionOperations, CommonWeightInfo, account::CrossAccountId, with_weight,8};9use sp_runtime::DispatchError;10use sp_std::vec::Vec;1112use crate::{13	AccountBalance, Allowance, Balance, Config, CreateItemData, DataKind, Error, Owned, Pallet,14	RefungibleHandle, SelfWeightOf, TokenData, weights::WeightInfo,15};1617pub struct CommonWeights<T: Config>(PhantomData<T>);18impl<T: Config> CommonWeightInfo for CommonWeights<T> {19	fn create_item() -> Weight {20		<SelfWeightOf<T>>::create_item()21	}2223	fn create_multiple_items(amount: u32) -> Weight {24		<SelfWeightOf<T>>::create_multiple_items(amount)25	}2627	fn burn_item() -> Weight {28		<SelfWeightOf<T>>::burn_item()29	}3031	fn transfer() -> Weight {32		<SelfWeightOf<T>>::transfer()33	}3435	fn approve() -> Weight {36		<SelfWeightOf<T>>::approve()37	}3839	fn transfer_from() -> Weight {40		<SelfWeightOf<T>>::transfer_from()41	}4243	fn set_variable_metadata(_bytes: u32) -> Weight {44		<SelfWeightOf<T>>::set_variable_metadata()45	}46}4748fn map_create_data<T: Config>(49	data: nft_data_structs::CreateItemData,50	to: &T::CrossAccountId,51) -> Result<CreateItemData<T>, DispatchError> {52	match data {53		nft_data_structs::CreateItemData::ReFungible(data) => Ok(CreateItemData {54			const_data: data.const_data,55			variable_data: data.variable_data,56			users: {57				let mut out = BTreeMap::new();58				out.insert(to.clone(), data.pieces);59				out60			},61		}),62		_ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),63	}64}6566impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {67	fn create_item(68		&self,69		sender: T::CrossAccountId,70		to: T::CrossAccountId,71		data: nft_data_structs::CreateItemData,72	) -> DispatchResultWithPostInfo {73		with_weight(74			<Pallet<T>>::create_item(self, &sender, map_create_data(data, &to)?),75			<SelfWeightOf<T>>::create_item(),76		)77	}7879	fn create_multiple_items(80		&self,81		sender: T::CrossAccountId,82		to: T::CrossAccountId,83		data: Vec<nft_data_structs::CreateItemData>,84	) -> DispatchResultWithPostInfo {85		let data = data86			.into_iter()87			.map(|d| map_create_data::<T>(d, &to))88			.collect::<Result<Vec<_>, DispatchError>>()?;8990		let amount = data.len();91		with_weight(92			<Pallet<T>>::create_multiple_items(self, &sender, data),93			<SelfWeightOf<T>>::create_multiple_items(amount as u32),94		)95	}9697	fn burn_item(98		&self,99		sender: T::CrossAccountId,100		token: TokenId,101		amount: u128,102	) -> DispatchResultWithPostInfo {103		with_weight(104			<Pallet<T>>::burn(self, &sender, token, amount),105			<SelfWeightOf<T>>::burn_item(),106		)107	}108109	fn transfer(110		&self,111		from: T::CrossAccountId,112		to: T::CrossAccountId,113		token: TokenId,114		amount: u128,115	) -> DispatchResultWithPostInfo {116		with_weight(117			<Pallet<T>>::transfer(&self, &from, &to, token, amount),118			<SelfWeightOf<T>>::transfer(),119		)120	}121122	fn approve(123		&self,124		sender: T::CrossAccountId,125		spender: T::CrossAccountId,126		token: TokenId,127		amount: u128,128	) -> DispatchResultWithPostInfo {129		with_weight(130			<Pallet<T>>::set_allowance(&self, &sender, &spender, token, amount),131			<SelfWeightOf<T>>::approve(),132		)133	}134135	fn transfer_from(136		&self,137		sender: T::CrossAccountId,138		from: T::CrossAccountId,139		to: T::CrossAccountId,140		token: TokenId,141		amount: u128,142	) -> DispatchResultWithPostInfo {143		with_weight(144			<Pallet<T>>::transfer_from(&self, &sender, &from, &to, token, amount),145			<SelfWeightOf<T>>::approve(),146		)147	}148149	fn set_variable_metadata(150		&self,151		sender: T::CrossAccountId,152		token: TokenId,153		data: Vec<u8>,154	) -> DispatchResultWithPostInfo {155		with_weight(156			<Pallet<T>>::set_variable_metadata(&self, &sender, token, data),157			<SelfWeightOf<T>>::set_variable_metadata(),158		)159	}160161	fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {162		<Owned<T>>::iter_prefix((self.id, account.as_sub()))163			.map(|(id, _)| id)164			.collect()165	}166167	fn token_exists(&self, token: TokenId) -> bool {168		<Pallet<T>>::token_exists(self, token)169	}170171	fn token_owner(&self, _token: TokenId) -> T::CrossAccountId {172		T::CrossAccountId::default()173	}174	fn const_metadata(&self, token: TokenId) -> Vec<u8> {175		<TokenData<T>>::get((self.id, token, DataKind::Constant))176	}177	fn variable_metadata(&self, token: TokenId) -> Vec<u8> {178		<TokenData<T>>::get((self.id, token, DataKind::Variable))179	}180181	fn collection_tokens(&self) -> u32 {182		<Pallet<T>>::total_supply(self)183	}184185	fn account_balance(&self, account: T::CrossAccountId) -> u32 {186		<AccountBalance<T>>::get((self.id, account.as_sub()))187	}188189	fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {190		<Balance<T>>::get((self.id, token, account.as_sub()))191	}192193	fn allowance(194		&self,195		sender: T::CrossAccountId,196		spender: T::CrossAccountId,197		token: TokenId,198	) -> u128 {199		<Allowance<T>>::get((self.id, token, sender.as_sub(), spender))200	}201}
modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -11,6 +11,7 @@
 use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
 use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
 use core::ops::Deref;
+use codec::{Encode, Decode};
 
 pub use pallet::*;
 pub mod benchmarking;
@@ -24,10 +25,16 @@
 }
 pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;
 
+#[derive(Encode, Decode, Default)]
+pub struct ItemData {
+	pub const_data: Vec<u8>,
+	pub variable_data: Vec<u8>,
+}
+
 #[frame_support::pallet]
 pub mod pallet {
+	use super::*;
 	use frame_support::{Blake2_128, Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};
-	use sp_std::vec::Vec;
 	use nft_data_structs::{CollectionId, TokenId};
 	use super::weights::WeightInfo;
 
@@ -55,20 +62,10 @@
 	pub(super) type TokensBurnt<T: Config> =
 		StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;
 
-	#[derive(Encode, Decode)]
-	pub enum DataKind {
-		Constant,
-		Variable,
-	}
-
 	#[pallet::storage]
 	pub(super) type TokenData<T: Config> = StorageNMap<
-		Key = (
-			Key<Twox64Concat, CollectionId>,
-			Key<Twox64Concat, TokenId>,
-			Key<Identity, DataKind>,
-		),
-		Value = Vec<u8>,
+		Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
+		Value = ItemData,
 		QueryKind = ValueQuery,
 	>;
 
@@ -185,7 +182,7 @@
 			.ok_or(ArithmeticError::Overflow)?;
 
 		<TokensBurnt<T>>::insert(collection.id, burnt);
-		<TokenData<T>>::remove_prefix((collection.id, token_id), None);
+		<TokenData<T>>::remove((collection.id, token_id));
 		<TotalSupply<T>>::remove((collection.id, token_id));
 		<Balance<T>>::remove_prefix((collection.id, token_id), None);
 		<Allowance<T>>::remove_prefix((collection.id, token_id), None);
@@ -210,10 +207,15 @@
 				<Balance<T>>::get((collection.id, token, owner.as_sub())) == amount,
 				<CommonError<T>>::TokenValueTooLow
 			);
+			let account_balance = <AccountBalance<T>>::get((collection.id, owner.as_sub()))
+				.checked_sub(1)
+				// Should not occur
+				.ok_or(ArithmeticError::Underflow)?;
 
 			// =========
 
 			<Owned<T>>::remove((collection.id, owner.as_sub(), token));
+			<AccountBalance<T>>::insert((collection.id, owner.as_sub()), account_balance);
 			Self::burn_token(collection, token)?;
 			<PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(
 				collection.id,
@@ -239,6 +241,7 @@
 		// =========
 
 		if balance == 0 {
+			<Owned<T>>::remove((collection.id, owner.as_sub(), token));
 			<Balance<T>>::remove((collection.id, token, owner.as_sub()));
 			<AccountBalance<T>>::insert((collection.id, owner.as_sub()), account_balance);
 		} else {
@@ -330,13 +333,12 @@
 			<Balance<T>>::insert((collection.id, token, to.as_sub()), balance_to);
 			if let Some(account_balance_from) = account_balance_from {
 				<AccountBalance<T>>::insert((collection.id, from.as_sub()), account_balance_from);
+				<Owned<T>>::remove((collection.id, from.as_sub(), token));
 			}
 			if let Some(account_balance_to) = account_balance_to {
 				<AccountBalance<T>>::insert((collection.id, to.as_sub()), account_balance_to);
+				<Owned<T>>::insert((collection.id, to.as_sub(), token), true);
 			}
-
-			<Owned<T>>::remove((collection.id, from.as_sub(), token));
-			<Owned<T>>::insert((collection.id, to.as_sub(), token), true);
 		}
 
 		// TODO: ERC20 transfer event
@@ -426,21 +428,16 @@
 			<AccountBalance<T>>::insert((collection.id, account), balance);
 		}
 		for (i, token) in data.into_iter().enumerate() {
-			let token_id = first_token_id + i as u32;
+			let token_id = first_token_id + i as u32 + 1;
 			<TotalSupply<T>>::insert((collection.id, token_id), totals[i]);
 
-			if !token.const_data.is_empty() {
-				<TokenData<T>>::insert(
-					(collection.id, token_id, DataKind::Constant),
-					token.const_data,
-				);
-			}
-			if !token.variable_data.is_empty() {
-				<TokenData<T>>::insert(
-					(collection.id, token_id, DataKind::Variable),
-					token.variable_data,
-				);
-			}
+			<TokenData<T>>::insert(
+				(collection.id, token_id),
+				ItemData {
+					const_data: token.const_data.into(),
+					variable_data: token.variable_data.into(),
+				},
+			);
 			for (user, amount) in token.users.into_iter() {
 				if amount == 0 {
 					continue;
@@ -554,10 +551,17 @@
 		)?;
 
 		collection.consume_sstore()?;
+		let token_data = <TokenData<T>>::get((collection.id, token));
 
 		// =========
 
-		<TokenData<T>>::insert((collection.id, token, DataKind::Variable), data);
+		<TokenData<T>>::insert(
+			(collection.id, token),
+			ItemData {
+				variable_data: data,
+				..token_data
+			},
+		);
 		Ok(())
 	}