Skip to content
Snippets Groups Projects
Unverified Commit 58c58c2c authored by zjb0807's avatar zjb0807 Committed by GitHub
Browse files

add feature disable-tokens-by-owner (#323)

parent ce1451d5
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,7 @@ check-tests: githooks ...@@ -6,6 +6,7 @@ check-tests: githooks
test: githooks test: githooks
./scripts/run.sh test ./scripts/run.sh test
cargo test --manifest-path nft/Cargo.toml -p orml-nft --features disable-tokens-by-owner
GITHOOKS_SRC = $(wildcard githooks/*) GITHOOKS_SRC = $(wildcard githooks/*)
GITHOOKS_DEST = $(patsubst githooks/%, $(GITHOOK)/%, $(GITHOOKS_SRC)) GITHOOKS_DEST = $(patsubst githooks/%, $(GITHOOK)/%, $(GITHOOKS_SRC))
...@@ -47,3 +48,4 @@ dev-check-tests: Cargo.toml ...@@ -47,3 +48,4 @@ dev-check-tests: Cargo.toml
dev-test: Cargo.toml dev-test: Cargo.toml
cargo test --all cargo test --all
cargo test --manifest-path nft/Cargo.toml -p orml-nft --features disable-tokens-by-owner
...@@ -28,3 +28,4 @@ std = [ ...@@ -28,3 +28,4 @@ std = [
"frame-support/std", "frame-support/std",
"frame-system/std", "frame-system/std",
] ]
disable-tokens-by-owner = []
...@@ -106,6 +106,7 @@ decl_storage! { ...@@ -106,6 +106,7 @@ decl_storage! {
/// Returns `None` if token info not set or removed. /// Returns `None` if token info not set or removed.
pub Tokens get(fn tokens): double_map hasher(twox_64_concat) T::ClassId, hasher(twox_64_concat) T::TokenId => Option<TokenInfoOf<T>>; pub Tokens get(fn tokens): double_map hasher(twox_64_concat) T::ClassId, hasher(twox_64_concat) T::TokenId => Option<TokenInfoOf<T>>;
/// Token existence check by owner and class ID. /// Token existence check by owner and class ID.
#[cfg(not(feature = "disable-tokens-by-owner"))]
pub TokensByOwner get(fn tokens_by_owner): double_map hasher(twox_64_concat) T::AccountId, hasher(twox_64_concat) (T::ClassId, T::TokenId) => Option<()>; pub TokensByOwner get(fn tokens_by_owner): double_map hasher(twox_64_concat) T::AccountId, hasher(twox_64_concat) (T::ClassId, T::TokenId) => Option<()>;
} }
} }
...@@ -141,21 +142,23 @@ impl<T: Trait> Module<T> { ...@@ -141,21 +142,23 @@ impl<T: Trait> Module<T> {
/// Transfer NFT(non fungible token) from `from` account to `to` account /// Transfer NFT(non fungible token) from `from` account to `to` account
pub fn transfer(from: &T::AccountId, to: &T::AccountId, token: (T::ClassId, T::TokenId)) -> DispatchResult { pub fn transfer(from: &T::AccountId, to: &T::AccountId, token: (T::ClassId, T::TokenId)) -> DispatchResult {
TokensByOwner::<T>::try_mutate_exists(from, token, |token_by_owner| -> DispatchResult { Tokens::<T>::try_mutate(token.0, token.1, |token_info| -> DispatchResult {
ensure!(token_by_owner.is_some(), Error::<T>::NoPermission); let mut info = token_info.as_mut().ok_or(Error::<T>::TokenNotFound)?;
ensure!(info.owner == *from, Error::<T>::NoPermission);
if from == to { if from == to {
// no change needed // no change needed
return Ok(()); return Ok(());
} }
*token_by_owner = None; info.owner = to.clone();
TokensByOwner::<T>::insert(to, token, ());
Tokens::<T>::try_mutate_exists(token.0, token.1, |token_info| -> DispatchResult { #[cfg(not(feature = "disable-tokens-by-owner"))]
let mut info = token_info.as_mut().ok_or(Error::<T>::TokenNotFound)?; {
info.owner = to.clone(); TokensByOwner::<T>::remove(from, token);
Ok(()) TokensByOwner::<T>::insert(to, token, ());
}) }
Ok(())
}) })
} }
...@@ -185,6 +188,7 @@ impl<T: Trait> Module<T> { ...@@ -185,6 +188,7 @@ impl<T: Trait> Module<T> {
data, data,
}; };
Tokens::<T>::insert(class_id, token_id, token_info); Tokens::<T>::insert(class_id, token_id, token_info);
#[cfg(not(feature = "disable-tokens-by-owner"))]
TokensByOwner::<T>::insert(owner, (class_id, token_id), ()); TokensByOwner::<T>::insert(owner, (class_id, token_id), ());
Ok(token_id) Ok(token_id)
...@@ -194,20 +198,22 @@ impl<T: Trait> Module<T> { ...@@ -194,20 +198,22 @@ impl<T: Trait> Module<T> {
/// Burn NFT(non fungible token) from `owner` /// Burn NFT(non fungible token) from `owner`
pub fn burn(owner: &T::AccountId, token: (T::ClassId, T::TokenId)) -> DispatchResult { pub fn burn(owner: &T::AccountId, token: (T::ClassId, T::TokenId)) -> DispatchResult {
Tokens::<T>::try_mutate_exists(token.0, token.1, |token_info| -> DispatchResult { Tokens::<T>::try_mutate_exists(token.0, token.1, |token_info| -> DispatchResult {
ensure!(token_info.take().is_some(), Error::<T>::TokenNotFound); let t = token_info.take().ok_or(Error::<T>::TokenNotFound)?;
ensure!(t.owner == *owner, Error::<T>::NoPermission);
TokensByOwner::<T>::try_mutate_exists(owner, token, |info| -> DispatchResult {
ensure!(info.take().is_some(), Error::<T>::NoPermission); Classes::<T>::try_mutate(token.0, |class_info| -> DispatchResult {
let info = class_info.as_mut().ok_or(Error::<T>::ClassNotFound)?;
Classes::<T>::try_mutate(token.0, |class_info| -> DispatchResult { info.total_issuance = info
let info = class_info.as_mut().ok_or(Error::<T>::ClassNotFound)?; .total_issuance
info.total_issuance = info .checked_sub(&One::one())
.total_issuance .ok_or(Error::<T>::NumOverflow)?;
.checked_sub(&One::one()) Ok(())
.ok_or(Error::<T>::NumOverflow)?; })?;
Ok(())
}) #[cfg(not(feature = "disable-tokens-by-owner"))]
}) TokensByOwner::<T>::remove(owner, token);
Ok(())
}) })
} }
...@@ -225,6 +231,10 @@ impl<T: Trait> Module<T> { ...@@ -225,6 +231,10 @@ impl<T: Trait> Module<T> {
} }
pub fn is_owner(account: &T::AccountId, token: (T::ClassId, T::TokenId)) -> bool { pub fn is_owner(account: &T::AccountId, token: (T::ClassId, T::TokenId)) -> bool {
#[cfg(feature = "disable-tokens-by-owner")]
return Tokens::<T>::get(token.0, token.1).map_or(false, |token| token.owner == *account);
#[cfg(not(feature = "disable-tokens-by-owner"))]
TokensByOwner::<T>::contains_key(account, token) TokensByOwner::<T>::contains_key(account, token)
} }
} }
...@@ -87,7 +87,7 @@ fn transfer_should_fail() { ...@@ -87,7 +87,7 @@ fn transfer_should_fail() {
assert_ok!(NonFungibleTokenModule::mint(&BOB, CLASS_ID, vec![1], ())); assert_ok!(NonFungibleTokenModule::mint(&BOB, CLASS_ID, vec![1], ()));
assert_noop!( assert_noop!(
NonFungibleTokenModule::transfer(&BOB, &ALICE, (CLASS_ID, TOKEN_ID_NOT_EXIST)), NonFungibleTokenModule::transfer(&BOB, &ALICE, (CLASS_ID, TOKEN_ID_NOT_EXIST)),
Error::<Runtime>::NoPermission Error::<Runtime>::TokenNotFound
); );
assert_noop!( assert_noop!(
NonFungibleTokenModule::transfer(&ALICE, &BOB, (CLASS_ID, TOKEN_ID)), NonFungibleTokenModule::transfer(&ALICE, &BOB, (CLASS_ID, TOKEN_ID)),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment