difftreelog
feat(nonfungible) transfer from parent token
in: master
2 files changed
pallets/nonfungible/Cargo.tomldiffbeforeafterboth--- a/pallets/nonfungible/Cargo.toml
+++ b/pallets/nonfungible/Cargo.toml
@@ -18,6 +18,7 @@
sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }
pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
pallet-common = { default-features = false, path = '../common' }
+pallet-structure = { default-features = false, path = '../structure' }
up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
evm-coder = { default-features = false, path = '../../crates/evm-coder' }
pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' }
@@ -36,6 +37,7 @@
"sp-std/std",
"up-data-structs/std",
"pallet-common/std",
+ "pallet-structure/std",
"evm-coder/std",
"ethereum/std",
"pallet-evm-coder-substrate/std",
pallets/nonfungible/src/lib.rsdiffbeforeafterboth27 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent,27 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent,28 CollectionHandle, dispatch::CollectionDispatch,28 CollectionHandle, dispatch::CollectionDispatch,29};29};30use pallet_structure::Pallet as PalletStructure;30use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};31use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};31use sp_core::H160;32use sp_core::H160;32use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};33use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};707171 #[pallet::config]72 #[pallet::config]72 pub trait Config: frame_system::Config + pallet_common::Config {73 pub trait Config:74 frame_system::Config + pallet_common::Config + pallet_structure::Config75 {73 type WeightInfo: WeightInfo;76 type WeightInfo: WeightInfo;74 }77 }256259257 let token_data =260 let token_data =258 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;261 <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;262 // TODO: require sender to be token, owner, require admins to go through transfer_from259 ensure!(263 ensure!(260 &token_data.owner == from264 &token_data.owner == from261 || (collection.limits.owner_can_transfer() && collection.is_owner_or_admin(from)),265 || (collection.limits.owner_can_transfer() && collection.is_owner_or_admin(from)),502 Ok(())506 Ok(())503 }507 }504508505 pub fn transfer_from(509 fn check_allowed(506 collection: &NonfungibleHandle<T>,510 collection: &NonfungibleHandle<T>,507 spender: &T::CrossAccountId,511 spender: &T::CrossAccountId,508 from: &T::CrossAccountId,512 from: &T::CrossAccountId,509 to: &T::CrossAccountId,510 token: TokenId,513 token: TokenId,511 ) -> DispatchResult {514 ) -> DispatchResult {512 if spender.conv_eq(from) {515 if spender.conv_eq(from) {513 return Self::transfer(collection, from, to, token);516 return Ok(());514 }517 }515 if collection.access == AccessMode::AllowList {518 if collection.access == AccessMode::AllowList {516 // `from`, `to` checked in [`transfer`]519 // `from`, `to` checked in [`transfer`]517 collection.check_allowlist(spender)?;520 collection.check_allowlist(spender)?;518 }521 }519520 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {522 if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {523 // TODO: should collection owner be allowed to perform this transfer?524 ensure!(525 <PalletStructure<T>>::indirectly_owned(spender.clone(), source.0, source.1, 1)?,526 <CommonError<T>>::ApprovedValueTooLow,527 );528 return Ok(());529 }530 if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {531 return Ok(());532 }521 ensure!(533 ensure!(522 collection.ignores_allowance(spender),534 collection.ignores_allowance(spender),523 <CommonError<T>>::ApprovedValueTooLow535 <CommonError<T>>::ApprovedValueTooLow524 );536 );525 }526527 // =========528529 Self::transfer(collection, from, to, token)?;530 // Allowance is reset in [`transfer`]531 Ok(())537 Ok(())532 }538 }539540 pub fn transfer_from(541 collection: &NonfungibleHandle<T>,542 spender: &T::CrossAccountId,543 from: &T::CrossAccountId,544 to: &T::CrossAccountId,545 token: TokenId,546 ) -> DispatchResult {547 Self::check_allowed(collection, spender, from, token)?;548549 // =========550551 // Allowance is reset in [`transfer`]552 Self::transfer(collection, from, to, token)553 }533554534 pub fn burn_from(555 pub fn burn_from(535 collection: &NonfungibleHandle<T>,556 collection: &NonfungibleHandle<T>,536 spender: &T::CrossAccountId,557 spender: &T::CrossAccountId,537 from: &T::CrossAccountId,558 from: &T::CrossAccountId,538 token: TokenId,559 token: TokenId,539 ) -> DispatchResult {560 ) -> DispatchResult {540 if spender.conv_eq(from) {541 return Self::burn(collection, from, token);561 Self::check_allowed(collection, spender, from, token)?;542 }543 if collection.access == AccessMode::AllowList {544 // `from` checked in [`burn`]545 collection.check_allowlist(spender)?;546 }547548 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {549 ensure!(550 collection.ignores_allowance(spender),551 <CommonError<T>>::ApprovedValueTooLow552 );553 }554562555 // =========563 // =========556564