difftreelog
refactor(nonfungible) merge TokenData & Owner
in: master
3 files changed
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -190,13 +190,19 @@
}
fn token_owner(&self, token: TokenId) -> T::CrossAccountId {
- <Owner<T>>::get((self.id, token))
+ <TokenData<T>>::get((self.id, token))
+ .map(|t| t.owner)
+ .unwrap_or_default()
}
fn const_metadata(&self, token: TokenId) -> Vec<u8> {
- <TokenData<T>>::get((self.id, token, DataKind::Constant))
+ <TokenData<T>>::get((self.id, token))
+ .map(|t| t.const_data.clone())
+ .unwrap_or_default()
}
fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
- <TokenData<T>>::get((self.id, token, DataKind::Variable))
+ <TokenData<T>>::get((self.id, token))
+ .map(|t| t.variable_data.clone())
+ .unwrap_or_default()
}
fn collection_tokens(&self) -> u32 {
@@ -208,7 +214,10 @@
}
fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {
- if <Owner<T>>::get((self.id, token)) == account {
+ if <TokenData<T>>::get((self.id, token))
+ .map(|a| a.owner == account)
+ .unwrap_or(false)
+ {
1
} else {
0
@@ -221,7 +230,10 @@
spender: T::CrossAccountId,
token: TokenId,
) -> u128 {
- if <Owner<T>>::get((self.id, token)) != sender {
+ if <TokenData<T>>::get((self.id, token))
+ .map(|a| a.owner == sender)
+ .unwrap_or(false)
+ {
0
} else if <Allowance<T>>::get((self.id, token)) == Some(spender) {
1
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -13,8 +13,7 @@
use pallet_common::erc::PrecompileOutput;
use crate::{
- AccountBalance, Config, CreateItemData, DataKind, NonfungibleHandle, Owner, Pallet, TokenData,
- TokensMinted,
+ AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,
};
#[derive(ToLog)]
@@ -65,11 +64,11 @@
#[solidity(rename_selector = "tokenURI")]
fn token_uri(&self, token_id: uint256) -> Result<string> {
let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
- Ok(string::from_utf8_lossy(&<TokenData<T>>::get((
- self.id,
- token_id,
- DataKind::Constant,
- )))
+ Ok(string::from_utf8_lossy(
+ &<TokenData<T>>::get((self.id, token_id))
+ .ok_or("token not found")?
+ .const_data,
+ )
.into())
}
}
@@ -99,7 +98,10 @@
}
fn owner_of(&self, token_id: uint256) -> Result<address> {
let token: TokenId = token_id.try_into()?;
- Ok(*<Owner<T>>::get((self.id, token)).as_eth())
+ Ok(*<TokenData<T>>::get((self.id, token))
+ .ok_or("token not found")?
+ .owner
+ .as_eth())
}
fn safe_transfer_from_with_data(
&mut self,
@@ -302,7 +304,9 @@
fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {
let token: TokenId = token_id.try_into()?;
- Ok(<TokenData<T>>::get((self.id, token, DataKind::Variable)))
+ Ok(<TokenData<T>>::get((self.id, token))
+ .ok_or("token not found")?
+ .variable_data)
}
fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
pallets/nonfungible/src/lib.rsdiffbeforeafterboth13use sp_std::{vec::Vec, vec};13use sp_std::{vec::Vec, vec};14use core::ops::Deref;14use core::ops::Deref;15use sp_std::collections::btree_map::BTreeMap;15use sp_std::collections::btree_map::BTreeMap;16use codec::{Encode, Decode};161717pub use pallet::*;18pub use pallet::*;18pub mod benchmarking;19pub mod benchmarking;27}28}28pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;29pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;3031#[derive(Encode, Decode)]32pub struct ItemData<T: Config> {33 pub const_data: Vec<u8>,34 pub variable_data: Vec<u8>,35 pub owner: T::CrossAccountId,36}293730#[frame_support::pallet]38#[frame_support::pallet]31pub mod pallet {39pub mod pallet {40 use super::*;32 use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};41 use frame_support::{Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key};33 use sp_std::vec::Vec;34 use nft_data_structs::{CollectionId, TokenId};42 use nft_data_structs::{CollectionId, TokenId};35 use super::weights::WeightInfo;43 use super::weights::WeightInfo;364458 pub(super) type TokensBurnt<T: Config> =66 pub(super) type TokensBurnt<T: Config> =59 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;67 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;6061 #[derive(Encode, Decode)]62 pub enum DataKind {63 Constant,64 Variable,65 }666867 #[pallet::storage]69 #[pallet::storage]68 pub(super) type TokenData<T: Config> = StorageNMap<70 pub(super) type TokenData<T: Config> = StorageNMap<69 Key = (71 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),70 Key<Twox64Concat, CollectionId>,71 Key<Twox64Concat, TokenId>,72 Key<Identity, DataKind>,73 ),74 Value = Vec<u8>,72 Value = ItemData<T>,75 QueryKind = ValueQuery,73 QueryKind = OptionQuery,76 >;74 >;777578 #[pallet::storage]79 pub(super) type Owner<T: Config> = StorageNMap<80 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),81 Value = T::CrossAccountId,82 QueryKind = ValueQuery,83 >;84 /// Used to enumerate tokens owned by account76 /// Used to enumerate tokens owned by account85 #[pallet::storage]77 #[pallet::storage]86 pub(super) type Owned<T: Config> = StorageNMap<78 pub(super) type Owned<T: Config> = StorageNMap<133 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)125 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)134 }126 }135 pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {127 pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {136 <Owner<T>>::contains_key((collection.id, token))128 <TokenData<T>>::contains_key((collection.id, token))137 }129 }138 pub fn ensure_owner(139 collection: &NonfungibleHandle<T>,140 token: TokenId,141 sender: &T::CrossAccountId,142 ) -> DispatchResult {143 ensure!(144 &<Owner<T>>::get((collection.id, token)) == sender,145 <CommonError<T>>::NoPermission146 );147 Ok(())148 }149 pub fn item_owner(150 collection: &NonfungibleHandle<T>,151 token: TokenId,152 ) -> Result<T::CrossAccountId, DispatchError> {153 let owner = <Owner<T>>::get((collection.id, token));154 ensure!(155 owner != T::CrossAccountId::default(),156 <CommonError<T>>::TokenNotFound157 );158 Ok(owner)159 }160}130}161131162// unchecked calls skips any permission checks132// unchecked calls skips any permission checks174144175 PalletCommon::destroy_collection(collection.0, sender)?;145 PalletCommon::destroy_collection(collection.0, sender)?;176146177 <Owner<T>>::remove_prefix((id,), None);147 <TokenData<T>>::remove_prefix((id,), None);178 <Owned<T>>::remove_prefix((id,), None);148 <Owned<T>>::remove_prefix((id,), None);179 <TokensMinted<T>>::remove(id);149 <TokensMinted<T>>::remove(id);180 <TokensBurnt<T>>::remove(id);150 <TokensBurnt<T>>::remove(id);181 <TokenData<T>>::remove_prefix((id,), None);182 <Allowance<T>>::remove_prefix((id,), None);151 <Allowance<T>>::remove_prefix((id,), None);183 <AccountBalance<T>>::remove_prefix((id,), None);152 <AccountBalance<T>>::remove_prefix((id,), None);184 Ok(())153 Ok(())189 sender: &T::CrossAccountId,158 sender: &T::CrossAccountId,190 token: TokenId,159 token: TokenId,191 ) -> DispatchResult {160 ) -> DispatchResult {192 let token_owner = <Pallet<T>>::item_owner(collection, token)?;161 let token_data = <TokenData<T>>::get((collection.id, token))162 .ok_or_else(|| <CommonError<T>>::TokenNotFound)?;193 ensure!(163 ensure!(194 &token_owner == sender164 &token_data.owner == sender195 || (collection.limits.owner_can_transfer165 || (collection.limits.owner_can_transfer196 && collection.is_owner_or_admin(sender)?),166 && collection.is_owner_or_admin(sender)?),197 <CommonError<T>>::NoPermission167 <CommonError<T>>::NoPermission207177208 // =========178 // =========209179210 <Owner<T>>::remove((collection.id, token));211 <Owned<T>>::remove((collection.id, token_owner.as_sub(), token));180 <Owned<T>>::remove((collection.id, token_data.owner.as_sub(), token));212 <TokensBurnt<T>>::insert(collection.id, burnt);181 <TokensBurnt<T>>::insert(collection.id, burnt);213 <TokenData<T>>::remove_prefix((collection.id, token), None);182 <TokenData<T>>::remove((collection.id, token));214 <Allowance<T>>::remove((collection.id, token));183 let old_spender = <Allowance<T>>::take((collection.id, token));184185 if let Some(old_spender) = old_spender {186 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(187 collection.id,188 token,189 sender.clone(),190 old_spender.clone(),191 0,192 ));193 }215194216 collection.log_infallible(ERC721Events::Transfer {195 collection.log_infallible(ERC721Events::Transfer {217 from: *token_owner.as_eth(),196 from: *token_data.owner.as_eth(),218 to: H160::default(),197 to: H160::default(),219 token_id: token.into(),198 token_id: token.into(),220 });199 });221 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(200 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(222 collection.id,201 collection.id,223 token,202 token,224 token_owner,203 token_data.owner,225 1,204 1,226 ));205 ));227 return Ok(());206 return Ok(());238 <CommonError<T>>::TransferNotAllowed217 <CommonError<T>>::TransferNotAllowed239 );218 );240219241 let token_owner = <Pallet<T>>::item_owner(collection, token)?;220 let token_data = <TokenData<T>>::get((collection.id, token))221 .ok_or_else(|| <CommonError<T>>::TokenNotFound)?;242 ensure!(222 ensure!(243 &token_owner == from223 &token_data.owner == from244 || (collection.limits.owner_can_transfer && collection.is_owner_or_admin(from)?),224 || (collection.limits.owner_can_transfer && collection.is_owner_or_admin(from)?),245 <CommonError<T>>::NoPermission225 <CommonError<T>>::NoPermission246 );226 );274254275 // =========255 // =========256257 <TokenData<T>>::insert(258 (collection.id, token),259 ItemData {260 owner: to.clone(),261 ..token_data262 },263 );276264277 if let Some(balance_to) = balance_to {265 if let Some(balance_to) = balance_to {278 // from != to266 // from != to286 <Owned<T>>::insert((collection.id, to.as_sub(), token), true);274 <Owned<T>>::insert((collection.id, to.as_sub(), token), true);287 }275 }288 Self::set_allowance_unchecked(collection, from, token, None);276 Self::set_allowance_unchecked(collection, from, token, None);289 <Owner<T>>::insert((collection.id, token), &to);290277291 collection.log_infallible(ERC721Events::Transfer {278 collection.log_infallible(ERC721Events::Transfer {292 from: *from.as_eth(),279 from: *from.as_eth(),364 <AccountBalance<T>>::insert((collection.id, account), balance);351 <AccountBalance<T>>::insert((collection.id, account), balance);365 }352 }366 for (i, data) in data.into_iter().enumerate() {353 for (i, data) in data.into_iter().enumerate() {367 let token = first_token + i as u32;354 let token = first_token + i as u32 + 1;368355369 if !data.const_data.is_empty() {370 <TokenData<T>>::insert((collection.id, token, DataKind::Constant), data.const_data);371 }372 if !data.variable_data.is_empty() {373 <TokenData<T>>::insert(356 <TokenData<T>>::insert(374 (collection.id, token, DataKind::Variable),357 (collection.id, token),358 ItemData {359 const_data: data.const_data.into(),375 data.variable_data,360 variable_data: data.variable_data.into(),361 owner: data.owner.clone(),362 },376 );363 );377 }378 <Owner<T>>::insert((collection.id, token), &data.owner);379 <Owned<T>>::insert((collection.id, data.owner.as_sub(), token), true);364 <Owned<T>>::insert((collection.id, data.owner.as_sub(), token), true);380365381 collection.log_infallible(ERC721Events::Transfer {366 collection.log_infallible(ERC721Events::Transfer {382 from: H160::default(),367 from: H160::default(),383 to: *data.owner.as_eth(),368 to: *data.owner.as_eth(),384 token_id: token.into(),369 token_id: token.into(),385 });370 });371 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(372 collection.id,373 TokenId(token),374 data.owner.clone(),375 1,376 ));386 }377 }387 Ok(())378 Ok(())388 }379 }462 if let Some(spender) = spender {453 if let Some(spender) = spender {463 <PalletCommon<T>>::ensure_correct_receiver(spender)?;454 <PalletCommon<T>>::ensure_correct_receiver(spender)?;464 }455 }465 let token_owner = Self::item_owner(collection, token)?;456 let token_data =457 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;466 if &token_owner != sender {458 if &token_data.owner != sender {467 ensure!(459 ensure!(468 collection.ignores_owned_amount(sender)?,460 collection.ignores_owned_amount(sender)?,469 <CommonError<T>>::CantApproveMoreThanOwned461 <CommonError<T>>::CantApproveMoreThanOwned515 data.len() as u32 <= CUSTOM_DATA_LIMIT,507 data.len() as u32 <= CUSTOM_DATA_LIMIT,516 <CommonError<T>>::TokenVariableDataLimitExceeded508 <CommonError<T>>::TokenVariableDataLimitExceeded517 );509 );518 let item_owner = Self::item_owner(collection, token)?;510 let token_data =511 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;519 collection.check_can_update_meta(sender, &item_owner)?;512 collection.check_can_update_meta(sender, &token_data.owner)?;520513521 collection.consume_sstore()?;514 collection.consume_sstore()?;522515523 // =========516 // =========524517525 <TokenData<T>>::insert((collection.id, token, DataKind::Variable), data);518 <TokenData<T>>::insert(519 (collection.id, token),520 ItemData {521 variable_data: data,522 ..token_data523 },524 );526 Ok(())525 Ok(())527 }526 }