git.delta.rocks / unique-network / refs/commits / 2748564f7070

difftreelog

feat(nonfungible) transfer from parent token

Yaroslav Bolyukin2022-04-07parent: #11621bb.patch.diff
in: master

2 files changed

modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
18sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }18sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }
19pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }19pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
20pallet-common = { default-features = false, path = '../common' }20pallet-common = { default-features = false, path = '../common' }
21pallet-structure = { default-features = false, path = '../structure' }
21up-data-structs = { default-features = false, path = '../../primitives/data-structs' }22up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
22evm-coder = { default-features = false, path = '../../crates/evm-coder' }23evm-coder = { default-features = false, path = '../../crates/evm-coder' }
23pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }24pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }
36 "sp-std/std",37 "sp-std/std",
37 "up-data-structs/std",38 "up-data-structs/std",
38 "pallet-common/std",39 "pallet-common/std",
40 "pallet-structure/std",
39 "evm-coder/std",41 "evm-coder/std",
40 "ethereum/std",42 "ethereum/std",
41 "pallet-evm-coder-substrate/std",43 "pallet-evm-coder-substrate/std",
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -27,6 +27,7 @@
 	Error as CommonError, Pallet as PalletCommon, Event as CommonEvent,
 	CollectionHandle, dispatch::CollectionDispatch,
 };
+use pallet_structure::Pallet as PalletStructure;
 use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
 use sp_core::H160;
 use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
@@ -69,7 +70,9 @@
 	}
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config + pallet_common::Config {
+	pub trait Config:
+		frame_system::Config + pallet_common::Config + pallet_structure::Config
+	{
 		type WeightInfo: WeightInfo;
 	}
 
@@ -256,6 +259,7 @@
 
 		let token_data =
 			<TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
+		// TODO: require sender to be token, owner, require admins to go through transfer_from
 		ensure!(
 			&token_data.owner == from
 				|| (collection.limits.owner_can_transfer() && collection.is_owner_or_admin(from)),
@@ -502,33 +506,50 @@
 		Ok(())
 	}
 
-	pub fn transfer_from(
+	fn check_allowed(
 		collection: &NonfungibleHandle<T>,
 		spender: &T::CrossAccountId,
 		from: &T::CrossAccountId,
-		to: &T::CrossAccountId,
 		token: TokenId,
 	) -> DispatchResult {
 		if spender.conv_eq(from) {
-			return Self::transfer(collection, from, to, token);
+			return Ok(());
 		}
 		if collection.access == AccessMode::AllowList {
 			// `from`, `to` checked in [`transfer`]
 			collection.check_allowlist(spender)?;
 		}
-
-		if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {
+		if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {
+			// TODO: should collection owner be allowed to perform this transfer?
 			ensure!(
-				collection.ignores_allowance(spender),
-				<CommonError<T>>::ApprovedValueTooLow
+				<PalletStructure<T>>::indirectly_owned(spender.clone(), source.0, source.1, 1)?,
+				<CommonError<T>>::ApprovedValueTooLow,
 			);
+			return Ok(());
+		}
+		if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
+			return Ok(());
 		}
+		ensure!(
+			collection.ignores_allowance(spender),
+			<CommonError<T>>::ApprovedValueTooLow
+		);
+		Ok(())
+	}
+
+	pub fn transfer_from(
+		collection: &NonfungibleHandle<T>,
+		spender: &T::CrossAccountId,
+		from: &T::CrossAccountId,
+		to: &T::CrossAccountId,
+		token: TokenId,
+	) -> DispatchResult {
+		Self::check_allowed(collection, spender, from, token)?;
 
 		// =========
 
-		Self::transfer(collection, from, to, token)?;
 		// Allowance is reset in [`transfer`]
-		Ok(())
+		Self::transfer(collection, from, to, token)
 	}
 
 	pub fn burn_from(
@@ -537,20 +558,7 @@
 		from: &T::CrossAccountId,
 		token: TokenId,
 	) -> DispatchResult {
-		if spender.conv_eq(from) {
-			return Self::burn(collection, from, token);
-		}
-		if collection.access == AccessMode::AllowList {
-			// `from` checked in [`burn`]
-			collection.check_allowlist(spender)?;
-		}
-
-		if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {
-			ensure!(
-				collection.ignores_allowance(spender),
-				<CommonError<T>>::ApprovedValueTooLow
-			);
-		}
+		Self::check_allowed(collection, spender, from, token)?;
 
 		// =========