difftreelog
Fix NFTPAR-291 - approval of non-existing token
in: master
2 files changed
pallets/nft/src/lib.rsdiffbeforeafterboth1009 {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 };10151015109210921093 let sender = ensure_signed(origin)?;1093 let sender = ensure_signed(origin)?;10941095 Self::collection_exists(collection_id)?;1096 Self::token_exists(collection_id, item_id, &sender)?;109410971095 // Transfer permissions check1098 // Transfer permissions check1096 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)?;12231220 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);122112251225 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);12271228 Self::item_exists(collection_id, item_id, &target_collection.mode)?;122912311230 match target_collection.mode1232 match target_collection.mode1231 {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();167916811680 Self::add_token_index(collection_id, current_index, owner.clone())?;1682 Self::add_token_index(collection_id, current_index, &owner)?;168116831682 <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);168416861685 // Update balance1687 // Update balance1686 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)?;169817001699 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)?;170117031702 <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>::TokenNotFound1722 );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 = token1725 .owner1727 .owner1726 .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)?;173117331732 // update balance1734 // update balance1733 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);173717391740 // Re-create owners list with sender removed1741 let index = token1742 .owner1743 .iter()1744 .position(|i| i.owner == *owner)1745 .unwrap();1746 token.owner.remove(index);1747 let owner_count = token.owner.len();17481749 // Burn the token completely if this was the last (only) owner1750 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 }173917561740 Ok(())1757 Ok(())1741 }1758 }1746 Error::<T>::TokenNotFound1763 Error::<T>::TokenNotFound1747 );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)?;175017671751 // update balance1768 // update balance1752 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 }18771878 /// Check if token exists. In case of Fungible, check if there is an entry for 1879 /// the owner in fungible balances double map1880 fn token_exists(1881 collection_id: CollectionId,1882 item_id: TokenId,1883 owner: &T::AccountId1884 ) -> DispatchResult {1885 let target_collection = <Collection<T>>::get(collection_id);1886 let exists = match target_collection.mode1887 {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 _ => false1892 };18931894 ensure!(exists == true, Error::<T>::TokenNotFound);1895 Ok(())1896 }186018971861 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>::TokenNotFound1870 );187119051872 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>::TokenNotFound1903 );190419351905 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_item1941 <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);1972 <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);194219731943 // update index collection1974 // update index collection1944 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_item1966 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 }197120021972 <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>::TokenNotFound1987 );198820161989 let mut item = <NftItemList<T>>::get(collection_id, item_id);2017 let mut item = <NftItemList<T>>::get(collection_id, item_id);199020182010 <NftItemList<T>>::insert(collection_id, item_id, item);2038 <NftItemList<T>>::insert(collection_id, item_id, item);201120392012 // update index collection2040 // update index collection2013 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)?;201420422015 Ok(())2043 Ok(())2016 }2044 }2017 2045 2018 fn item_exists(2019 collection_id: CollectionId,2020 item_id: TokenId,2021 mode: &CollectionMode2022 ) -> 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 }20312032 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();209121052092 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();209421082095 <ItemListIndex>::insert(collection_id, current_index);2109 <ItemListIndex>::insert(collection_id, current_index);209621102097 // Update balance2111 // Update balance2098 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();210821222109 Self::add_token_index(collection_id, current_index, (*owner).clone()).unwrap();2123 Self::add_token_index(collection_id, current_index, owner).unwrap();211021242111 <ItemListIndex>::insert(collection_id, current_index);2125 <ItemListIndex>::insert(collection_id, current_index);211221262125 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();212721412128 Self::add_token_index(collection_id, current_index, owner.clone()).unwrap();2142 Self::add_token_index(collection_id, current_index, &owner).unwrap();212921432130 <ItemListIndex>::insert(collection_id, current_index);2144 <ItemListIndex>::insert(collection_id, current_index);213121452132 // Update balance2146 // Update balance2133 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 }213821522139 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 {214021542141 // add to account limit2155 // add to account limit2142 if <AccountItemCount<T>>::contains_key(owner.clone()) {2156 if <AccountItemCount<T>>::contains_key(owner) {214321572144 // bound Owned tokens by a single address2158 // bound Owned tokens by a single address2145 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);214721612148 <AccountItemCount<T>>::insert(owner.clone(), count2162 <AccountItemCount<T>>::insert(owner.clone(), count2153 <AccountItemCount<T>>::insert(owner.clone(), 1);2167 <AccountItemCount<T>>::insert(owner.clone(), 1);2154 }2168 }215521692156 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());216021742161 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 }217221852176 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 {218121942182 // update counter2195 // update counter2183 <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)?);21872200218822012189 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());219322062194 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 }219922122203 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)?;tests/src/addToWhiteList.test.tsdiffbeforeafterboth18let 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) => {