git.delta.rocks / unique-network / refs/commits / 31c0a8fb6eb8

difftreelog

Fix NFTPAR-291 - approval of non-existing token

Greg Zaitsev2021-01-20parent: #517dd9f.patch.diff
in: master

2 files changed

modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
1009 {1009 {
1010 CollectionMode::NFT => Self::burn_nft_item(collection_id, item_id)?,1010 CollectionMode::NFT => Self::burn_nft_item(collection_id, item_id)?,
1011 CollectionMode::Fungible(_) => Self::burn_fungible_item(&sender, collection_id, value)?,1011 CollectionMode::Fungible(_) => Self::burn_fungible_item(&sender, collection_id, value)?,
1012 CollectionMode::ReFungible(_) => Self::burn_refungible_item(collection_id, item_id, sender.clone())?,1012 CollectionMode::ReFungible(_) => Self::burn_refungible_item(collection_id, item_id, &sender)?,
1013 _ => ()1013 _ => ()
1014 };1014 };
10151015
10921092
1093 let sender = ensure_signed(origin)?;1093 let sender = ensure_signed(origin)?;
1094
1095 Self::collection_exists(collection_id)?;
1096 Self::token_exists(collection_id, item_id, &sender)?;
10941097
1095 // Transfer permissions check1098 // Transfer permissions check
1096 let target_collection = <Collection<T>>::get(collection_id);1099 let target_collection = <Collection<T>>::get(collection_id);
1216 let sender = ensure_signed(origin)?;1219 let sender = ensure_signed(origin)?;
1217 1220
1218 Self::collection_exists(collection_id)?;1221 Self::collection_exists(collection_id)?;
1219 1222 Self::token_exists(collection_id, item_id, &sender)?;
1223
1220 ensure!(ChainLimit::get().custom_data_limit >= data.len() as u32, Error::<T>::TokenVariableDataLimitExceeded);1224 ensure!(ChainLimit::get().custom_data_limit >= data.len() as u32, Error::<T>::TokenVariableDataLimitExceeded);
12211225
1225 Self::is_owner_or_admin_permissions(collection_id, sender.clone()),1229 Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
1226 Error::<T>::NoPermission);1230 Error::<T>::NoPermission);
1227
1228 Self::item_exists(collection_id, item_id, &target_collection.mode)?;
12291231
1230 match target_collection.mode1232 match target_collection.mode
1231 {1233 {
1677 let value = item.owner.first().unwrap().fraction;1679 let value = item.owner.first().unwrap().fraction;
1678 let owner = item.owner.first().unwrap().owner.clone();1680 let owner = item.owner.first().unwrap().owner.clone();
16791681
1680 Self::add_token_index(collection_id, current_index, owner.clone())?;1682 Self::add_token_index(collection_id, current_index, &owner)?;
16811683
1682 <ItemListIndex>::insert(collection_id, current_index);1684 <ItemListIndex>::insert(collection_id, current_index);
1683 <ReFungibleItemList<T>>::insert(collection_id, current_index, itemcopy);1685 <ReFungibleItemList<T>>::insert(collection_id, current_index, itemcopy);
16841686
1685 // Update balance1687 // Update balance
1686 let new_balance = <Balance<T>>::get(collection_id, owner.clone())1688 let new_balance = <Balance<T>>::get(collection_id, &owner)
1687 .checked_add(value)1689 .checked_add(value)
1688 .ok_or(Error::<T>::NumOverflow)?;1690 .ok_or(Error::<T>::NumOverflow)?;
1689 <Balance<T>>::insert(collection_id, owner.clone(), new_balance);1691 <Balance<T>>::insert(collection_id, owner.clone(), new_balance);
1697 .ok_or(Error::<T>::NumOverflow)?;1699 .ok_or(Error::<T>::NumOverflow)?;
16981700
1699 let item_owner = item.owner.clone();1701 let item_owner = item.owner.clone();
1700 Self::add_token_index(collection_id, current_index, item.owner.clone())?;1702 Self::add_token_index(collection_id, current_index, &item.owner)?;
17011703
1702 <ItemListIndex>::insert(collection_id, current_index);1704 <ItemListIndex>::insert(collection_id, current_index);
1703 <NftItemList<T>>::insert(collection_id, current_index, item);1705 <NftItemList<T>>::insert(collection_id, current_index, item);
1714 fn burn_refungible_item(1716 fn burn_refungible_item(
1715 collection_id: CollectionId,1717 collection_id: CollectionId,
1716 item_id: TokenId,1718 item_id: TokenId,
1717 owner: T::AccountId,1719 owner: &T::AccountId,
1718 ) -> DispatchResult {1720 ) -> DispatchResult {
1719 ensure!(1721 ensure!(
1720 <ReFungibleItemList<T>>::contains_key(collection_id, item_id),1722 <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
1721 Error::<T>::TokenNotFound1723 Error::<T>::TokenNotFound
1722 );1724 );
1723 let collection = <ReFungibleItemList<T>>::get(collection_id, item_id);1725 let mut token = <ReFungibleItemList<T>>::get(collection_id, item_id);
1724 let item = collection1726 let rft_balance = token
1725 .owner1727 .owner
1726 .iter()1728 .iter()
1727 .filter(|&i| i.owner == owner)1729 .filter(|&i| i.owner == *owner)
1728 .next()1730 .next()
1729 .unwrap();1731 .unwrap();
1730 Self::remove_token_index(collection_id, item_id, owner.clone())?;1732 Self::remove_token_index(collection_id, item_id, owner)?;
17311733
1732 // update balance1734 // update balance
1733 let new_balance = <Balance<T>>::get(collection_id, item.owner.clone())1735 let new_balance = <Balance<T>>::get(collection_id, rft_balance.owner.clone())
1734 .checked_sub(item.fraction)1736 .checked_sub(rft_balance.fraction)
1735 .ok_or(Error::<T>::NumOverflow)?;1737 .ok_or(Error::<T>::NumOverflow)?;
1736 <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);1738 <Balance<T>>::insert(collection_id, rft_balance.owner.clone(), new_balance);
17371739
1740 // Re-create owners list with sender removed
1741 let index = token
1742 .owner
1743 .iter()
1744 .position(|i| i.owner == *owner)
1745 .unwrap();
1746 token.owner.remove(index);
1747 let owner_count = token.owner.len();
1748
1749 // Burn the token completely if this was the last (only) owner
1750 if owner_count == 0 {
1738 <ReFungibleItemList<T>>::remove(collection_id, item_id);1751 <ReFungibleItemList<T>>::remove(collection_id, item_id);
1752 }
1753 else {
1754 <ReFungibleItemList<T>>::insert(collection_id, item_id, token);
1755 }
17391756
1740 Ok(())1757 Ok(())
1741 }1758 }
1746 Error::<T>::TokenNotFound1763 Error::<T>::TokenNotFound
1747 );1764 );
1748 let item = <NftItemList<T>>::get(collection_id, item_id);1765 let item = <NftItemList<T>>::get(collection_id, item_id);
1749 Self::remove_token_index(collection_id, item_id, item.owner.clone())?;1766 Self::remove_token_index(collection_id, item_id, &item.owner)?;
17501767
1751 // update balance1768 // update balance
1752 let new_balance = <Balance<T>>::get(collection_id, item.owner.clone())1769 let new_balance = <Balance<T>>::get(collection_id, &item.owner)
1753 .checked_sub(1)1770 .checked_sub(1)
1754 .ok_or(Error::<T>::NumOverflow)?;1771 .ok_or(Error::<T>::NumOverflow)?;
1755 <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);1772 <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
1858 Ok(())1875 Ok(())
1859 }1876 }
1877
1878 /// Check if token exists. In case of Fungible, check if there is an entry for
1879 /// the owner in fungible balances double map
1880 fn token_exists(
1881 collection_id: CollectionId,
1882 item_id: TokenId,
1883 owner: &T::AccountId
1884 ) -> DispatchResult {
1885 let target_collection = <Collection<T>>::get(collection_id);
1886 let exists = match target_collection.mode
1887 {
1888 CollectionMode::NFT => <NftItemList<T>>::contains_key(collection_id, item_id),
1889 CollectionMode::Fungible(_) => <FungibleItemList<T>>::contains_key(collection_id, owner),
1890 CollectionMode::ReFungible(_) => <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
1891 _ => false
1892 };
1893
1894 ensure!(exists == true, Error::<T>::TokenNotFound);
1895 Ok(())
1896 }
18601897
1861 fn transfer_fungible(1898 fn transfer_fungible(
1862 collection_id: CollectionId,1899 collection_id: CollectionId,
1863 value: u128,1900 value: u128,
1864 owner: &T::AccountId,1901 owner: &T::AccountId,
1865 recipient: &T::AccountId,1902 recipient: &T::AccountId,
1866 ) -> DispatchResult {1903 ) -> DispatchResult {
1867 ensure!(
1868 <FungibleItemList<T>>::contains_key(collection_id, owner),1904 Self::token_exists(collection_id, 0, owner)?;
1869 Error::<T>::TokenNotFound
1870 );
18711905
1872 let mut balance = <FungibleItemList<T>>::get(collection_id, owner);1906 let mut balance = <FungibleItemList<T>>::get(collection_id, owner);
1873 ensure!(balance.value >= value, Error::<T>::TokenValueTooLow);1907 ensure!(balance.value >= value, Error::<T>::TokenValueTooLow);
1897 owner: T::AccountId,1931 owner: T::AccountId,
1898 new_owner: T::AccountId,1932 new_owner: T::AccountId,
1899 ) -> DispatchResult {1933 ) -> DispatchResult {
1900 ensure!(
1901 <ReFungibleItemList<T>>::contains_key(collection_id, item_id),1934 Self::token_exists(collection_id, item_id, &owner)?;
1902 Error::<T>::TokenNotFound
1903 );
19041935
1905 let full_item = <ReFungibleItemList<T>>::get(collection_id, item_id);1936 let full_item = <ReFungibleItemList<T>>::get(collection_id, item_id);
1906 let item = full_item1937 let item = full_item
1941 <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);1972 <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
19421973
1943 // update index collection1974 // update index collection
1944 Self::move_token_index(collection_id, item_id, old_owner.clone(), new_owner.clone())?;1975 Self::move_token_index(collection_id, item_id, &old_owner, &new_owner)?;
1945 } else {1976 } else {
1946 let mut new_full_item = full_item.clone();1977 let mut new_full_item = full_item.clone();
1947 new_full_item1978 new_full_item
1966 owner: new_owner.clone(),1997 owner: new_owner.clone(),
1967 fraction: value,1998 fraction: value,
1968 });1999 });
1969 Self::add_token_index(collection_id, item_id, new_owner.clone())?;2000 Self::add_token_index(collection_id, item_id, &new_owner)?;
1970 }2001 }
19712002
1972 <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);2003 <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
1981 sender: T::AccountId,2012 sender: T::AccountId,
1982 new_owner: T::AccountId,2013 new_owner: T::AccountId,
1983 ) -> DispatchResult {2014 ) -> DispatchResult {
1984 ensure!(
1985 <NftItemList<T>>::contains_key(collection_id, item_id),2015 Self::token_exists(collection_id, item_id, &sender)?;
1986 Error::<T>::TokenNotFound
1987 );
19882016
1989 let mut item = <NftItemList<T>>::get(collection_id, item_id);2017 let mut item = <NftItemList<T>>::get(collection_id, item_id);
19902018
2010 <NftItemList<T>>::insert(collection_id, item_id, item);2038 <NftItemList<T>>::insert(collection_id, item_id, item);
20112039
2012 // update index collection2040 // update index collection
2013 Self::move_token_index(collection_id, item_id, old_owner.clone(), new_owner.clone())?;2041 Self::move_token_index(collection_id, item_id, &old_owner, &new_owner)?;
20142042
2015 Ok(())2043 Ok(())
2016 }2044 }
2017 2045
2018 fn item_exists(
2019 collection_id: CollectionId,
2020 item_id: TokenId,
2021 mode: &CollectionMode
2022 ) -> DispatchResult {
2023 match mode {
2024 CollectionMode::NFT => ensure!(<NftItemList<T>>::contains_key(collection_id, item_id), Error::<T>::TokenNotFound),
2025 CollectionMode::ReFungible(_) => ensure!(<ReFungibleItemList<T>>::contains_key(collection_id, item_id), Error::<T>::TokenNotFound),
2026 _ => ()
2027 };
2028
2029 Ok(())
2030 }
2031
2032 fn set_re_fungible_variable_data(2046 fn set_re_fungible_variable_data(
2033 collection_id: CollectionId,2047 collection_id: CollectionId,
2090 .unwrap();2104 .unwrap();
20912105
2092 let item_owner = item.owner.clone();2106 let item_owner = item.owner.clone();
2093 Self::add_token_index(collection_id, current_index, item.owner.clone()).unwrap();2107 Self::add_token_index(collection_id, current_index, &item.owner).unwrap();
20942108
2095 <ItemListIndex>::insert(collection_id, current_index);2109 <ItemListIndex>::insert(collection_id, current_index);
20962110
2097 // Update balance2111 // Update balance
2098 let new_balance = <Balance<T>>::get(collection_id, item_owner.clone())2112 let new_balance = <Balance<T>>::get(collection_id, &item_owner)
2099 .checked_add(1)2113 .checked_add(1)
2100 .unwrap();2114 .unwrap();
2101 <Balance<T>>::insert(collection_id, item_owner.clone(), new_balance);2115 <Balance<T>>::insert(collection_id, item_owner.clone(), new_balance);
2106 .checked_add(1)2120 .checked_add(1)
2107 .unwrap();2121 .unwrap();
21082122
2109 Self::add_token_index(collection_id, current_index, (*owner).clone()).unwrap();2123 Self::add_token_index(collection_id, current_index, owner).unwrap();
21102124
2111 <ItemListIndex>::insert(collection_id, current_index);2125 <ItemListIndex>::insert(collection_id, current_index);
21122126
2125 let value = item.owner.first().unwrap().fraction;2139 let value = item.owner.first().unwrap().fraction;
2126 let owner = item.owner.first().unwrap().owner.clone();2140 let owner = item.owner.first().unwrap().owner.clone();
21272141
2128 Self::add_token_index(collection_id, current_index, owner.clone()).unwrap();2142 Self::add_token_index(collection_id, current_index, &owner).unwrap();
21292143
2130 <ItemListIndex>::insert(collection_id, current_index);2144 <ItemListIndex>::insert(collection_id, current_index);
21312145
2132 // Update balance2146 // Update balance
2133 let new_balance = <Balance<T>>::get(collection_id, owner.clone())2147 let new_balance = <Balance<T>>::get(collection_id, &owner)
2134 .checked_add(value)2148 .checked_add(value)
2135 .unwrap();2149 .unwrap();
2136 <Balance<T>>::insert(collection_id, owner.clone(), new_balance);2150 <Balance<T>>::insert(collection_id, owner.clone(), new_balance);
2137 }2151 }
21382152
2139 fn add_token_index(collection_id: CollectionId, item_index: TokenId, owner: T::AccountId) -> DispatchResult {2153 fn add_token_index(collection_id: CollectionId, item_index: TokenId, owner: &T::AccountId) -> DispatchResult {
21402154
2141 // add to account limit2155 // add to account limit
2142 if <AccountItemCount<T>>::contains_key(owner.clone()) {2156 if <AccountItemCount<T>>::contains_key(owner) {
21432157
2144 // bound Owned tokens by a single address2158 // bound Owned tokens by a single address
2145 let count = <AccountItemCount<T>>::get(owner.clone());2159 let count = <AccountItemCount<T>>::get(owner);
2146 ensure!(count < ChainLimit::get().account_token_ownership_limit, Error::<T>::AddressOwnershipLimitExceeded);2160 ensure!(count < ChainLimit::get().account_token_ownership_limit, Error::<T>::AddressOwnershipLimitExceeded);
21472161
2148 <AccountItemCount<T>>::insert(owner.clone(), count2162 <AccountItemCount<T>>::insert(owner.clone(), count
2153 <AccountItemCount<T>>::insert(owner.clone(), 1);2167 <AccountItemCount<T>>::insert(owner.clone(), 1);
2154 }2168 }
21552169
2156 let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner.clone());2170 let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner);
2157 if list_exists {2171 if list_exists {
2158 let mut list = <AddressTokens<T>>::get(collection_id, owner.clone());2172 let mut list = <AddressTokens<T>>::get(collection_id, owner);
2159 let item_contains = list.contains(&item_index.clone());2173 let item_contains = list.contains(&item_index.clone());
21602174
2161 if !item_contains {2175 if !item_contains {
2166 } else {2180 } else {
2167 let mut itm = Vec::new();2181 let mut itm = Vec::new();
2168 itm.push(item_index.clone());2182 itm.push(item_index.clone());
2169 <AddressTokens<T>>::insert(collection_id, owner, itm);2183 <AddressTokens<T>>::insert(collection_id, owner.clone(), itm);
2170
2171 }2184 }
21722185
2176 fn remove_token_index(2189 fn remove_token_index(
2177 collection_id: CollectionId,2190 collection_id: CollectionId,
2178 item_index: TokenId,2191 item_index: TokenId,
2179 owner: T::AccountId,2192 owner: &T::AccountId,
2180 ) -> DispatchResult {2193 ) -> DispatchResult {
21812194
2182 // update counter2195 // update counter
2183 <AccountItemCount<T>>::insert(owner.clone(), 2196 <AccountItemCount<T>>::insert(owner.clone(),
2184 <AccountItemCount<T>>::get(owner.clone())2197 <AccountItemCount<T>>::get(owner)
2185 .checked_sub(1)2198 .checked_sub(1)
2186 .ok_or(Error::<T>::NumOverflow)?);2199 .ok_or(Error::<T>::NumOverflow)?);
21872200
21882201
2189 let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner.clone());2202 let list_exists = <AddressTokens<T>>::contains_key(collection_id, owner);
2190 if list_exists {2203 if list_exists {
2191 let mut list = <AddressTokens<T>>::get(collection_id, owner.clone());2204 let mut list = <AddressTokens<T>>::get(collection_id, owner);
2192 let item_contains = list.contains(&item_index.clone());2205 let item_contains = list.contains(&item_index.clone());
21932206
2194 if item_contains {2207 if item_contains {
2195 list.retain(|&item| item != item_index);2208 list.retain(|&item| item != item_index);
2196 <AddressTokens<T>>::insert(collection_id, owner, list);2209 <AddressTokens<T>>::insert(collection_id, owner.clone(), list);
2197 }2210 }
2198 }2211 }
21992212
2203 fn move_token_index(2216 fn move_token_index(
2204 collection_id: CollectionId,2217 collection_id: CollectionId,
2205 item_index: TokenId,2218 item_index: TokenId,
2206 old_owner: T::AccountId,2219 old_owner: &T::AccountId,
2207 new_owner: T::AccountId,2220 new_owner: &T::AccountId,
2208 ) -> DispatchResult {2221 ) -> DispatchResult {
2209 Self::remove_token_index(collection_id, item_index, old_owner)?;2222 Self::remove_token_index(collection_id, item_index, old_owner)?;
2210 Self::add_token_index(collection_id, item_index, new_owner)?;2223 Self::add_token_index(collection_id, item_index, new_owner)?;
modifiedtests/src/addToWhiteList.test.tsdiffbeforeafterboth
18let Alice: IKeyringPair; 18let Alice: IKeyringPair;
19let Bob: IKeyringPair; 19let Bob: IKeyringPair;
20 20
21describe.only('Integration Test ext. addToWhiteList()', () => { 21describe('Integration Test ext. addToWhiteList()', () => {
22 22
23 before(async () => { 23 before(async () => {
24 await usingApi(async (api) => { 24 await usingApi(async (api) => {
41 }); 41 });
42}); 42});
43 43
44describe.only('Negative Integration Test ext. addToWhiteList()', () => { 44describe('Negative Integration Test ext. addToWhiteList()', () => {
45 45
46 it('White list an address in the collection that does not exist', async () => { 46 it('White list an address in the collection that does not exist', async () => {
47 await usingApi(async (api) => { 47 await usingApi(async (api) => {