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

difftreelog

refactor(nonfungible) merge TokenData & Owner

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

3 files changed

modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
190 }190 }
191191
192 fn token_owner(&self, token: TokenId) -> T::CrossAccountId {192 fn token_owner(&self, token: TokenId) -> T::CrossAccountId {
193 <Owner<T>>::get((self.id, token))193 <TokenData<T>>::get((self.id, token))
194 .map(|t| t.owner)
195 .unwrap_or_default()
194 }196 }
195 fn const_metadata(&self, token: TokenId) -> Vec<u8> {197 fn const_metadata(&self, token: TokenId) -> Vec<u8> {
196 <TokenData<T>>::get((self.id, token, DataKind::Constant))198 <TokenData<T>>::get((self.id, token))
199 .map(|t| t.const_data.clone())
200 .unwrap_or_default()
197 }201 }
198 fn variable_metadata(&self, token: TokenId) -> Vec<u8> {202 fn variable_metadata(&self, token: TokenId) -> Vec<u8> {
199 <TokenData<T>>::get((self.id, token, DataKind::Variable))203 <TokenData<T>>::get((self.id, token))
204 .map(|t| t.variable_data.clone())
205 .unwrap_or_default()
200 }206 }
201207
202 fn collection_tokens(&self) -> u32 {208 fn collection_tokens(&self) -> u32 {
208 }214 }
209215
210 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {216 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128 {
211 if <Owner<T>>::get((self.id, token)) == account {217 if <TokenData<T>>::get((self.id, token))
218 .map(|a| a.owner == account)
219 .unwrap_or(false)
220 {
212 1221 1
213 } else {222 } else {
221 spender: T::CrossAccountId,230 spender: T::CrossAccountId,
222 token: TokenId,231 token: TokenId,
223 ) -> u128 {232 ) -> u128 {
224 if <Owner<T>>::get((self.id, token)) != sender {233 if <TokenData<T>>::get((self.id, token))
234 .map(|a| a.owner == sender)
235 .unwrap_or(false)
236 {
225 0237 0
226 } else if <Allowance<T>>::get((self.id, token)) == Some(spender) {238 } else if <Allowance<T>>::get((self.id, token)) == Some(spender) {
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
13use pallet_common::erc::PrecompileOutput;13use pallet_common::erc::PrecompileOutput;
1414
15use crate::{15use crate::{
16 AccountBalance, Config, CreateItemData, DataKind, NonfungibleHandle, Owner, Pallet, TokenData,16 AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,
17 TokensMinted,
18};17};
1918
67 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;66 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
68 Ok(string::from_utf8_lossy(&<TokenData<T>>::get((67 Ok(string::from_utf8_lossy(
69 self.id,68 &<TokenData<T>>::get((self.id, token_id))
70 token_id,69 .ok_or("token not found")?
71 DataKind::Constant,70 .const_data,
72 )))71 )
73 .into())72 .into())
74 }73 }
99 }98 }
100 fn owner_of(&self, token_id: uint256) -> Result<address> {99 fn owner_of(&self, token_id: uint256) -> Result<address> {
101 let token: TokenId = token_id.try_into()?;100 let token: TokenId = token_id.try_into()?;
102 Ok(*<Owner<T>>::get((self.id, token)).as_eth())101 Ok(*<TokenData<T>>::get((self.id, token))
102 .ok_or("token not found")?
103 .owner
104 .as_eth())
103 }105 }
104 fn safe_transfer_from_with_data(106 fn safe_transfer_from_with_data(
302 fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {304 fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {
303 let token: TokenId = token_id.try_into()?;305 let token: TokenId = token_id.try_into()?;
304306
305 Ok(<TokenData<T>>::get((self.id, token, DataKind::Variable)))307 Ok(<TokenData<T>>::get((self.id, token))
308 .ok_or("token not found")?
309 .variable_data)
306 }310 }
307311
308 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {312 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
13use 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};
1617
17pub 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;
30
31#[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}
2937
30#[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;
3644
58 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>;
60
61 #[derive(Encode, Decode)]
62 pub enum DataKind {
63 Constant,
64 Variable,
65 }
6668
67 #[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 >;
7775
78 #[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 account
85 #[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>>::NoPermission
146 );
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>>::TokenNotFound
157 );
158 Ok(owner)
159 }
160}130}
161131
162// unchecked calls skips any permission checks132// unchecked calls skips any permission checks
174144
175 PalletCommon::destroy_collection(collection.0, sender)?;145 PalletCommon::destroy_collection(collection.0, sender)?;
176146
177 <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 == sender
195 || (collection.limits.owner_can_transfer165 || (collection.limits.owner_can_transfer
196 && collection.is_owner_or_admin(sender)?),166 && collection.is_owner_or_admin(sender)?),
197 <CommonError<T>>::NoPermission167 <CommonError<T>>::NoPermission
207177
208 // =========178 // =========
209179
210 <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));
184
185 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 }
215194
216 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>>::TransferNotAllowed
239 );218 );
240219
241 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 == from
244 || (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>>::NoPermission
246 );226 );
274254
275 // =========255 // =========
256
257 <TokenData<T>>::insert(
258 (collection.id, token),
259 ItemData {
260 owner: to.clone(),
261 ..token_data
262 },
263 );
276264
277 if let Some(balance_to) = balance_to {265 if let Some(balance_to) = balance_to {
278 // from != to266 // from != to
286 <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);
290277
291 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;
368355
369 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);
380365
381 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>>::CantApproveMoreThanOwned
515 data.len() as u32 <= CUSTOM_DATA_LIMIT,507 data.len() as u32 <= CUSTOM_DATA_LIMIT,
516 <CommonError<T>>::TokenVariableDataLimitExceeded508 <CommonError<T>>::TokenVariableDataLimitExceeded
517 );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)?;
520513
521 collection.consume_sstore()?;514 collection.consume_sstore()?;
522515
523 // =========516 // =========
524517
525 <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_data
523 },
524 );
526 Ok(())525 Ok(())
527 }526 }