git.delta.rocks / unique-network / refs/commits / 9e3547bbeb4c

difftreelog

feat support approve from evm

Yaroslav Bolyukin2021-04-30parent: #481e942.patch.diff
in: master

1 file changed

modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
1239 /// * item_id: ID of the item.1239 /// * item_id: ID of the item.
1240 #[weight = <T as Config>::WeightInfo::approve()]1240 #[weight = <T as Config>::WeightInfo::approve()]
1241 #[transactional]1241 #[transactional]
1242 pub fn approve(origin, spender: T::AccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResult {1242 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResult {
12431243
1244 let sender = ensure_signed(origin)?;1244 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
1245 let target_collection = Self::get_collection(collection_id)?;1245 let collection = Self::get_collection(collection_id)?;
12461246
1247 Self::token_exists(&target_collection, item_id)?;1247 Self::approve_internal(sender, spender, &collection, item_id, amount)?;
12481248
1249 // Transfer permissions check
1250 let bypasses_limits = target_collection.limits.owner_can_transfer &&
1251 Self::is_owner_or_admin_permissions(
1252 &target_collection,
1253 sender.clone(),
1254 );
1255
1256 let allowance_limit = if bypasses_limits {
1257 None
1258 } else if let Some(amount) = Self::owned_amount(
1259 sender.clone(),
1260 &target_collection,
1261 item_id,
1262 ) {
1263 Some(amount)
1264 } else {
1265 fail!(Error::<T>::NoPermission);
1266 };
1267
1268 if target_collection.access == AccessMode::WhiteList {
1269 Self::check_white_list(&target_collection, &sender)?;
1270 Self::check_white_list(&target_collection, &spender)?;
1271 }
1272
1273 let allowance: u128 = amount
1274 .checked_add(<Allowances<T>>::get(collection_id, (item_id, &sender, &spender)))
1275 .ok_or(Error::<T>::NumOverflow)?;
1276 if let Some(limit) = allowance_limit {
1277 ensure!(limit >= allowance, Error::<T>::TokenValueTooLow);
1278 }
1279 <Allowances<T>>::insert(collection_id, (item_id, sender.clone(), spender.clone()), allowance);
1280
1281 Self::deposit_event(RawEvent::Approved(target_collection.id, item_id, sender, spender, allowance));
1282 Ok(())1249 Ok(())
1283 }1250 }
1284 1251
1303 /// * value: Amount to transfer.1270 /// * value: Amount to transfer.
1304 #[weight = <T as Config>::WeightInfo::transfer_from()]1271 #[weight = <T as Config>::WeightInfo::transfer_from()]
1305 #[transactional]1272 #[transactional]
1306 pub fn transfer_from(origin, from: T::AccountId, recipient: T::AccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResult {1273 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResult {
13071274
1308 let sender = ensure_signed(origin)?;1275 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
1309 let target_collection = Self::get_collection(collection_id)?;1276 let collection = Self::get_collection(collection_id)?;
13101277
1311 // Check approval1278 Self::transfer_from_internal(sender, from, recipient, &collection, item_id, value)?;
1312 let approval: u128 = <Allowances<T>>::get(collection_id, (item_id, &from, &sender));
13131279
1314 // Limits check
1315 Self::is_correct_transfer(&target_collection, &recipient)?;
1316
1317 // Transfer permissions check
1318 ensure!(
1319 approval >= value ||
1320 (
1321 target_collection.limits.owner_can_transfer &&
1322 Self::is_owner_or_admin_permissions(&target_collection, sender.clone())
1323 ),
1324 Error::<T>::NoPermission
1325 );
1326
1327 if target_collection.access == AccessMode::WhiteList {
1328 Self::check_white_list(&target_collection, &sender)?;
1329 Self::check_white_list(&target_collection, &recipient)?;
1330 }
1331
1332 // Reduce approval by transferred amount or remove if remaining approval drops to 0
1333 if approval.saturating_sub(value) > 0 {
1334 <Allowances<T>>::insert(collection_id, (item_id, &from, &sender), approval - value);
1335 }
1336 else {
1337 <Allowances<T>>::remove(collection_id, (item_id, &from, &sender));
1338 }
1339
1340 match target_collection.mode
1341 {
1342 CollectionMode::NFT => Self::transfer_nft(&target_collection, item_id, from.clone(), recipient.clone())?,
1343 CollectionMode::Fungible(_) => Self::transfer_fungible(&target_collection, value, &from, &recipient)?,
1344 CollectionMode::ReFungible => Self::transfer_refungible(&target_collection, item_id, value, from.clone(), recipient.clone())?,
1345 _ => ()
1346 };
1347
1348 Self::deposit_event(RawEvent::Transfer(target_collection.id, item_id, from, recipient, value));
1349 Ok(())1280 Ok(())
1350 }1281 }
13511282
1767 }1698 }
17681699
1769 pub fn approve_internal(1700 pub fn approve_internal(
1770 sender: T::AccountId,1701 sender: T::CrossAccountId,
1771 spender: T::AccountId,1702 spender: T::CrossAccountId,
1772 collection: &CollectionHandle<T>,1703 collection: &CollectionHandle<T>,
1773 item_id: TokenId,1704 item_id: TokenId,
1774 amount: u1281705 amount: u128
1800 }1731 }
18011732
1802 let allowance: u128 = amount1733 let allowance: u128 = amount
1803 .checked_add(<Allowances<T>>::get(collection.id, (item_id, &sender, &spender)))1734 .checked_add(<Allowances<T>>::get(collection.id, (item_id, sender.as_sub(), spender.as_sub())))
1804 .ok_or(Error::<T>::NumOverflow)?;1735 .ok_or(Error::<T>::NumOverflow)?;
1805 if let Some(limit) = allowance_limit {1736 if let Some(limit) = allowance_limit {
1806 ensure!(limit >= allowance, Error::<T>::TokenValueTooLow);1737 ensure!(limit >= allowance, Error::<T>::TokenValueTooLow);
1807 }1738 }
1808 <Allowances<T>>::insert(collection.id, (item_id, sender.clone(), spender.clone()), allowance);1739 <Allowances<T>>::insert(collection.id, (item_id, sender.as_sub(), spender.as_sub()), allowance);
18091740
1741
1810 Self::deposit_event(RawEvent::Approved(collection.id, item_id, sender, spender, allowance));1742 Self::deposit_event(RawEvent::Approved(collection.id, item_id, sender, spender, allowance));
1811 Ok(())1743 Ok(())
1812 }1744 }
18131745
1814 pub fn transfer_from_internal(1746 pub fn transfer_from_internal(
1815 sender: T::AccountId,1747 sender: T::CrossAccountId,
1816 from: T::AccountId,1748 from: T::CrossAccountId,
1817 recipient: T::AccountId,1749 recipient: T::CrossAccountId,
1818 collection: &CollectionHandle<T>,1750 collection: &CollectionHandle<T>,
1819 item_id: TokenId,1751 item_id: TokenId,
1820 amount: u128,1752 amount: u128,
1821 ) -> DispatchResult {1753 ) -> DispatchResult {
1822 // Check approval1754 // Check approval
1823 let approval: u128 = <Allowances<T>>::get(collection.id, (item_id, &from, &sender));1755 let approval: u128 = <Allowances<T>>::get(collection.id, (item_id, from.as_sub(), sender.as_sub()));
18241756
1825 // Limits check1757 // Limits check
1826 Self::is_correct_transfer(&collection, &recipient)?;1758 Self::is_correct_transfer(&collection, &recipient)?;
1841 }1773 }
18421774
1843 // Reduce approval by transferred amount or remove if remaining approval drops to 01775 // Reduce approval by transferred amount or remove if remaining approval drops to 0
1844 if approval.saturating_sub(amount) > 0 {1776 let allowance = approval.saturating_sub(amount);
1777 if allowance > 0 {
1845 <Allowances<T>>::insert(collection.id, (item_id, &from, &sender), approval - amount);1778 <Allowances<T>>::insert(collection.id, (item_id, from.as_sub(), sender.as_sub()), allowance);
1846 } else {1779 } else {
1847 <Allowances<T>>::remove(collection.id, (item_id, &from, &sender));1780 <Allowances<T>>::remove(collection.id, (item_id, from.as_sub(), sender.as_sub()));
1848 }1781 }
18491782
1850 match collection.mode {1783 match collection.mode {
1859 }1792 }
1860 _ => ()1793 _ => ()
1861 };1794 };
1795
1796 Ok(())
1797 }
18621798
1863 pub fn create_multiple_items_internal(1799 pub fn create_multiple_items_internal(
1864 sender: T::CrossAccountId,1800 sender: T::CrossAccountId,