--- a/pallets/refungible/Cargo.toml +++ b/pallets/refungible/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' } frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" } scale-info = { version = "2.0.1", default-features = false, features = [ @@ -33,6 +34,7 @@ "sp-std/std", "up-data-structs/std", "pallet-common/std", + "pallet-structure/std", 'frame-benchmarking/std', "pallet-evm/std", ] --- a/pallets/refungible/src/lib.rs +++ b/pallets/refungible/src/lib.rs @@ -26,6 +26,7 @@ Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, CollectionHandle, dispatch::CollectionDispatch, }; +use pallet_structure::Pallet as PalletStructure; use sp_runtime::{ArithmeticError, DispatchError, DispatchResult}; use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap}; use core::ops::Deref; @@ -64,7 +65,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; } @@ -534,22 +537,29 @@ Ok(()) } - pub fn transfer_from( + /// Returns allowance, which should be set after transaction + fn check_allowed( collection: &RefungibleHandle, spender: &T::CrossAccountId, from: &T::CrossAccountId, - to: &T::CrossAccountId, token: TokenId, amount: u128, - ) -> DispatchResult { + ) -> Result, DispatchError> { if spender.conv_eq(from) { - return Self::transfer(collection, from, to, token, amount); + return Ok(None); } if collection.access == AccessMode::AllowList { // `from`, `to` checked in [`transfer`] collection.check_allowlist(spender)?; } - + if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) { + // TODO: should collection owner be allowed to perform this transfer? + ensure!( + >::indirectly_owned(spender.clone(), source.0, source.1, 1)?, + >::ApprovedValueTooLow, + ); + return Ok(None); + } let allowance = >::get((collection.id, token, from, &spender)).checked_sub(amount); if allowance.is_none() { @@ -558,7 +568,19 @@ >::ApprovedValueTooLow ); } + Ok(allowance) + } + pub fn transfer_from( + collection: &RefungibleHandle, + spender: &T::CrossAccountId, + from: &T::CrossAccountId, + to: &T::CrossAccountId, + token: TokenId, + amount: u128, + ) -> DispatchResult { + let allowance = Self::check_allowed(collection, spender, from, token, amount)?; + // ========= Self::transfer(collection, from, to, token, amount)?; @@ -575,22 +597,7 @@ token: TokenId, amount: u128, ) -> DispatchResult { - if spender.conv_eq(from) { - return Self::burn(collection, from, token, amount); - } - if collection.access == AccessMode::AllowList { - // `from` checked in [`burn`] - collection.check_allowlist(spender)?; - } - - let allowance = - >::get((collection.id, token, from, &spender)).checked_sub(amount); - if allowance.is_none() { - ensure!( - collection.ignores_allowance(spender), - >::ApprovedValueTooLow - ); - } + let allowance = Self::check_allowed(collection, spender, from, token, amount)?; // =========