difftreelog
feat(nonfungible) transfer from parent token
in: master
2 files changed
pallets/nonfungible/Cargo.tomldiffbeforeafterboth18sp-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",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