diff --git a/substrate/frame/assets/src/benchmarking.rs b/substrate/frame/assets/src/benchmarking.rs index 227d45623d688d9c6b7009b0fbad63ba291e240f..0d80ec5923d267965941439fbf9d63d2906f20eb 100644 --- a/substrate/frame/assets/src/benchmarking.rs +++ b/substrate/frame/assets/src/benchmarking.rs @@ -24,7 +24,7 @@ use super::*; use sp_runtime::traits::Bounded; use frame_system::RawOrigin as SystemOrigin; use frame_benchmarking::{ - benchmarks, account, whitelisted_caller, whitelist_account, impl_benchmark_test_suite + benchmarks_instance_pallet, account, whitelisted_caller, whitelist_account, impl_benchmark_test_suite }; use frame_support::traits::Get; use frame_support::{traits::EnsureOrigin, dispatch::UnfilteredDispatchable}; @@ -33,13 +33,13 @@ use crate::Pallet as Assets; const SEED: u32 = 0; -fn create_default_asset<T: Config>(is_sufficient: bool) +fn create_default_asset<T: Config<I>, I: 'static>(is_sufficient: bool) -> (T::AccountId, <T::Lookup as StaticLookup>::Source) { let caller: T::AccountId = whitelisted_caller(); let caller_lookup = T::Lookup::unlookup(caller.clone()); let root = SystemOrigin::Root.into(); - assert!(Assets::<T>::force_create( + assert!(Assets::<T, I>::force_create( root, Default::default(), caller_lookup.clone(), @@ -49,14 +49,14 @@ fn create_default_asset<T: Config>(is_sufficient: bool) (caller, caller_lookup) } -fn create_default_minted_asset<T: Config>(is_sufficient: bool, amount: T::Balance) +fn create_default_minted_asset<T: Config<I>, I: 'static>(is_sufficient: bool, amount: T::Balance) -> (T::AccountId, <T::Lookup as StaticLookup>::Source) { - let (caller, caller_lookup) = create_default_asset::<T>(is_sufficient); + let (caller, caller_lookup) = create_default_asset::<T, I>(is_sufficient); if !is_sufficient { T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance()); } - assert!(Assets::<T>::mint( + assert!(Assets::<T, I>::mint( SystemOrigin::Signed(caller.clone()).into(), Default::default(), caller_lookup.clone(), @@ -65,42 +65,42 @@ fn create_default_minted_asset<T: Config>(is_sufficient: bool, amount: T::Balanc (caller, caller_lookup) } -fn swap_is_sufficient<T: Config>(s: &mut bool) { - Asset::<T>::mutate(&T::AssetId::default(), |maybe_a| +fn swap_is_sufficient<T: Config<I>, I: 'static>(s: &mut bool) { + Asset::<T, I>::mutate(&T::AssetId::default(), |maybe_a| if let Some(ref mut a) = maybe_a { sp_std::mem::swap(s, &mut a.is_sufficient) } ); } -fn add_consumers<T: Config>(minter: T::AccountId, n: u32) { +fn add_consumers<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) { let origin = SystemOrigin::Signed(minter); let mut s = false; - swap_is_sufficient::<T>(&mut s); + swap_is_sufficient::<T, I>(&mut s); for i in 0..n { let target = account("consumer", i, SEED); T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance()); let target_lookup = T::Lookup::unlookup(target); - assert!(Assets::<T>::mint(origin.clone().into(), Default::default(), target_lookup, 100u32.into()).is_ok()); + assert!(Assets::<T, I>::mint(origin.clone().into(), Default::default(), target_lookup, 100u32.into()).is_ok()); } - swap_is_sufficient::<T>(&mut s); + swap_is_sufficient::<T, I>(&mut s); } -fn add_sufficients<T: Config>(minter: T::AccountId, n: u32) { +fn add_sufficients<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) { let origin = SystemOrigin::Signed(minter); let mut s = true; - swap_is_sufficient::<T>(&mut s); + swap_is_sufficient::<T, I>(&mut s); for i in 0..n { let target = account("sufficient", i, SEED); let target_lookup = T::Lookup::unlookup(target); - assert!(Assets::<T>::mint(origin.clone().into(), Default::default(), target_lookup, 100u32.into()).is_ok()); + assert!(Assets::<T, I>::mint(origin.clone().into(), Default::default(), target_lookup, 100u32.into()).is_ok()); } - swap_is_sufficient::<T>(&mut s); + swap_is_sufficient::<T, I>(&mut s); } -fn add_approvals<T: Config>(minter: T::AccountId, n: u32) { +fn add_approvals<T: Config<I>, I: 'static>(minter: T::AccountId, n: u32) { T::Currency::deposit_creating(&minter, T::ApprovalDeposit::get() * n.into()); let minter_lookup = T::Lookup::unlookup(minter.clone()); let origin = SystemOrigin::Signed(minter); - Assets::<T>::mint( + Assets::<T, I>::mint( origin.clone().into(), Default::default(), minter_lookup, @@ -110,7 +110,7 @@ fn add_approvals<T: Config>(minter: T::AccountId, n: u32) { let target = account("approval", i, SEED); T::Currency::make_free_balance_be(&target, T::Currency::minimum_balance()); let target_lookup = T::Lookup::unlookup(target); - Assets::<T>::approve_transfer( + Assets::<T, I>::approve_transfer( origin.clone().into(), Default::default(), target_lookup, @@ -119,7 +119,7 @@ fn add_approvals<T: Config>(minter: T::AccountId, n: u32) { } } -fn assert_last_event<T: Config>(generic_event: <T as Config>::Event) { +fn assert_last_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::Event) { let events = frame_system::Pallet::<T>::events(); let system_event: <T as frame_system::Config>::Event = generic_event.into(); // compare to the last event record @@ -127,7 +127,7 @@ fn assert_last_event<T: Config>(generic_event: <T as Config>::Event) { assert_eq!(event, &system_event); } -fn assert_event<T: Config>(generic_event: <T as Config>::Event) { +fn assert_event<T: Config<I>, I: 'static>(generic_event: <T as Config<I>>::Event) { let system_event: <T as frame_system::Config>::Event = generic_event.into(); let events = frame_system::Pallet::<T>::events(); assert!(events.iter().any(|event_record| { @@ -135,14 +135,14 @@ fn assert_event<T: Config>(generic_event: <T as Config>::Event) { })); } -benchmarks! { +benchmarks_instance_pallet! { create { let caller: T::AccountId = whitelisted_caller(); let caller_lookup = T::Lookup::unlookup(caller.clone()); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T>::max_value()); + T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, 1u32.into()) verify { - assert_last_event::<T>(Event::Created(Default::default(), caller.clone(), caller).into()); + assert_last_event::<T, I>(Event::Created(Default::default(), caller.clone(), caller).into()); } force_create { @@ -150,127 +150,127 @@ benchmarks! { let caller_lookup = T::Lookup::unlookup(caller.clone()); }: _(SystemOrigin::Root, Default::default(), caller_lookup, true, 1u32.into()) verify { - assert_last_event::<T>(Event::ForceCreated(Default::default(), caller).into()); + assert_last_event::<T, I>(Event::ForceCreated(Default::default(), caller).into()); } destroy { let c in 0 .. 5_000; let s in 0 .. 5_000; let a in 0 .. 5_00; - let (caller, _) = create_default_asset::<T>(true); - add_consumers::<T>(caller.clone(), c); - add_sufficients::<T>(caller.clone(), s); - add_approvals::<T>(caller.clone(), a); - let witness = Asset::<T>::get(T::AssetId::default()).unwrap().destroy_witness(); + let (caller, _) = create_default_asset::<T, I>(true); + add_consumers::<T, I>(caller.clone(), c); + add_sufficients::<T, I>(caller.clone(), s); + add_approvals::<T, I>(caller.clone(), a); + let witness = Asset::<T, I>::get(T::AssetId::default()).unwrap().destroy_witness(); }: _(SystemOrigin::Signed(caller), Default::default(), witness) verify { - assert_last_event::<T>(Event::Destroyed(Default::default()).into()); + assert_last_event::<T, I>(Event::Destroyed(Default::default()).into()); } mint { - let (caller, caller_lookup) = create_default_asset::<T>(true); + let (caller, caller_lookup) = create_default_asset::<T, I>(true); let amount = T::Balance::from(100u32); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, amount) verify { - assert_last_event::<T>(Event::Issued(Default::default(), caller, amount).into()); + assert_last_event::<T, I>(Event::Issued(Default::default(), caller, amount).into()); } burn { let amount = T::Balance::from(100u32); - let (caller, caller_lookup) = create_default_minted_asset::<T>(true, amount); + let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, amount) verify { - assert_last_event::<T>(Event::Burned(Default::default(), caller, amount).into()); + assert_last_event::<T, I>(Event::Burned(Default::default(), caller, amount).into()); } transfer { let amount = T::Balance::from(100u32); - let (caller, caller_lookup) = create_default_minted_asset::<T>(true, amount); + let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount); let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), target_lookup, amount) verify { - assert_last_event::<T>(Event::Transferred(Default::default(), caller, target, amount).into()); + assert_last_event::<T, I>(Event::Transferred(Default::default(), caller, target, amount).into()); } transfer_keep_alive { let mint_amount = T::Balance::from(200u32); let amount = T::Balance::from(100u32); - let (caller, caller_lookup) = create_default_minted_asset::<T>(true, mint_amount); + let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, mint_amount); let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), target_lookup, amount) verify { assert!(frame_system::Pallet::<T>::account_exists(&caller)); - assert_last_event::<T>(Event::Transferred(Default::default(), caller, target, amount).into()); + assert_last_event::<T, I>(Event::Transferred(Default::default(), caller, target, amount).into()); } force_transfer { let amount = T::Balance::from(100u32); - let (caller, caller_lookup) = create_default_minted_asset::<T>(true, amount); + let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, amount); let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup, target_lookup, amount) verify { - assert_last_event::<T>( + assert_last_event::<T, I>( Event::Transferred(Default::default(), caller, target, amount).into() ); } freeze { - let (caller, caller_lookup) = create_default_minted_asset::<T>(true, 100u32.into()); + let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into()); }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup) verify { - assert_last_event::<T>(Event::Frozen(Default::default(), caller).into()); + assert_last_event::<T, I>(Event::Frozen(Default::default(), caller).into()); } thaw { - let (caller, caller_lookup) = create_default_minted_asset::<T>(true, 100u32.into()); - Assets::<T>::freeze( + let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into()); + Assets::<T, I>::freeze( SystemOrigin::Signed(caller.clone()).into(), Default::default(), caller_lookup.clone(), )?; }: _(SystemOrigin::Signed(caller.clone()), Default::default(), caller_lookup) verify { - assert_last_event::<T>(Event::Thawed(Default::default(), caller).into()); + assert_last_event::<T, I>(Event::Thawed(Default::default(), caller).into()); } freeze_asset { - let (caller, caller_lookup) = create_default_minted_asset::<T>(true, 100u32.into()); + let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into()); }: _(SystemOrigin::Signed(caller.clone()), Default::default()) verify { - assert_last_event::<T>(Event::AssetFrozen(Default::default()).into()); + assert_last_event::<T, I>(Event::AssetFrozen(Default::default()).into()); } thaw_asset { - let (caller, caller_lookup) = create_default_minted_asset::<T>(true, 100u32.into()); - Assets::<T>::freeze_asset( + let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into()); + Assets::<T, I>::freeze_asset( SystemOrigin::Signed(caller.clone()).into(), Default::default(), )?; }: _(SystemOrigin::Signed(caller.clone()), Default::default()) verify { - assert_last_event::<T>(Event::AssetThawed(Default::default()).into()); + assert_last_event::<T, I>(Event::AssetThawed(Default::default()).into()); } transfer_ownership { - let (caller, _) = create_default_asset::<T>(true); + let (caller, _) = create_default_asset::<T, I>(true); let target: T::AccountId = account("target", 0, SEED); let target_lookup = T::Lookup::unlookup(target.clone()); }: _(SystemOrigin::Signed(caller), Default::default(), target_lookup) verify { - assert_last_event::<T>(Event::OwnerChanged(Default::default(), target).into()); + assert_last_event::<T, I>(Event::OwnerChanged(Default::default(), target).into()); } set_team { - let (caller, _) = create_default_asset::<T>(true); + let (caller, _) = create_default_asset::<T, I>(true); let target0 = T::Lookup::unlookup(account("target", 0, SEED)); let target1 = T::Lookup::unlookup(account("target", 1, SEED)); let target2 = T::Lookup::unlookup(account("target", 2, SEED)); }: _(SystemOrigin::Signed(caller), Default::default(), target0.clone(), target1.clone(), target2.clone()) verify { - assert_last_event::<T>(Event::TeamChanged( + assert_last_event::<T, I>(Event::TeamChanged( Default::default(), account("target", 0, SEED), account("target", 1, SEED), @@ -286,23 +286,23 @@ benchmarks! { let symbol = vec![0u8; s as usize]; let decimals = 12; - let (caller, _) = create_default_asset::<T>(true); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T>::max_value()); + let (caller, _) = create_default_asset::<T, I>(true); + T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value()); }: _(SystemOrigin::Signed(caller), Default::default(), name.clone(), symbol.clone(), decimals) verify { let id = Default::default(); - assert_last_event::<T>(Event::MetadataSet(id, name, symbol, decimals, false).into()); + assert_last_event::<T, I>(Event::MetadataSet(id, name, symbol, decimals, false).into()); } clear_metadata { - let (caller, _) = create_default_asset::<T>(true); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T>::max_value()); + let (caller, _) = create_default_asset::<T, I>(true); + T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value()); let dummy = vec![0u8; T::StringLimit::get() as usize]; let origin = SystemOrigin::Signed(caller.clone()).into(); - Assets::<T>::set_metadata(origin, Default::default(), dummy.clone(), dummy, 12)?; + Assets::<T, I>::set_metadata(origin, Default::default(), dummy.clone(), dummy, 12)?; }: _(SystemOrigin::Signed(caller), Default::default()) verify { - assert_last_event::<T>(Event::MetadataCleared(Default::default()).into()); + assert_last_event::<T, I>(Event::MetadataCleared(Default::default()).into()); } force_set_metadata { @@ -313,10 +313,10 @@ benchmarks! { let symbol = vec![0u8; s as usize]; let decimals = 12; - create_default_asset::<T>(true); + create_default_asset::<T, I>(true); let origin = T::ForceOrigin::successful_origin(); - let call = Call::<T>::force_set_metadata( + let call = Call::<T, I>::force_set_metadata( Default::default(), name.clone(), symbol.clone(), @@ -326,28 +326,28 @@ benchmarks! { }: { call.dispatch_bypass_filter(origin)? } verify { let id = Default::default(); - assert_last_event::<T>(Event::MetadataSet(id, name, symbol, decimals, false).into()); + assert_last_event::<T, I>(Event::MetadataSet(id, name, symbol, decimals, false).into()); } force_clear_metadata { - let (caller, _) = create_default_asset::<T>(true); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T>::max_value()); + let (caller, _) = create_default_asset::<T, I>(true); + T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value()); let dummy = vec![0u8; T::StringLimit::get() as usize]; let origin = SystemOrigin::Signed(caller.clone()).into(); - Assets::<T>::set_metadata(origin, Default::default(), dummy.clone(), dummy, 12)?; + Assets::<T, I>::set_metadata(origin, Default::default(), dummy.clone(), dummy, 12)?; let origin = T::ForceOrigin::successful_origin(); - let call = Call::<T>::force_clear_metadata(Default::default()); + let call = Call::<T, I>::force_clear_metadata(Default::default()); }: { call.dispatch_bypass_filter(origin)? } verify { - assert_last_event::<T>(Event::MetadataCleared(Default::default()).into()); + assert_last_event::<T, I>(Event::MetadataCleared(Default::default()).into()); } force_asset_status { - let (caller, caller_lookup) = create_default_asset::<T>(true); + let (caller, caller_lookup) = create_default_asset::<T, I>(true); let origin = T::ForceOrigin::successful_origin(); - let call = Call::<T>::force_asset_status( + let call = Call::<T, I>::force_asset_status( Default::default(), caller_lookup.clone(), caller_lookup.clone(), @@ -359,12 +359,12 @@ benchmarks! { ); }: { call.dispatch_bypass_filter(origin)? } verify { - assert_last_event::<T>(Event::AssetStatusChanged(Default::default()).into()); + assert_last_event::<T, I>(Event::AssetStatusChanged(Default::default()).into()); } approve_transfer { - let (caller, _) = create_default_minted_asset::<T>(true, 100u32.into()); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T>::max_value()); + let (caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into()); + T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value()); let id = Default::default(); let delegate: T::AccountId = account("delegate", 0, SEED); @@ -372,12 +372,12 @@ benchmarks! { let amount = 100u32.into(); }: _(SystemOrigin::Signed(caller.clone()), id, delegate_lookup, amount) verify { - assert_last_event::<T>(Event::ApprovedTransfer(id, caller, delegate, amount).into()); + assert_last_event::<T, I>(Event::ApprovedTransfer(id, caller, delegate, amount).into()); } transfer_approved { - let (owner, owner_lookup) = create_default_minted_asset::<T>(true, 100u32.into()); - T::Currency::make_free_balance_be(&owner, DepositBalanceOf::<T>::max_value()); + let (owner, owner_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into()); + T::Currency::make_free_balance_be(&owner, DepositBalanceOf::<T, I>::max_value()); let id = Default::default(); let delegate: T::AccountId = account("delegate", 0, SEED); @@ -385,44 +385,44 @@ benchmarks! { let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let amount = 100u32.into(); let origin = SystemOrigin::Signed(owner.clone()).into(); - Assets::<T>::approve_transfer(origin, id, delegate_lookup.clone(), amount)?; + Assets::<T, I>::approve_transfer(origin, id, delegate_lookup.clone(), amount)?; let dest: T::AccountId = account("dest", 0, SEED); let dest_lookup = T::Lookup::unlookup(dest.clone()); }: _(SystemOrigin::Signed(delegate.clone()), id, owner_lookup, dest_lookup, amount) verify { assert!(T::Currency::reserved_balance(&owner).is_zero()); - assert_event::<T>(Event::Transferred(id, owner, dest, amount).into()); + assert_event::<T, I>(Event::Transferred(id, owner, dest, amount).into()); } cancel_approval { - let (caller, _) = create_default_minted_asset::<T>(true, 100u32.into()); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T>::max_value()); + let (caller, _) = create_default_minted_asset::<T, I>(true, 100u32.into()); + T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value()); let id = Default::default(); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let amount = 100u32.into(); let origin = SystemOrigin::Signed(caller.clone()).into(); - Assets::<T>::approve_transfer(origin, id, delegate_lookup.clone(), amount)?; + Assets::<T, I>::approve_transfer(origin, id, delegate_lookup.clone(), amount)?; }: _(SystemOrigin::Signed(caller.clone()), id, delegate_lookup) verify { - assert_last_event::<T>(Event::ApprovalCancelled(id, caller, delegate).into()); + assert_last_event::<T, I>(Event::ApprovalCancelled(id, caller, delegate).into()); } force_cancel_approval { - let (caller, caller_lookup) = create_default_minted_asset::<T>(true, 100u32.into()); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T>::max_value()); + let (caller, caller_lookup) = create_default_minted_asset::<T, I>(true, 100u32.into()); + T::Currency::make_free_balance_be(&caller, DepositBalanceOf::<T, I>::max_value()); let id = Default::default(); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); let amount = 100u32.into(); let origin = SystemOrigin::Signed(caller.clone()).into(); - Assets::<T>::approve_transfer(origin, id, delegate_lookup.clone(), amount)?; + Assets::<T, I>::approve_transfer(origin, id, delegate_lookup.clone(), amount)?; }: _(SystemOrigin::Signed(caller.clone()), id, caller_lookup, delegate_lookup) verify { - assert_last_event::<T>(Event::ApprovalCancelled(id, caller, delegate).into()); + assert_last_event::<T, I>(Event::ApprovalCancelled(id, caller, delegate).into()); } } diff --git a/substrate/frame/assets/src/extra_mutator.rs b/substrate/frame/assets/src/extra_mutator.rs index 26a9a3f357c52eed8b649d6e3cc97d672a3e4a26..d86d78ce3e376697d9f8cfdfa3086c714b9b7eee 100644 --- a/substrate/frame/assets/src/extra_mutator.rs +++ b/substrate/frame/assets/src/extra_mutator.rs @@ -25,20 +25,23 @@ use super::*; /// any uncommitted changes (see `commit` function) will be automatically committed to storage when /// dropped. Changes, even after committed, may be reverted to their original values with the /// `revert` function. -pub struct ExtraMutator<T: Config> { +pub struct ExtraMutator<T: Config<I>, I: 'static = ()> { id: T::AssetId, who: T::AccountId, original: T::Extra, pending: Option<T::Extra>, } -impl<T: Config> Drop for ExtraMutator<T> { +impl<T: Config<I>, I: 'static> Drop for ExtraMutator<T, I> { fn drop(&mut self) { - debug_assert!(self.commit().is_ok(), "attempt to write to non-existent asset account"); + debug_assert!( + self.commit().is_ok(), + "attempt to write to non-existent asset account" + ); } } -impl<T: Config> sp_std::ops::Deref for ExtraMutator<T> { +impl<T: Config<I>, I: 'static> sp_std::ops::Deref for ExtraMutator<T, I> { type Target = T::Extra; fn deref(&self) -> &T::Extra { match self.pending { @@ -48,7 +51,7 @@ impl<T: Config> sp_std::ops::Deref for ExtraMutator<T> { } } -impl<T: Config> sp_std::ops::DerefMut for ExtraMutator<T> { +impl<T: Config<I>, I: 'static> sp_std::ops::DerefMut for ExtraMutator<T, I> { fn deref_mut(&mut self) -> &mut T::Extra { if self.pending.is_none() { self.pending = Some(self.original.clone()); @@ -57,15 +60,16 @@ impl<T: Config> sp_std::ops::DerefMut for ExtraMutator<T> { } } -impl<T: Config> ExtraMutator<T> { - pub(super) fn maybe_new(id: T::AssetId, who: impl sp_std::borrow::Borrow<T::AccountId>) - -> Option<ExtraMutator<T>> - { - if Account::<T>::contains_key(id, who.borrow()) { - Some(ExtraMutator::<T> { +impl<T: Config<I>, I: 'static> ExtraMutator<T, I> { + pub(super) fn maybe_new( + id: T::AssetId, + who: impl sp_std::borrow::Borrow<T::AccountId>, + ) -> Option<ExtraMutator<T, I>> { + if Account::<T, I>::contains_key(id, who.borrow()) { + Some(ExtraMutator::<T, I> { id, who: who.borrow().clone(), - original: Account::<T>::get(id, who.borrow()).extra, + original: Account::<T, I>::get(id, who.borrow()).extra, pending: None, }) } else { @@ -73,18 +77,17 @@ impl<T: Config> ExtraMutator<T> { } } - /// Commit any changes to storage. pub fn commit(&mut self) -> Result<(), ()> { if let Some(extra) = self.pending.take() { - Account::<T>::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| + Account::<T, I>::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| { if let Some(ref mut account) = maybe_account { account.extra = extra; Ok(()) } else { Err(()) } - ) + }) } else { Ok(()) } @@ -93,13 +96,13 @@ impl<T: Config> ExtraMutator<T> { /// Revert any changes, even those already committed by `self` and drop self. pub fn revert(mut self) -> Result<(), ()> { self.pending = None; - Account::<T>::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| + Account::<T, I>::try_mutate_exists(self.id, self.who.borrow(), |maybe_account| { if let Some(ref mut account) = maybe_account { account.extra = self.original.clone(); Ok(()) } else { Err(()) } - ) + }) } } diff --git a/substrate/frame/assets/src/functions.rs b/substrate/frame/assets/src/functions.rs index 197b010b6eb871af3faf89ac4c4e06ebaa70a018..3f2abe0617e1881258eefb4d66a0c3aaab6a7982 100644 --- a/substrate/frame/assets/src/functions.rs +++ b/substrate/frame/assets/src/functions.rs @@ -20,37 +20,40 @@ use super::*; // The main implementation block for the module. -impl<T: Config> Pallet<T> { +impl<T: Config<I>, I: 'static> Pallet<T, I> { // Public immutables /// Return the extra "sid-car" data for `id`/`who`, or `None` if the account doesn't exist. - pub fn adjust_extra(id: T::AssetId, who: impl sp_std::borrow::Borrow<T::AccountId>) - -> Option<ExtraMutator<T>> - { + pub fn adjust_extra( + id: T::AssetId, + who: impl sp_std::borrow::Borrow<T::AccountId>, + ) -> Option<ExtraMutator<T, I>> { ExtraMutator::maybe_new(id, who) } /// Get the asset `id` balance of `who`. pub fn balance(id: T::AssetId, who: impl sp_std::borrow::Borrow<T::AccountId>) -> T::Balance { - Account::<T>::get(id, who.borrow()).balance + Account::<T, I>::get(id, who.borrow()).balance } /// Get the total supply of an asset `id`. pub fn total_supply(id: T::AssetId) -> T::Balance { - Asset::<T>::get(id).map(|x| x.supply).unwrap_or_else(Zero::zero) + Asset::<T, I>::get(id) + .map(|x| x.supply) + .unwrap_or_else(Zero::zero) } pub(super) fn new_account( who: &T::AccountId, - d: &mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T>>, + d: &mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T, I>>, ) -> Result<bool, DispatchError> { - let accounts = d.accounts.checked_add(1).ok_or(Error::<T>::Overflow)?; + let accounts = d.accounts.checked_add(1).ok_or(Error::<T, I>::Overflow)?; let is_sufficient = if d.is_sufficient { frame_system::Pallet::<T>::inc_sufficients(who); d.sufficients += 1; true } else { - frame_system::Pallet::<T>::inc_consumers(who).map_err(|_| Error::<T>::NoProvider)?; + frame_system::Pallet::<T>::inc_consumers(who).map_err(|_| Error::<T, I>::NoProvider)?; false }; d.accounts = accounts; @@ -60,7 +63,7 @@ impl<T: Config> Pallet<T> { pub(super) fn dead_account( what: T::AssetId, who: &T::AccountId, - d: &mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T>>, + d: &mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T, I>>, sufficient: bool, ) { if sufficient { @@ -73,15 +76,19 @@ impl<T: Config> Pallet<T> { T::Freezer::died(what, who) } - pub(super) fn can_increase(id: T::AssetId, who: &T::AccountId, amount: T::Balance) -> DepositConsequence { - let details = match Asset::<T>::get(id) { + pub(super) fn can_increase( + id: T::AssetId, + who: &T::AccountId, + amount: T::Balance, + ) -> DepositConsequence { + let details = match Asset::<T, I>::get(id) { Some(details) => details, None => return DepositConsequence::UnknownAsset, }; if details.supply.checked_add(&amount).is_none() { return DepositConsequence::Overflow } - let account = Account::<T>::get(id, who); + let account = Account::<T, I>::get(id, who); if account.balance.checked_add(&amount).is_none() { return DepositConsequence::Overflow } @@ -108,7 +115,7 @@ impl<T: Config> Pallet<T> { keep_alive: bool, ) -> WithdrawConsequence<T::Balance> { use WithdrawConsequence::*; - let details = match Asset::<T>::get(id) { + let details = match Asset::<T, I>::get(id) { Some(details) => details, None => return UnknownAsset, }; @@ -118,7 +125,7 @@ impl<T: Config> Pallet<T> { if details.is_frozen { return Frozen } - let account = Account::<T>::get(id, who); + let account = Account::<T, I>::get(id, who); if account.is_frozen { return Frozen } @@ -155,19 +162,21 @@ impl<T: Config> Pallet<T> { id: T::AssetId, who: &T::AccountId, keep_alive: bool, - ) -> Result<T::Balance, Error<T>> { - let details = match Asset::<T>::get(id) { + ) -> Result<T::Balance, Error<T, I>> { + let details = match Asset::<T, I>::get(id) { Some(details) => details, - None => return Err(Error::<T>::Unknown), + None => return Err(Error::<T, I>::Unknown), }; - ensure!(!details.is_frozen, Error::<T>::Frozen); + ensure!(!details.is_frozen, Error::<T, I>::Frozen); - let account = Account::<T>::get(id, who); - ensure!(!account.is_frozen, Error::<T>::Frozen); + let account = Account::<T, I>::get(id, who); + ensure!(!account.is_frozen, Error::<T, I>::Frozen); let amount = if let Some(frozen) = T::Freezer::frozen_balance(id, who) { // Frozen balance: account CANNOT be deleted - let required = frozen.checked_add(&details.min_balance).ok_or(Error::<T>::Overflow)?; + let required = frozen + .checked_add(&details.min_balance) + .ok_or(Error::<T, I>::Overflow)?; account.balance.saturating_sub(required) } else { let is_provider = false; @@ -204,9 +213,8 @@ impl<T: Config> Pallet<T> { amount: T::Balance, f: DebitFlags, ) -> Result<T::Balance, DispatchError> { - let actual = Self::reducible_balance(id, target, f.keep_alive)? - .min(amount); - ensure!(f.best_effort || actual >= amount, Error::<T>::BalanceLow); + let actual = Self::reducible_balance(id, target, f.keep_alive)?.min(amount); + ensure!(f.best_effort || actual >= amount, Error::<T, I>::BalanceLow); let conseq = Self::can_decrease(id, target, actual, f.keep_alive); let actual = match conseq.into_result() { @@ -263,7 +271,10 @@ impl<T: Config> Pallet<T> { ) -> DispatchResult { Self::increase_balance(id, beneficiary, amount, |details| -> DispatchResult { if let Some(check_issuer) = maybe_check_issuer { - ensure!(&check_issuer == &details.issuer, Error::<T>::NoPermission); + ensure!( + &check_issuer == &details.issuer, + Error::<T, I>::NoPermission + ); } debug_assert!(T::Balance::max_value() - details.supply >= amount, "checked in prep; qed"); details.supply = details.supply.saturating_add(amount); @@ -283,17 +294,19 @@ impl<T: Config> Pallet<T> { id: T::AssetId, beneficiary: &T::AccountId, amount: T::Balance, - check: impl FnOnce(&mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T>>) -> DispatchResult, + check: impl FnOnce( + &mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T, I>>, + ) -> DispatchResult, ) -> DispatchResult { if amount.is_zero() { return Ok(()) } Self::can_increase(id, beneficiary, amount).into_result()?; - Asset::<T>::try_mutate(id, |maybe_details| -> DispatchResult { - let details = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?; + Asset::<T, I>::try_mutate(id, |maybe_details| -> DispatchResult { + let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?; check(details)?; - Account::<T>::try_mutate(id, beneficiary, |t| -> DispatchResult { + Account::<T, I>::try_mutate(id, beneficiary, |t| -> DispatchResult { let new_balance = t.balance.saturating_add(amount); ensure!(new_balance >= details.min_balance, TokenError::BelowMinimum); if t.balance.is_zero() { @@ -324,7 +337,7 @@ impl<T: Config> Pallet<T> { let actual = Self::decrease_balance(id, target, amount, f, |actual, details| { // Check admin rights. if let Some(check_admin) = maybe_check_admin { - ensure!(&check_admin == &details.admin, Error::<T>::NoPermission); + ensure!(&check_admin == &details.admin, Error::<T, I>::NoPermission); } debug_assert!(details.supply >= actual, "checked in prep; qed"); @@ -351,19 +364,19 @@ impl<T: Config> Pallet<T> { f: DebitFlags, check: impl FnOnce( T::Balance, - &mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T>>, + &mut AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T, I>>, ) -> DispatchResult, ) -> Result<T::Balance, DispatchError> { if amount.is_zero() { return Ok(amount) } let actual = Self::prep_debit(id, target, amount, f)?; - Asset::<T>::try_mutate(id, |maybe_details| -> DispatchResult { - let details = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?; + Asset::<T, I>::try_mutate(id, |maybe_details| -> DispatchResult { + let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?; check(actual, details)?; - Account::<T>::try_mutate_exists(id, target, |maybe_account| -> DispatchResult { + Account::<T, I>::try_mutate_exists(id, target, |maybe_account| -> DispatchResult { let mut account = maybe_account.take().unwrap_or_default(); debug_assert!(account.balance >= actual, "checked in prep; qed"); @@ -411,14 +424,14 @@ impl<T: Config> Pallet<T> { let debit = Self::prep_debit(id, &source, amount, f.into())?; let (credit, maybe_burn) = Self::prep_credit(id, &dest, amount, debit, f.burn_dust)?; - let mut source_account = Account::<T>::get(id, &source); + let mut source_account = Account::<T, I>::get(id, &source); - Asset::<T>::try_mutate(id, |maybe_details| -> DispatchResult { - let details = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?; + Asset::<T, I>::try_mutate(id, |maybe_details| -> DispatchResult { + let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?; // Check admin rights. if let Some(need_admin) = maybe_need_admin { - ensure!(&need_admin == &details.admin, Error::<T>::NoPermission); + ensure!(&need_admin == &details.admin, Error::<T, I>::NoPermission); } // Skip if source == dest @@ -437,7 +450,7 @@ impl<T: Config> Pallet<T> { debug_assert!(source_account.balance >= debit, "checked in prep; qed"); source_account.balance = source_account.balance.saturating_sub(debit); - Account::<T>::try_mutate(id, &dest, |a| -> DispatchResult { + Account::<T, I>::try_mutate(id, &dest, |a| -> DispatchResult { // Calculate new balance; this will not saturate since it's already checked in prep. debug_assert!(a.balance.checked_add(&credit).is_some(), "checked in prep; qed"); let new_balance = a.balance.saturating_add(credit); @@ -455,9 +468,9 @@ impl<T: Config> Pallet<T> { if source_account.balance < details.min_balance { debug_assert!(source_account.balance.is_zero(), "checked in prep; qed"); Self::dead_account(id, &source, details, source_account.sufficient); - Account::<T>::remove(id, &source); + Account::<T, I>::remove(id, &source); } else { - Account::<T>::insert(id, &source, &source_account) + Account::<T, I>::insert(id, &source, &source_account) } Ok(()) diff --git a/substrate/frame/assets/src/impl_fungibles.rs b/substrate/frame/assets/src/impl_fungibles.rs index a4cff9b7e9a62fa48771ac679d5d1148e2fb669f..d0ab13072a88dfa687392d709c409d9b31fcb884 100644 --- a/substrate/frame/assets/src/impl_fungibles.rs +++ b/substrate/frame/assets/src/impl_fungibles.rs @@ -19,23 +19,24 @@ use super::*; -impl<T: Config> fungibles::Inspect<<T as SystemConfig>::AccountId> for Pallet<T> { +impl<T: Config<I>, I: 'static> fungibles::Inspect<<T as SystemConfig>::AccountId> for Pallet<T, I> { type AssetId = T::AssetId; type Balance = T::Balance; fn total_issuance(asset: Self::AssetId) -> Self::Balance { - Asset::<T>::get(asset).map(|x| x.supply).unwrap_or_else(Zero::zero) + Asset::<T, I>::get(asset) + .map(|x| x.supply) + .unwrap_or_else(Zero::zero) } fn minimum_balance(asset: Self::AssetId) -> Self::Balance { - Asset::<T>::get(asset).map(|x| x.min_balance).unwrap_or_else(Zero::zero) + Asset::<T, I>::get(asset) + .map(|x| x.min_balance) + .unwrap_or_else(Zero::zero) } - fn balance( - asset: Self::AssetId, - who: &<T as SystemConfig>::AccountId, - ) -> Self::Balance { - Pallet::<T>::balance(asset, who) + fn balance(asset: Self::AssetId, who: &<T as SystemConfig>::AccountId) -> Self::Balance { + Pallet::<T, I>::balance(asset, who) } fn reducible_balance( @@ -43,7 +44,7 @@ impl<T: Config> fungibles::Inspect<<T as SystemConfig>::AccountId> for Pallet<T> who: &<T as SystemConfig>::AccountId, keep_alive: bool, ) -> Self::Balance { - Pallet::<T>::reducible_balance(asset, who, keep_alive).unwrap_or(Zero::zero()) + Pallet::<T, I>::reducible_balance(asset, who, keep_alive).unwrap_or(Zero::zero()) } fn can_deposit( @@ -51,7 +52,7 @@ impl<T: Config> fungibles::Inspect<<T as SystemConfig>::AccountId> for Pallet<T> who: &<T as SystemConfig>::AccountId, amount: Self::Balance, ) -> DepositConsequence { - Pallet::<T>::can_increase(asset, who, amount) + Pallet::<T, I>::can_increase(asset, who, amount) } fn can_withdraw( @@ -59,11 +60,11 @@ impl<T: Config> fungibles::Inspect<<T as SystemConfig>::AccountId> for Pallet<T> who: &<T as SystemConfig>::AccountId, amount: Self::Balance, ) -> WithdrawConsequence<Self::Balance> { - Pallet::<T>::can_decrease(asset, who, amount, false) + Pallet::<T, I>::can_decrease(asset, who, amount, false) } } -impl<T: Config> fungibles::Mutate<<T as SystemConfig>::AccountId> for Pallet<T> { +impl<T: Config<I>, I: 'static> fungibles::Mutate<<T as SystemConfig>::AccountId> for Pallet<T, I> { fn mint_into( asset: Self::AssetId, who: &<T as SystemConfig>::AccountId, @@ -97,7 +98,7 @@ impl<T: Config> fungibles::Mutate<<T as SystemConfig>::AccountId> for Pallet<T> } } -impl<T: Config> fungibles::Transfer<T::AccountId> for Pallet<T> { +impl<T: Config<I>, I: 'static> fungibles::Transfer<T::AccountId> for Pallet<T, I> { fn transfer( asset: Self::AssetId, source: &T::AccountId, @@ -114,13 +115,15 @@ impl<T: Config> fungibles::Transfer<T::AccountId> for Pallet<T> { } } -impl<T: Config> fungibles::Unbalanced<T::AccountId> for Pallet<T> { +impl<T: Config<I>, I: 'static> fungibles::Unbalanced<T::AccountId> for Pallet<T, I> { fn set_balance(_: Self::AssetId, _: &T::AccountId, _: Self::Balance) -> DispatchResult { unreachable!("set_balance is not used if other functions are impl'd"); } fn set_total_issuance(id: T::AssetId, amount: Self::Balance) { - Asset::<T>::mutate_exists(id, |maybe_asset| if let Some(ref mut asset) = maybe_asset { - asset.supply = amount + Asset::<T, I>::mutate_exists(id, |maybe_asset| { + if let Some(ref mut asset) = maybe_asset { + asset.supply = amount + } }); } fn decrease_balance(asset: T::AssetId, who: &T::AccountId, amount: Self::Balance) diff --git a/substrate/frame/assets/src/impl_stored_map.rs b/substrate/frame/assets/src/impl_stored_map.rs index a8a6f95557dfb92986c5cdc33a3b6684aeb57187..6e91e5c1322f7fa3f0cbe4fd4b7ab5c585146b80 100644 --- a/substrate/frame/assets/src/impl_stored_map.rs +++ b/substrate/frame/assets/src/impl_stored_map.rs @@ -19,11 +19,11 @@ use super::*; -impl<T: Config> StoredMap<(T::AssetId, T::AccountId), T::Extra> for Pallet<T> { +impl<T: Config<I>, I: 'static> StoredMap<(T::AssetId, T::AccountId), T::Extra> for Pallet<T, I> { fn get(id_who: &(T::AssetId, T::AccountId)) -> T::Extra { let &(id, ref who) = id_who; - if Account::<T>::contains_key(id, who) { - Account::<T>::get(id, who).extra + if Account::<T, I>::contains_key(id, who) { + Account::<T, I>::get(id, who).extra } else { Default::default() } @@ -34,13 +34,13 @@ impl<T: Config> StoredMap<(T::AssetId, T::AccountId), T::Extra> for Pallet<T> { f: impl FnOnce(&mut Option<T::Extra>) -> Result<R, E>, ) -> Result<R, E> { let &(id, ref who) = id_who; - let mut maybe_extra = Some(Account::<T>::get(id, who).extra); + let mut maybe_extra = Some(Account::<T, I>::get(id, who).extra); let r = f(&mut maybe_extra)?; // They want to write some value or delete it. // If the account existed and they want to write a value, then we write. // If the account didn't exist and they want to delete it, then we let it pass. // Otherwise, we fail. - Account::<T>::try_mutate_exists(id, who, |maybe_account| { + Account::<T, I>::try_mutate_exists(id, who, |maybe_account| { if let Some(extra) = maybe_extra { // They want to write a value. Let this happen only if the account actually exists. if let Some(ref mut account) = maybe_account { diff --git a/substrate/frame/assets/src/lib.rs b/substrate/frame/assets/src/lib.rs index 2a162c2c936b19dc6811d7540923b00bb2762fd2..e8dfd50f4086ab72b44c23ad71fe11b725a8e19a 100644 --- a/substrate/frame/assets/src/lib.rs +++ b/substrate/frame/assets/src/lib.rs @@ -165,13 +165,13 @@ pub mod pallet { #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet<T>(_); + pub struct Pallet<T, I = ()>(_); #[pallet::config] /// The module configuration trait. - pub trait Config: frame_system::Config { + pub trait Config<I: 'static = ()>: frame_system::Config { /// The overarching event type. - type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>; + type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>; /// The units in which we record balances. type Balance: Member + Parameter + AtLeast32BitUnsigned + Default + Copy; @@ -187,17 +187,17 @@ pub mod pallet { type ForceOrigin: EnsureOrigin<Self::Origin>; /// The basic amount of funds that must be reserved for an asset. - type AssetDeposit: Get<DepositBalanceOf<Self>>; + type AssetDeposit: Get<DepositBalanceOf<Self, I>>; /// The basic amount of funds that must be reserved when adding metadata to your asset. - type MetadataDepositBase: Get<DepositBalanceOf<Self>>; + type MetadataDepositBase: Get<DepositBalanceOf<Self, I>>; /// The additional funds that must be reserved for the number of bytes you store in your /// metadata. - type MetadataDepositPerByte: Get<DepositBalanceOf<Self>>; + type MetadataDepositPerByte: Get<DepositBalanceOf<Self, I>>; /// The amount of funds that must be reserved when creating a new approval. - type ApprovalDeposit: Get<DepositBalanceOf<Self>>; + type ApprovalDeposit: Get<DepositBalanceOf<Self, I>>; /// The maximum length of a name or symbol stored on-chain. type StringLimit: Get<u32>; @@ -215,16 +215,16 @@ pub mod pallet { #[pallet::storage] /// Details of an asset. - pub(super) type Asset<T: Config> = StorageMap< + pub(super) type Asset<T: Config<I>, I: 'static = ()> = StorageMap< _, Blake2_128Concat, T::AssetId, - AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T>>, + AssetDetails<T::Balance, T::AccountId, DepositBalanceOf<T, I>>, >; #[pallet::storage] /// The number of units of assets held by any given account. - pub(super) type Account<T: Config> = StorageDoubleMap< + pub(super) type Account<T: Config<I>, I: 'static = ()> = StorageDoubleMap< _, Blake2_128Concat, T::AssetId, @@ -237,30 +237,34 @@ pub mod pallet { #[pallet::storage] /// Approved balance transfers. First balance is the amount approved for transfer. Second /// is the amount of `T::Currency` reserved for storing this. - pub(super) type Approvals<T: Config> = StorageDoubleMap< + pub(super) type Approvals<T: Config<I>, I: 'static = ()> = StorageDoubleMap< _, Blake2_128Concat, T::AssetId, Blake2_128Concat, ApprovalKey<T::AccountId>, - Approval<T::Balance, DepositBalanceOf<T>>, + Approval<T::Balance, DepositBalanceOf<T, I>>, OptionQuery, >; #[pallet::storage] /// Metadata of an asset. - pub(super) type Metadata<T: Config> = StorageMap< + pub(super) type Metadata<T: Config<I>, I: 'static = ()> = StorageMap< _, Blake2_128Concat, T::AssetId, - AssetMetadata<DepositBalanceOf<T>>, + AssetMetadata<DepositBalanceOf<T, I>>, ValueQuery, >; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] - #[pallet::metadata(T::AccountId = "AccountId", T::Balance = "Balance", T::AssetId = "AssetId")] - pub enum Event<T: Config> { + #[pallet::metadata( + T::AccountId = "AccountId", + T::Balance = "Balance", + T::AssetId = "AssetId" + )] + pub enum Event<T: Config<I>, I: 'static = ()> { /// Some asset class was created. \[asset_id, creator, owner\] Created(T::AssetId, T::AccountId, T::AccountId), /// Some assets were issued. \[asset_id, owner, total_supply\] @@ -305,7 +309,7 @@ pub mod pallet { } #[pallet::error] - pub enum Error<T> { + pub enum Error<T, I = ()> { /// Account balance must be greater than or equal to the transfer amount. BalanceLow, /// Balance should be non-zero. @@ -335,10 +339,10 @@ pub mod pallet { } #[pallet::hooks] - impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {} + impl<T: Config<I>, I: 'static> Hooks<BlockNumberFor<T>> for Pallet<T, I> {} #[pallet::call] - impl<T: Config> Pallet<T> { + impl<T: Config<I>, I: 'static> Pallet<T, I> { /// Issue a new class of fungible assets from a public origin. /// /// This new asset class has no assets initially and its owner is the origin. @@ -368,26 +372,29 @@ pub mod pallet { let owner = ensure_signed(origin)?; let admin = T::Lookup::lookup(admin)?; - ensure!(!Asset::<T>::contains_key(id), Error::<T>::InUse); - ensure!(!min_balance.is_zero(), Error::<T>::MinBalanceZero); + ensure!(!Asset::<T, I>::contains_key(id), Error::<T, I>::InUse); + ensure!(!min_balance.is_zero(), Error::<T, I>::MinBalanceZero); let deposit = T::AssetDeposit::get(); T::Currency::reserve(&owner, deposit)?; - Asset::<T>::insert(id, AssetDetails { - owner: owner.clone(), - issuer: admin.clone(), - admin: admin.clone(), - freezer: admin.clone(), - supply: Zero::zero(), - deposit, - min_balance, - is_sufficient: false, - accounts: 0, - sufficients: 0, - approvals: 0, - is_frozen: false, - }); + Asset::<T, I>::insert( + id, + AssetDetails { + owner: owner.clone(), + issuer: admin.clone(), + admin: admin.clone(), + freezer: admin.clone(), + supply: Zero::zero(), + deposit, + min_balance, + is_sufficient: false, + accounts: 0, + sufficients: 0, + approvals: 0, + is_frozen: false, + }, + ); Self::deposit_event(Event::Created(id, owner, admin)); Ok(()) } @@ -424,23 +431,26 @@ pub mod pallet { T::ForceOrigin::ensure_origin(origin)?; let owner = T::Lookup::lookup(owner)?; - ensure!(!Asset::<T>::contains_key(id), Error::<T>::InUse); - ensure!(!min_balance.is_zero(), Error::<T>::MinBalanceZero); - - Asset::<T>::insert(id, AssetDetails { - owner: owner.clone(), - issuer: owner.clone(), - admin: owner.clone(), - freezer: owner.clone(), - supply: Zero::zero(), - deposit: Zero::zero(), - min_balance, - is_sufficient, - accounts: 0, - sufficients: 0, - approvals: 0, - is_frozen: false, - }); + ensure!(!Asset::<T, I>::contains_key(id), Error::<T, I>::InUse); + ensure!(!min_balance.is_zero(), Error::<T, I>::MinBalanceZero); + + Asset::<T, I>::insert( + id, + AssetDetails { + owner: owner.clone(), + issuer: owner.clone(), + admin: owner.clone(), + freezer: owner.clone(), + supply: Zero::zero(), + deposit: Zero::zero(), + min_balance, + is_sufficient, + accounts: 0, + sufficients: 0, + approvals: 0, + is_frozen: false, + }, + ); Self::deposit_event(Event::ForceCreated(id, owner)); Ok(()) } @@ -473,25 +483,28 @@ pub mod pallet { Ok(_) => None, Err(origin) => Some(ensure_signed(origin)?), }; - Asset::<T>::try_mutate_exists(id, |maybe_details| { - let mut details = maybe_details.take().ok_or(Error::<T>::Unknown)?; + Asset::<T, I>::try_mutate_exists(id, |maybe_details| { + let mut details = maybe_details.take().ok_or(Error::<T, I>::Unknown)?; if let Some(check_owner) = maybe_check_owner { - ensure!(details.owner == check_owner, Error::<T>::NoPermission); + ensure!(details.owner == check_owner, Error::<T, I>::NoPermission); } - ensure!(details.accounts == witness.accounts, Error::<T>::BadWitness); - ensure!(details.sufficients == witness.sufficients, Error::<T>::BadWitness); - ensure!(details.approvals == witness.approvals, Error::<T>::BadWitness); + ensure!(details.accounts == witness.accounts, Error::<T, I>::BadWitness); + ensure!(details.sufficients == witness.sufficients, Error::<T, I>::BadWitness); + ensure!(details.approvals == witness.approvals, Error::<T, I>::BadWitness); - for (who, v) in Account::<T>::drain_prefix(id) { + for (who, v) in Account::<T, I>::drain_prefix(id) { Self::dead_account(id, &who, &mut details, v.sufficient); } debug_assert_eq!(details.accounts, 0); debug_assert_eq!(details.sufficients, 0); - let metadata = Metadata::<T>::take(&id); - T::Currency::unreserve(&details.owner, details.deposit.saturating_add(metadata.deposit)); + let metadata = Metadata::<T, I>::take(&id); + T::Currency::unreserve( + &details.owner, + details.deposit.saturating_add(metadata.deposit), + ); - Approvals::<T>::remove_prefix(&id); + Approvals::<T, I>::remove_prefix(&id); Self::deposit_event(Event::Destroyed(id)); // NOTE: could use postinfo to reflect the actual number of accounts/sufficient/approvals @@ -685,14 +698,17 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; - let d = Asset::<T>::get(id).ok_or(Error::<T>::Unknown)?; - ensure!(&origin == &d.freezer, Error::<T>::NoPermission); + let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?; + ensure!(&origin == &d.freezer, Error::<T, I>::NoPermission); let who = T::Lookup::lookup(who)?; - ensure!(Account::<T>::contains_key(id, &who), Error::<T>::BalanceZero); + ensure!( + Account::<T, I>::contains_key(id, &who), + Error::<T, I>::BalanceZero + ); - Account::<T>::mutate(id, &who, |a| a.is_frozen = true); + Account::<T, I>::mutate(id, &who, |a| a.is_frozen = true); - Self::deposit_event(Event::<T>::Frozen(id, who)); + Self::deposit_event(Event::<T, I>::Frozen(id, who)); Ok(()) } @@ -715,14 +731,17 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; - let details = Asset::<T>::get(id).ok_or(Error::<T>::Unknown)?; - ensure!(&origin == &details.admin, Error::<T>::NoPermission); + let details = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?; + ensure!(&origin == &details.admin, Error::<T, I>::NoPermission); let who = T::Lookup::lookup(who)?; - ensure!(Account::<T>::contains_key(id, &who), Error::<T>::BalanceZero); + ensure!( + Account::<T, I>::contains_key(id, &who), + Error::<T, I>::BalanceZero + ); - Account::<T>::mutate(id, &who, |a| a.is_frozen = false); + Account::<T, I>::mutate(id, &who, |a| a.is_frozen = false); - Self::deposit_event(Event::<T>::Thawed(id, who)); + Self::deposit_event(Event::<T, I>::Thawed(id, who)); Ok(()) } @@ -742,13 +761,13 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; - Asset::<T>::try_mutate(id, |maybe_details| { - let d = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?; - ensure!(&origin == &d.freezer, Error::<T>::NoPermission); + Asset::<T, I>::try_mutate(id, |maybe_details| { + let d = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?; + ensure!(&origin == &d.freezer, Error::<T, I>::NoPermission); d.is_frozen = true; - Self::deposit_event(Event::<T>::AssetFrozen(id)); + Self::deposit_event(Event::<T, I>::AssetFrozen(id)); Ok(()) }) } @@ -769,13 +788,13 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; - Asset::<T>::try_mutate(id, |maybe_details| { - let d = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?; - ensure!(&origin == &d.admin, Error::<T>::NoPermission); + Asset::<T, I>::try_mutate(id, |maybe_details| { + let d = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?; + ensure!(&origin == &d.admin, Error::<T, I>::NoPermission); d.is_frozen = false; - Self::deposit_event(Event::<T>::AssetThawed(id)); + Self::deposit_event(Event::<T, I>::AssetThawed(id)); Ok(()) }) } @@ -799,12 +818,14 @@ pub mod pallet { let origin = ensure_signed(origin)?; let owner = T::Lookup::lookup(owner)?; - Asset::<T>::try_mutate(id, |maybe_details| { - let details = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?; - ensure!(&origin == &details.owner, Error::<T>::NoPermission); - if details.owner == owner { return Ok(()) } + Asset::<T, I>::try_mutate(id, |maybe_details| { + let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?; + ensure!(&origin == &details.owner, Error::<T, I>::NoPermission); + if details.owner == owner { + return Ok(()); + } - let metadata_deposit = Metadata::<T>::get(id).deposit; + let metadata_deposit = Metadata::<T, I>::get(id).deposit; let deposit = details.deposit + metadata_deposit; // Move the deposit to the new owner. @@ -842,9 +863,9 @@ pub mod pallet { let admin = T::Lookup::lookup(admin)?; let freezer = T::Lookup::lookup(freezer)?; - Asset::<T>::try_mutate(id, |maybe_details| { - let details = maybe_details.as_mut().ok_or(Error::<T>::Unknown)?; - ensure!(&origin == &details.owner, Error::<T>::NoPermission); + Asset::<T, I>::try_mutate(id, |maybe_details| { + let details = maybe_details.as_mut().ok_or(Error::<T, I>::Unknown)?; + ensure!(&origin == &details.owner, Error::<T, I>::NoPermission); details.issuer = issuer.clone(); details.admin = admin.clone(); @@ -881,14 +902,17 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; - ensure!(name.len() <= T::StringLimit::get() as usize, Error::<T>::BadMetadata); - ensure!(symbol.len() <= T::StringLimit::get() as usize, Error::<T>::BadMetadata); + ensure!(name.len() <= T::StringLimit::get() as usize, Error::<T, I>::BadMetadata); + ensure!(symbol.len() <= T::StringLimit::get() as usize, Error::<T, I>::BadMetadata); - let d = Asset::<T>::get(id).ok_or(Error::<T>::Unknown)?; - ensure!(&origin == &d.owner, Error::<T>::NoPermission); + let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?; + ensure!(&origin == &d.owner, Error::<T, I>::NoPermission); - Metadata::<T>::try_mutate_exists(id, |metadata| { - ensure!(metadata.as_ref().map_or(true, |m| !m.is_frozen), Error::<T>::NoPermission); + Metadata::<T, I>::try_mutate_exists(id, |metadata| { + ensure!( + metadata.as_ref().map_or(true, |m| !m.is_frozen), + Error::<T, I>::NoPermission + ); let old_deposit = metadata.take().map_or(Zero::zero(), |m| m.deposit); let new_deposit = T::MetadataDepositPerByte::get() @@ -932,11 +956,11 @@ pub mod pallet { ) -> DispatchResult { let origin = ensure_signed(origin)?; - let d = Asset::<T>::get(id).ok_or(Error::<T>::Unknown)?; - ensure!(&origin == &d.owner, Error::<T>::NoPermission); + let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?; + ensure!(&origin == &d.owner, Error::<T, I>::NoPermission); - Metadata::<T>::try_mutate_exists(id, |metadata| { - let deposit = metadata.take().ok_or(Error::<T>::Unknown)?.deposit; + Metadata::<T, I>::try_mutate_exists(id, |metadata| { + let deposit = metadata.take().ok_or(Error::<T, I>::Unknown)?.deposit; T::Currency::unreserve(&d.owner, deposit); Self::deposit_event(Event::MetadataCleared(id)); Ok(()) @@ -968,11 +992,11 @@ pub mod pallet { ) -> DispatchResult { T::ForceOrigin::ensure_origin(origin)?; - ensure!(name.len() <= T::StringLimit::get() as usize, Error::<T>::BadMetadata); - ensure!(symbol.len() <= T::StringLimit::get() as usize, Error::<T>::BadMetadata); + ensure!(name.len() <= T::StringLimit::get() as usize, Error::<T, I>::BadMetadata); + ensure!(symbol.len() <= T::StringLimit::get() as usize, Error::<T, I>::BadMetadata); - ensure!(Asset::<T>::contains_key(id), Error::<T>::Unknown); - Metadata::<T>::try_mutate_exists(id, |metadata| { + ensure!(Asset::<T, I>::contains_key(id), Error::<T, I>::Unknown); + Metadata::<T, I>::try_mutate_exists(id, |metadata| { let deposit = metadata.take().map_or(Zero::zero(), |m| m.deposit); *metadata = Some(AssetMetadata { deposit, @@ -1005,9 +1029,9 @@ pub mod pallet { ) -> DispatchResult { T::ForceOrigin::ensure_origin(origin)?; - let d = Asset::<T>::get(id).ok_or(Error::<T>::Unknown)?; - Metadata::<T>::try_mutate_exists(id, |metadata| { - let deposit = metadata.take().ok_or(Error::<T>::Unknown)?.deposit; + let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?; + Metadata::<T, I>::try_mutate_exists(id, |metadata| { + let deposit = metadata.take().ok_or(Error::<T, I>::Unknown)?.deposit; T::Currency::unreserve(&d.owner, deposit); Self::deposit_event(Event::MetadataCleared(id)); Ok(()) @@ -1050,8 +1074,8 @@ pub mod pallet { ) -> DispatchResult { T::ForceOrigin::ensure_origin(origin)?; - Asset::<T>::try_mutate(id, |maybe_asset| { - let mut asset = maybe_asset.take().ok_or(Error::<T>::Unknown)?; + Asset::<T, I>::try_mutate(id, |maybe_asset| { + let mut asset = maybe_asset.take().ok_or(Error::<T, I>::Unknown)?; asset.owner = T::Lookup::lookup(owner)?; asset.issuer = T::Lookup::lookup(issuer)?; asset.admin = T::Lookup::lookup(admin)?; @@ -1097,7 +1121,7 @@ pub mod pallet { let delegate = T::Lookup::lookup(delegate)?; let key = ApprovalKey { owner, delegate }; - Approvals::<T>::try_mutate(id, &key, |maybe_approved| -> DispatchResult { + Approvals::<T, I>::try_mutate(id, &key, |maybe_approved| -> DispatchResult { let mut approved = maybe_approved.take().unwrap_or_default(); let deposit_required = T::ApprovalDeposit::get(); if approved.deposit < deposit_required { @@ -1135,7 +1159,7 @@ pub mod pallet { let owner = ensure_signed(origin)?; let delegate = T::Lookup::lookup(delegate)?; let key = ApprovalKey { owner, delegate }; - let approval = Approvals::<T>::take(id, &key).ok_or(Error::<T>::Unknown)?; + let approval = Approvals::<T, I>::take(id, &key).ok_or(Error::<T, I>::Unknown)?; T::Currency::unreserve(&key.owner, approval.deposit); Self::deposit_event(Event::ApprovalCancelled(id, key.owner, key.delegate)); @@ -1166,8 +1190,8 @@ pub mod pallet { .map(|_| ()) .or_else(|origin| -> DispatchResult { let origin = ensure_signed(origin)?; - let d = Asset::<T>::get(id).ok_or(Error::<T>::Unknown)?; - ensure!(&origin == &d.admin, Error::<T>::NoPermission); + let d = Asset::<T, I>::get(id).ok_or(Error::<T, I>::Unknown)?; + ensure!(&origin == &d.admin, Error::<T, I>::NoPermission); Ok(()) })?; @@ -1175,7 +1199,7 @@ pub mod pallet { let delegate = T::Lookup::lookup(delegate)?; let key = ApprovalKey { owner, delegate }; - let approval = Approvals::<T>::take(id, &key).ok_or(Error::<T>::Unknown)?; + let approval = Approvals::<T, I>::take(id, &key).ok_or(Error::<T, I>::Unknown)?; T::Currency::unreserve(&key.owner, approval.deposit); Self::deposit_event(Event::ApprovalCancelled(id, key.owner, key.delegate)); @@ -1213,9 +1237,12 @@ pub mod pallet { let destination = T::Lookup::lookup(destination)?; let key = ApprovalKey { owner, delegate }; - Approvals::<T>::try_mutate_exists(id, &key, |maybe_approved| -> DispatchResult { - let mut approved = maybe_approved.take().ok_or(Error::<T>::Unapproved)?; - let remaining = approved.amount.checked_sub(&amount).ok_or(Error::<T>::Unapproved)?; + Approvals::<T, I>::try_mutate_exists(id, &key, |maybe_approved| -> DispatchResult { + let mut approved = maybe_approved.take().ok_or(Error::<T, I>::Unapproved)?; + let remaining = approved + .amount + .checked_sub(&amount) + .ok_or(Error::<T, I>::Unapproved)?; let f = TransferFlags { keep_alive: false, diff --git a/substrate/frame/assets/src/types.rs b/substrate/frame/assets/src/types.rs index 7e0e235b1b7e62848864200c2d4d9a1801f11aaa..f3f17c00a218fb6bd7d85ec9e06c1cccbe67152d 100644 --- a/substrate/frame/assets/src/types.rs +++ b/substrate/frame/assets/src/types.rs @@ -15,11 +15,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Various basic tyoes for use in the assets pallet. +//! Various basic types for use in the assets pallet. use super::*; -pub(super) type DepositBalanceOf<T> = <<T as Config>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance; +pub(super) type DepositBalanceOf<T, I = ()> = + <<T as Config<I>>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance; #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug)] pub struct AssetDetails<