diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/swap.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/swap.rs index 7d1615c9e291..3390d9f695e0 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/swap.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/swap.rs @@ -319,10 +319,10 @@ fn cannot_create_pool_from_pool_assets() { let asset_native = Box::new(asset_hub_westend_runtime::xcm_config::WestendLocation::get()); let mut asset_one = asset_hub_westend_runtime::xcm_config::PoolAssetsPalletLocation::get(); asset_one.append_with(GeneralIndex(ASSET_ID.into())).expect("pool assets"); + let pool_owner_account_id = asset_hub_westend_runtime::AssetConversionOrigin::get(); + AssetHubWestend::fund_accounts(vec![(pool_owner_account_id.clone(), 1_000_000_000)]); AssetHubWestend::execute_with(|| { - let pool_owner_account_id = asset_hub_westend_runtime::AssetConversionOrigin::get(); - assert_ok!(::PoolAssets::create( ::RuntimeOrigin::signed(pool_owner_account_id.clone()), ASSET_ID.into(), diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index 5c51a3a52324..374ef43aed6c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -227,8 +227,9 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); // We allow each account to have holds on it from: + // - `Assets`: 4 * 3 instances = 12 // - `NftFractionalization`: 1 - type MaxHolds = ConstU32<1>; + type MaxHolds = ConstU32<13>; type MaxFreezes = ConstU32<0>; } @@ -268,10 +269,11 @@ pub type TrustBackedAssetsInstance = pallet_assets::Instance1; type TrustBackedAssetsCall = pallet_assets::Call; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = AssetIdForTrustBackedAssets; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; type AssetDeposit = AssetDeposit; @@ -304,11 +306,12 @@ ord_parameter_types! { pub type PoolAssetsInstance = pallet_assets::Instance3; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type RemoveItemsLimit = ConstU32<1000>; type AssetId = u32; type AssetIdParameter = u32; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; @@ -376,10 +379,11 @@ parameter_types! { pub type ForeignAssetsInstance = pallet_assets::Instance2; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = MultiLocationForAssetId; type AssetIdParameter = MultiLocationForAssetId; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = ForeignCreators< (FromSiblingParachain>,), ForeignCreatorsSovereignAccountOf, @@ -855,13 +859,13 @@ construct_runtime!( Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, // The main stage. - Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, + Assets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 50, Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 51, Nfts: pallet_nfts::{Pallet, Call, Storage, Event} = 52, - ForeignAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 53, + ForeignAssets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 53, NftFractionalization: pallet_nft_fractionalization::{Pallet, Call, Storage, Event, HoldReason} = 54, - PoolAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 55, + PoolAssets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 55, AssetConversion: pallet_asset_conversion::{Pallet, Call, Storage, Event} = 56, #[cfg(feature = "state-trie-version-1")] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index b58d094deec6..8822c7ba781d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -236,7 +236,9 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + // We allow each account to have holds on it from: + // - `Assets`: 4 * 2 instances = 8 + type MaxHolds = ConstU32<8>; type MaxFreezes = ConstU32<0>; } @@ -276,10 +278,11 @@ pub type TrustBackedAssetsInstance = pallet_assets::Instance1; type TrustBackedAssetsCall = pallet_assets::Call; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = AssetIdForTrustBackedAssets; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; type AssetDeposit = AssetDeposit; @@ -314,10 +317,11 @@ parameter_types! { pub type ForeignAssetsInstance = pallet_assets::Instance2; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = MultiLocationForAssetId; type AssetIdParameter = MultiLocationForAssetId; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = ForeignCreators< (FromSiblingParachain>,), ForeignCreatorsSovereignAccountOf, @@ -769,10 +773,10 @@ construct_runtime!( Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, // The main stage. - Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, + Assets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 50, Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 51, Nfts: pallet_nfts::{Pallet, Call, Storage, Event} = 52, - ForeignAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 53, + ForeignAssets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 53, } ); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index a0eef7e43a4b..c33480a464cc 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -234,7 +234,8 @@ impl pallet_balances::Config for Runtime { type FreezeIdentifier = (); // We allow each account to have holds on it from: // - `NftFractionalization`: 1 - type MaxHolds = ConstU32<1>; + // - `Assets`: 12 (3 instances) + type MaxHolds = ConstU32<13>; type MaxFreezes = ConstU32<0>; } @@ -274,10 +275,11 @@ pub type TrustBackedAssetsInstance = pallet_assets::Instance1; type TrustBackedAssetsCall = pallet_assets::Call; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = AssetIdForTrustBackedAssets; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; type AssetDeposit = AssetDeposit; @@ -310,11 +312,12 @@ ord_parameter_types! { pub type PoolAssetsInstance = pallet_assets::Instance3; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type RemoveItemsLimit = ConstU32<1000>; type AssetId = u32; type AssetIdParameter = u32; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; @@ -382,10 +385,11 @@ parameter_types! { pub type ForeignAssetsInstance = pallet_assets::Instance2; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = MultiLocationForAssetId; type AssetIdParameter = MultiLocationForAssetId; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = ForeignCreators< (FromSiblingParachain>,), ForeignCreatorsSovereignAccountOf, @@ -932,13 +936,13 @@ construct_runtime!( ToRococoXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 44, // The main stage. - Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, + Assets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 50, Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 51, Nfts: pallet_nfts::{Pallet, Call, Storage, Event} = 52, - ForeignAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 53, + ForeignAssets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 53, NftFractionalization: pallet_nft_fractionalization::{Pallet, Call, Storage, Event, HoldReason} = 54, - PoolAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 55, + PoolAssets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 55, AssetConversion: pallet_asset_conversion::{Pallet, Call, Storage, Event} = 56, #[cfg(feature = "state-trie-version-1")] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index a7dc3a84777e..c915d59f2974 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -205,8 +205,9 @@ impl pallet_balances::Config for Runtime { type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); // We allow each account to have holds on it from: + // - `Assets`: 4 * 3 instaces = 12 // - `NftFractionalization`: 1 - type MaxHolds = ConstU32<1>; + type MaxHolds = ConstU32<13>; type MaxFreezes = ConstU32<0>; } @@ -245,10 +246,11 @@ pub type TrustBackedAssetsInstance = pallet_assets::Instance1; type TrustBackedAssetsCall = pallet_assets::Call; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = AssetIdForTrustBackedAssets; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; type AssetDeposit = AssetDeposit; @@ -281,11 +283,12 @@ ord_parameter_types! { pub type PoolAssetsInstance = pallet_assets::Instance3; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type RemoveItemsLimit = ConstU32<1000>; type AssetId = u32; type AssetIdParameter = u32; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AssetsForceOrigin; @@ -351,10 +354,11 @@ parameter_types! { pub type ForeignAssetsInstance = pallet_assets::Instance2; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = MultiLocationForAssetId; type AssetIdParameter = MultiLocationForAssetId; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = ForeignCreators< (FromSiblingParachain>,), ForeignCreatorsSovereignAccountOf, @@ -831,12 +835,12 @@ construct_runtime!( Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, // The main stage. - Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, + Assets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 50, Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 51, Nfts: pallet_nfts::{Pallet, Call, Storage, Event} = 52, - ForeignAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 53, + ForeignAssets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 53, NftFractionalization: pallet_nft_fractionalization::{Pallet, Call, Storage, Event, HoldReason} = 54, - PoolAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 55, + PoolAssets: pallet_assets::::{Pallet, Call, Storage, Event, HoldReason} = 55, AssetConversion: pallet_asset_conversion::{Pallet, Call, Storage, Event} = 56, } ); diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 86389425eb5e..ee43b2b4f613 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -400,7 +400,7 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + type MaxHolds = ConstU32<4>; // assets type MaxFreezes = ConstU32<0>; } @@ -433,10 +433,11 @@ parameter_types! { impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = AssetId; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; @@ -598,7 +599,7 @@ construct_runtime!( DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 33, // The main stage. - Assets: pallet_assets::{Pallet, Call, Storage, Event} = 50, + Assets: pallet_assets::{Pallet, Call, Storage, Event, HoldReason} = 50, Sudo: pallet_sudo::{Pallet, Call, Storage, Event, Config} = 255, } diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index dcea349f3a0e..b58e98dd3591 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -249,7 +249,7 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + type MaxHolds = ConstU32<4>; // assets type MaxFreezes = ConstU32<0>; } @@ -545,10 +545,11 @@ pub type AdminOrigin = impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = u64; type AssetId = AssetIdForTrustBackedAssets; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = AdminOrigin; type AssetDeposit = AssetDeposit; @@ -589,7 +590,7 @@ construct_runtime! { ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 30, - Assets: pallet_assets::{Pallet, Call, Storage, Event} = 31, + Assets: pallet_assets::{Pallet, Call, Storage, Event, HoldReason} = 31, Aura: pallet_aura::{Pallet, Config}, AuraExt: cumulus_pallet_aura_ext::{Pallet, Config}, diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 5b6fa3ee5a0b..df2265e5cd44 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -76,7 +76,7 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + type MaxHolds = ConstU32<4>; // assets type MaxFreezes = ConstU32<0>; } @@ -92,9 +92,10 @@ parameter_types! { impl pallet_assets::Config for Test { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = AssetIdForAssets; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; diff --git a/prdoc/pr_1907.prdoc b/prdoc/pr_1907.prdoc new file mode 100644 index 000000000000..cdd618db9668 --- /dev/null +++ b/prdoc/pr_1907.prdoc @@ -0,0 +1,20 @@ +# Schema: Parity PR Documentation Schema (prdoc) +# See doc at https://github.com/paritytech/prdoc + +title: pallet assets / upgrade to use fungible + +doc: + - audience: Core Dev + description: | + This updates the assets pallet to use the new fungible traits rather than the now deprecated + Currency and ReserveCurrency traits ( paritytech/substrate#12951 ). + Partial fix of #226. + +migrations: + db: [] + + runtime: [] + +crates: [] + +host_functions: [] diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 2070e3f12d04..a6a75f320480 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -524,7 +524,7 @@ impl pallet_balances::Config for Runtime { type FreezeIdentifier = RuntimeFreezeReason; type MaxFreezes = ConstU32<1>; type RuntimeHoldReason = RuntimeHoldReason; - type MaxHolds = ConstU32<2>; + type MaxHolds = ConstU32<10>; // 2 + 8 (2 asset instances) } parameter_types! { @@ -1583,10 +1583,11 @@ parameter_types! { impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = u128; type AssetId = u32; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; @@ -1610,10 +1611,11 @@ ord_parameter_types! { impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = u128; type AssetId = u32; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; type AssetDeposit = AssetDeposit; diff --git a/substrate/frame/asset-conversion/src/lib.rs b/substrate/frame/asset-conversion/src/lib.rs index 8d811473e861..f2357d1c97c6 100644 --- a/substrate/frame/asset-conversion/src/lib.rs +++ b/substrate/frame/asset-conversion/src/lib.rs @@ -1121,7 +1121,7 @@ pub mod pallet { let reserve_out = T::HigherPrecisionBalance::from(*reserve_out); if reserve_in.is_zero() || reserve_out.is_zero() { - return Err(Error::::ZeroLiquidity.into()) + return Err(Error::::ZeroLiquidity) } let amount_in_with_fee = amount_in diff --git a/substrate/frame/asset-conversion/src/mock.rs b/substrate/frame/asset-conversion/src/mock.rs index 3a19f39e7ca6..b4c778e44901 100644 --- a/substrate/frame/asset-conversion/src/mock.rs +++ b/substrate/frame/asset-conversion/src/mock.rs @@ -86,17 +86,18 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type FreezeIdentifier = (); type MaxFreezes = (); - type RuntimeHoldReason = (); - type MaxHolds = (); + type RuntimeHoldReason = RuntimeHoldReason; + type MaxHolds = ConstU32<8>; // each asset instance is 4 holds. } impl pallet_assets::Config for Test { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = u128; type RemoveItemsLimit = ConstU32<1000>; type AssetId = u32; type AssetIdParameter = u32; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; type AssetDeposit = ConstU128<1>; @@ -116,11 +117,12 @@ impl pallet_assets::Config for Test { impl pallet_assets::Config for Test { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = u128; type RemoveItemsLimit = ConstU32<1000>; type AssetId = u32; type AssetIdParameter = u32; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; diff --git a/substrate/frame/assets/src/benchmarking.rs b/substrate/frame/assets/src/benchmarking.rs index c9b0825542de..0a1e4e5d2f70 100644 --- a/substrate/frame/assets/src/benchmarking.rs +++ b/substrate/frame/assets/src/benchmarking.rs @@ -23,7 +23,13 @@ use super::*; use frame_benchmarking::v1::{ account, benchmarks_instance_pallet, whitelist_account, whitelisted_caller, BenchmarkError, }; -use frame_support::traits::{EnsureOrigin, Get, UnfilteredDispatchable}; +use frame_support::{ + assert_ok, + traits::{ + fungible::{Inspect, InspectHold, Mutate}, + EnsureOrigin, Get, UnfilteredDispatchable, + }, +}; use frame_system::RawOrigin as SystemOrigin; use sp_runtime::traits::Bounded; use sp_std::prelude::*; @@ -31,6 +37,10 @@ use sp_std::prelude::*; use crate::Pallet as Assets; const SEED: u32 = 0; +/// A large amount but not enough to cause overflows. +fn large_amount, I: 'static>() -> DepositBalanceOf { + DepositBalanceOf::::max_value() >> 4 +} fn default_asset_id, I: 'static>() -> T::AssetIdParameter { T::BenchmarkHelper::create_asset_id_parameter(0) @@ -43,14 +53,13 @@ fn create_default_asset, I: 'static>( let caller: T::AccountId = whitelisted_caller(); let caller_lookup = T::Lookup::unlookup(caller.clone()); let root = SystemOrigin::Root.into(); - assert!(Assets::::force_create( + assert_ok!(Assets::::force_create( root, asset_id, caller_lookup.clone(), is_sufficient, 1u32.into(), - ) - .is_ok()); + )); (asset_id, caller, caller_lookup) } @@ -60,15 +69,14 @@ fn create_default_minted_asset, I: 'static>( ) -> (T::AssetIdParameter, T::AccountId, AccountIdLookupOf) { let (asset_id, caller, caller_lookup) = create_default_asset::(is_sufficient); if !is_sufficient { - T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance()); + T::NativeToken::set_balance(&caller, T::NativeToken::minimum_balance()); } - assert!(Assets::::mint( + assert_ok!(Assets::::mint( SystemOrigin::Signed(caller.clone()).into(), asset_id, caller_lookup.clone(), amount, - ) - .is_ok()); + )); (asset_id, caller, caller_lookup) } @@ -89,31 +97,31 @@ fn add_sufficients, I: 'static>(minter: T::AccountId, n: u32) { for i in 0..n { let target = account("sufficient", i, SEED); let target_lookup = T::Lookup::unlookup(target); - assert!(Assets::::mint( + assert_ok!(Assets::::mint( origin.clone().into(), asset_id, target_lookup, 100u32.into() - ) - .is_ok()); + )); } swap_is_sufficient::(&mut s); } fn add_approvals, I: 'static>(minter: T::AccountId, n: u32) { let asset_id = default_asset_id::(); - T::Currency::deposit_creating( + T::NativeToken::mint_into( &minter, - T::ApprovalDeposit::get() * n.into() + T::Currency::minimum_balance(), - ); + T::ApprovalDeposit::get() * n.into() + T::NativeToken::minimum_balance(), + ) + .unwrap(); let minter_lookup = T::Lookup::unlookup(minter.clone()); let origin = SystemOrigin::Signed(minter); Assets::::mint(origin.clone().into(), asset_id, minter_lookup, (100 * (n + 1)).into()) .unwrap(); - let enough = T::Currency::minimum_balance(); + let enough = T::NativeToken::minimum_balance(); for i in 0..n { let target = account("approval", i, SEED); - T::Currency::make_free_balance_be(&target, enough); + T::NativeToken::set_balance(&target, enough); let target_lookup = T::Lookup::unlookup(target); Assets::::approve_transfer( origin.clone().into(), @@ -140,7 +148,7 @@ benchmarks_instance_pallet! { .map_err(|_| BenchmarkError::Weightless)?; let caller = T::CreateOrigin::ensure_origin(origin.clone(), &asset_id.into()).unwrap(); let caller_lookup = T::Lookup::unlookup(caller.clone()); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&caller, large_amount::()); }: _(origin, asset_id, caller_lookup, 1u32.into()) verify { assert_last_event::(Event::Created { asset_id: asset_id.into(), creator: caller.clone(), owner: caller }.into()); @@ -307,6 +315,10 @@ benchmarks_instance_pallet! { transfer_ownership { let (asset_id, caller, _) = create_default_asset::(true); let target: T::AccountId = account("target", 0, SEED); + + // Add ED to target account as transferring non-sufficient assets: + T::NativeToken::set_balance(&target, T::NativeToken::minimum_balance()); + let target_lookup = T::Lookup::unlookup(target.clone()); }: _(SystemOrigin::Signed(caller), asset_id, target_lookup) verify { @@ -337,7 +349,7 @@ benchmarks_instance_pallet! { let decimals = 12; let (asset_id, caller, _) = create_default_asset::(true); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&caller, large_amount::()); }: _(SystemOrigin::Signed(caller), asset_id, name.clone(), symbol.clone(), decimals) verify { assert_last_event::(Event::MetadataSet { asset_id: asset_id.into(), name, symbol, decimals, is_frozen: false }.into()); @@ -345,7 +357,7 @@ benchmarks_instance_pallet! { clear_metadata { let (asset_id, caller, _) = create_default_asset::(true); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&caller, large_amount::()); let dummy = vec![0u8; T::StringLimit::get() as usize]; let origin = SystemOrigin::Signed(caller.clone()).into(); Assets::::set_metadata(origin, asset_id, dummy.clone(), dummy, 12)?; @@ -380,7 +392,7 @@ benchmarks_instance_pallet! { force_clear_metadata { let (asset_id, caller, _) = create_default_asset::(true); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&caller, large_amount::()); let dummy = vec![0u8; T::StringLimit::get() as usize]; let origin = SystemOrigin::Signed(caller).into(); Assets::::set_metadata(origin, asset_id, dummy.clone(), dummy, 12)?; @@ -415,7 +427,7 @@ benchmarks_instance_pallet! { approve_transfer { let (asset_id, caller, _) = create_default_minted_asset::(true, 100u32.into()); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&caller, large_amount::()); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); @@ -427,7 +439,7 @@ benchmarks_instance_pallet! { transfer_approved { let (asset_id, owner, owner_lookup) = create_default_minted_asset::(true, 100u32.into()); - T::Currency::make_free_balance_be(&owner, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&owner, large_amount::()); let delegate: T::AccountId = account("delegate", 0, SEED); whitelist_account!(delegate); @@ -440,13 +452,13 @@ benchmarks_instance_pallet! { let dest_lookup = T::Lookup::unlookup(dest.clone()); }: _(SystemOrigin::Signed(delegate.clone()), asset_id, owner_lookup, dest_lookup, amount) verify { - assert!(T::Currency::reserved_balance(&owner).is_zero()); + assert!(T::NativeToken::total_balance_on_hold(&owner).is_zero()); assert_event::(Event::Transferred { asset_id: asset_id.into(), from: owner, to: dest, amount }.into()); } cancel_approval { let (asset_id, caller, _) = create_default_minted_asset::(true, 100u32.into()); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&caller, large_amount::()); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); @@ -460,7 +472,7 @@ benchmarks_instance_pallet! { force_cancel_approval { let (asset_id, caller, caller_lookup) = create_default_minted_asset::(true, 100u32.into()); - T::Currency::make_free_balance_be(&caller, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&caller, large_amount::()); let delegate: T::AccountId = account("delegate", 0, SEED); let delegate_lookup = T::Lookup::unlookup(delegate.clone()); @@ -482,7 +494,7 @@ benchmarks_instance_pallet! { touch { let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::(false); let new_account: T::AccountId = account("newaccount", 1, SEED); - T::Currency::make_free_balance_be(&new_account, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&new_account, large_amount::()); assert_ne!(asset_owner, new_account); assert!(!Account::::contains_key(asset_id.into(), &new_account)); }: _(SystemOrigin::Signed(new_account.clone()), asset_id) @@ -494,7 +506,7 @@ benchmarks_instance_pallet! { let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::(false); let new_account: T::AccountId = account("newaccount", 1, SEED); let new_account_lookup = T::Lookup::unlookup(new_account.clone()); - T::Currency::make_free_balance_be(&asset_owner, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&asset_owner, large_amount::()); assert_ne!(asset_owner, new_account); assert!(!Account::::contains_key(asset_id.into(), &new_account)); }: _(SystemOrigin::Signed(asset_owner.clone()), asset_id, new_account_lookup) @@ -505,40 +517,40 @@ benchmarks_instance_pallet! { refund { let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::(false); let new_account: T::AccountId = account("newaccount", 1, SEED); - T::Currency::make_free_balance_be(&new_account, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&new_account, large_amount::()); assert_ne!(asset_owner, new_account); - assert!(Assets::::touch( + assert_ok!(Assets::::touch( SystemOrigin::Signed(new_account.clone()).into(), asset_id - ).is_ok()); + )); // `touch` should reserve balance of the caller according to the `AssetAccountDeposit` amount... - assert_eq!(T::Currency::reserved_balance(&new_account), T::AssetAccountDeposit::get()); + assert_eq!(T::NativeToken::total_balance_on_hold(&new_account), T::AssetAccountDeposit::get()); // ...and also create an `Account` entry. assert!(Account::::contains_key(asset_id.into(), &new_account)); }: _(SystemOrigin::Signed(new_account.clone()), asset_id, true) verify { // `refund`ing should of course repatriate the reserve - assert!(T::Currency::reserved_balance(&new_account).is_zero()); + assert!(T::NativeToken::total_balance_on_hold(&new_account).is_zero()); } refund_other { let (asset_id, asset_owner, asset_owner_lookup) = create_default_asset::(false); let new_account: T::AccountId = account("newaccount", 1, SEED); let new_account_lookup = T::Lookup::unlookup(new_account.clone()); - T::Currency::make_free_balance_be(&asset_owner, DepositBalanceOf::::max_value()); + T::NativeToken::set_balance(&asset_owner, large_amount::()); assert_ne!(asset_owner, new_account); - assert!(Assets::::touch_other( + assert_ok!(Assets::::touch_other( SystemOrigin::Signed(asset_owner.clone()).into(), asset_id, new_account_lookup.clone() - ).is_ok()); + )); // `touch` should reserve balance of the caller according to the `AssetAccountDeposit` amount... - assert_eq!(T::Currency::reserved_balance(&asset_owner), T::AssetAccountDeposit::get()); + assert_eq!(T::NativeToken::total_balance_on_hold(&asset_owner), T::AssetAccountDeposit::get()); assert!(Account::::contains_key(asset_id.into(), &new_account)); }: _(SystemOrigin::Signed(asset_owner.clone()), asset_id, new_account_lookup.clone()) verify { // this should repatriate the reserved balance of the freezer - assert!(T::Currency::reserved_balance(&asset_owner).is_zero()); + assert!(T::NativeToken::total_balance_on_hold(&asset_owner).is_zero()); } block { diff --git a/substrate/frame/assets/src/functions.rs b/substrate/frame/assets/src/functions.rs index c2c1b6839060..8d9062cd7a23 100644 --- a/substrate/frame/assets/src/functions.rs +++ b/substrate/frame/assets/src/functions.rs @@ -323,7 +323,7 @@ impl, I: 'static> Pallet { Error::::NoPermission ); let reason = Self::new_account(&who, &mut details, Some((&depositor, deposit)))?; - T::Currency::reserve(&depositor, deposit)?; + T::NativeToken::hold(&HoldReason::AssetAccount.into(), &depositor, deposit)?; Asset::::insert(&id, details); Account::::insert( &id, @@ -351,7 +351,12 @@ impl, I: 'static> Pallet { ensure!(account.balance.is_zero() || allow_burn, Error::::WouldBurn); if let Some(deposit) = account.reason.take_deposit() { - T::Currency::unreserve(&who, deposit); + T::NativeToken::release( + &HoldReason::AssetAccount.into(), + &who, + deposit, + Precision::BestEffort, + )?; } if let Remove = Self::dead_account(&who, &mut details, &account.reason, false) { @@ -383,7 +388,12 @@ impl, I: 'static> Pallet { ensure!(caller == &depositor || caller == &details.admin, Error::::NoPermission); ensure!(account.balance.is_zero(), Error::::WouldBurn); - T::Currency::unreserve(&depositor, deposit); + T::NativeToken::release( + &HoldReason::AssetAccount.into(), + &depositor, + deposit, + Precision::BestEffort, + )?; if let Remove = Self::dead_account(&who, &mut details, &account.reason, false) { Account::::remove(&id, &who); @@ -762,10 +772,16 @@ impl, I: 'static> Pallet { ensure!(details.status == AssetStatus::Destroying, Error::::IncorrectStatus); for (i, (who, mut v)) in Account::::iter_prefix(&id).enumerate() { // unreserve the existence deposit if any + let reason = &HoldReason::AssetAccount.into(); if let Some((depositor, deposit)) = v.reason.take_deposit_from() { - T::Currency::unreserve(&depositor, deposit); + T::NativeToken::release( + reason, + &depositor, + deposit, + Precision::BestEffort, + )?; } else if let Some(deposit) = v.reason.take_deposit() { - T::Currency::unreserve(&who, deposit); + T::NativeToken::release(reason, &who, deposit, Precision::BestEffort)?; } if let Remove = Self::dead_account(&who, &mut details, &v.reason, false) { Account::::remove(&id, &who); @@ -813,7 +829,12 @@ impl, I: 'static> Pallet { ensure!(details.status == AssetStatus::Destroying, Error::::IncorrectStatus); for ((owner, _), approval) in Approvals::::drain_prefix((id.clone(),)) { - T::Currency::unreserve(&owner, approval.deposit); + T::NativeToken::release( + &HoldReason::AssetApproval.into(), + &owner, + approval.deposit, + Precision::BestEffort, + )?; removed_approvals = removed_approvals.saturating_add(1); details.approvals = details.approvals.saturating_sub(1); if removed_approvals >= max_items { @@ -843,10 +864,18 @@ impl, I: 'static> Pallet { ensure!(T::CallbackHandle::destroyed(&id).is_ok(), Error::::CallbackFailed); let metadata = Metadata::::take(&id); - T::Currency::unreserve( + T::NativeToken::release( + &HoldReason::AssetMetadata.into(), + &details.owner, + metadata.deposit, + Precision::BestEffort, + )?; + T::NativeToken::release( + &HoldReason::AssetCreation.into(), &details.owner, - details.deposit.saturating_add(metadata.deposit), - ); + details.deposit, + Precision::BestEffort, + )?; Self::deposit_event(Event::Destroyed { asset_id: id }); Ok(()) @@ -879,7 +908,8 @@ impl, I: 'static> Pallet { }; let deposit_required = T::ApprovalDeposit::get(); if approved.deposit < deposit_required { - T::Currency::reserve(owner, deposit_required - approved.deposit)?; + let reason = &HoldReason::AssetApproval.into(); + T::NativeToken::hold(reason, owner, deposit_required - approved.deposit)?; approved.deposit = deposit_required; } approved.amount = approved.amount.saturating_add(amount); @@ -929,7 +959,13 @@ impl, I: 'static> Pallet { Self::transfer_and_die(id.clone(), owner, destination, amount, None, f)?.1; if remaining.is_zero() { - T::Currency::unreserve(owner, approved.deposit); + let reason = &HoldReason::AssetApproval.into(); + T::NativeToken::release( + reason, + owner, + approved.deposit, + Precision::BestEffort, + )?; Asset::::mutate(id.clone(), |maybe_details| { if let Some(details) = maybe_details { details.approvals.saturating_dec(); @@ -973,10 +1009,16 @@ impl, I: 'static> Pallet { let old_deposit = metadata.take().map_or(Zero::zero(), |m| m.deposit); let new_deposit = Self::calc_metadata_deposit(&name, &symbol); + let reason = &HoldReason::AssetMetadata.into(); if new_deposit > old_deposit { - T::Currency::reserve(from, new_deposit - old_deposit)?; + T::NativeToken::hold(reason, from, new_deposit - old_deposit)?; } else { - T::Currency::unreserve(from, old_deposit - new_deposit); + T::NativeToken::release( + reason, + from, + old_deposit - new_deposit, + Precision::BestEffort, + )?; } *metadata = Some(AssetMetadata { diff --git a/substrate/frame/assets/src/impl_fungibles.rs b/substrate/frame/assets/src/impl_fungibles.rs index 123abeba8283..c237c9618c7c 100644 --- a/substrate/frame/assets/src/impl_fungibles.rs +++ b/substrate/frame/assets/src/impl_fungibles.rs @@ -228,13 +228,13 @@ impl, I: 'static> fungibles::metadata::Mutate<:: impl, I: 'static> fungibles::metadata::MetadataDeposit< - ::AccountId>>::Balance, + ::AccountId>>::Balance, > for Pallet { fn calc_metadata_deposit( name: &[u8], symbol: &[u8], - ) -> ::AccountId>>::Balance { + ) -> ::AccountId>>::Balance { Self::calc_metadata_deposit(&name, &symbol) } } diff --git a/substrate/frame/assets/src/lib.rs b/substrate/frame/assets/src/lib.rs index 79e4fe300187..0a8f5b19c1d2 100644 --- a/substrate/frame/assets/src/lib.rs +++ b/substrate/frame/assets/src/lib.rs @@ -170,9 +170,12 @@ use frame_support::{ pallet_prelude::DispatchResultWithPostInfo, storage::KeyPrefixIterator, traits::{ - tokens::{fungibles, DepositConsequence, WithdrawConsequence}, - BalanceStatus::Reserved, - Currency, EnsureOriginWithArg, ReservableCurrency, StoredMap, + fungible::MutateHold, + tokens::{ + fungible, fungibles, DepositConsequence, Fortitude, Precision, Restriction, + WithdrawConsequence, + }, + EnsureOriginWithArg, StoredMap, }, }; use frame_system::Config as SystemConfig; @@ -233,6 +236,9 @@ pub mod pallet { type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// The overarching hold reason. + type RuntimeHoldReason: From>; + /// The units in which we record balances. type Balance: Member + Parameter @@ -266,7 +272,12 @@ pub mod pallet { + MaxEncodedLen; /// The currency mechanism. - type Currency: ReservableCurrency; + //type Currency: ReservableCurrency; + + type NativeToken: fungible::Inspect + + fungible::InspectHold + + fungible::Mutate + + fungible::MutateHold; /// Standard asset class creation is only allowed if the origin attempting it and the /// asset class are in this set. @@ -346,7 +357,7 @@ 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. + /// is the amount of `T::NativeToken` reserved for storing this. /// First key is the asset ID, second key is the owner and third key is the delegate. pub(super) type Approvals, I: 'static = ()> = StorageNMap< _, @@ -573,6 +584,17 @@ pub mod pallet { CallbackFailed, } + /// A reason for this pallet placing a hold on funds. + #[pallet::composite_enum] + pub enum HoldReason { + // Holds involved in asset construction: + AssetCreation, + AssetMetadata, + // Holds involved in using assets: + AssetAccount, + AssetApproval, + } + #[pallet::call(weight(>::WeightInfo))] impl, I: 'static> Pallet { /// Issue a new class of fungible assets from a public origin. @@ -608,8 +630,10 @@ pub mod pallet { ensure!(!Asset::::contains_key(&id), Error::::InUse); ensure!(!min_balance.is_zero(), Error::::MinBalanceZero); + use frame_support::traits::fungible::MutateHold; let deposit = T::AssetDeposit::get(); - T::Currency::reserve(&owner, deposit)?; + let reason = &HoldReason::AssetCreation.into(); + T::NativeToken::hold(reason, &owner, deposit)?; Asset::::insert( id.clone(), @@ -1049,7 +1073,7 @@ pub mod pallet { /// Origin must be Signed and the sender should be the Owner of the asset `id`. /// /// - `id`: The identifier of the asset. - /// - `owner`: The new Owner of this asset. + /// - `new_owner`: The new Owner of this asset. /// /// Emits `OwnerChanged`. /// @@ -1058,29 +1082,53 @@ pub mod pallet { pub fn transfer_ownership( origin: OriginFor, id: T::AssetIdParameter, - owner: AccountIdLookupOf, + new_owner: AccountIdLookupOf, ) -> DispatchResult { let origin = ensure_signed(origin)?; - let owner = T::Lookup::lookup(owner)?; + let new_owner = T::Lookup::lookup(new_owner)?; let id: T::AssetId = id.into(); Asset::::try_mutate(id.clone(), |maybe_details| { let details = maybe_details.as_mut().ok_or(Error::::Unknown)?; ensure!(details.status == AssetStatus::Live, Error::::LiveAsset); ensure!(origin == details.owner, Error::::NoPermission); - if details.owner == owner { + if details.owner == new_owner { return Ok(()) } let metadata_deposit = Metadata::::get(&id).deposit; - let deposit = details.deposit + metadata_deposit; + let deposit = details.deposit; // + metadata_deposit; // Move the deposit to the new owner. - T::Currency::repatriate_reserved(&details.owner, &owner, deposit, Reserved)?; + use frame_support::traits::fungible::MutateHold; + let reason = &HoldReason::AssetCreation.into(); + let metadata_reason = &HoldReason::AssetMetadata.into(); + if !deposit.is_zero() { + T::NativeToken::transfer_on_hold( + reason, + &origin, + &new_owner, + deposit, + Precision::Exact, + Restriction::OnHold, + Fortitude::Polite, + )?; + } + if !metadata_deposit.is_zero() { + T::NativeToken::transfer_on_hold( + metadata_reason, + &origin, + &new_owner, + metadata_deposit, + Precision::Exact, + Restriction::OnHold, + Fortitude::Polite, + )?; + } - details.owner = owner.clone(); + details.owner = new_owner.clone(); - Self::deposit_event(Event::OwnerChanged { asset_id: id, owner }); + Self::deposit_event(Event::OwnerChanged { asset_id: id, owner: new_owner }); Ok(()) }) } @@ -1177,7 +1225,8 @@ pub mod pallet { Metadata::::try_mutate_exists(id.clone(), |metadata| { let deposit = metadata.take().ok_or(Error::::Unknown)?.deposit; - T::Currency::unreserve(&d.owner, deposit); + let reason = &HoldReason::AssetMetadata.into(); + T::NativeToken::release(reason, &d.owner, deposit, Precision::BestEffort)?; Self::deposit_event(Event::MetadataCleared { asset_id: id }); Ok(()) }) @@ -1260,7 +1309,8 @@ pub mod pallet { let d = Asset::::get(&id).ok_or(Error::::Unknown)?; Metadata::::try_mutate_exists(id.clone(), |metadata| { let deposit = metadata.take().ok_or(Error::::Unknown)?.deposit; - T::Currency::unreserve(&d.owner, deposit); + let reason = &HoldReason::AssetMetadata.into(); + T::NativeToken::release(reason, &d.owner, deposit, Precision::BestEffort)?; Self::deposit_event(Event::MetadataCleared { asset_id: id }); Ok(()) }) @@ -1384,7 +1434,8 @@ pub mod pallet { let approval = Approvals::::take((id.clone(), &owner, &delegate)) .ok_or(Error::::Unknown)?; - T::Currency::unreserve(&owner, approval.deposit); + let reason = &HoldReason::AssetApproval.into(); + T::NativeToken::release(reason, &owner, approval.deposit, Precision::BestEffort)?; d.approvals.saturating_dec(); Asset::::insert(id.clone(), d); @@ -1429,7 +1480,8 @@ pub mod pallet { let approval = Approvals::::take((id.clone(), &owner, &delegate)) .ok_or(Error::::Unknown)?; - T::Currency::unreserve(&owner, approval.deposit); + let reason = &HoldReason::AssetApproval.into(); + T::NativeToken::release(reason, &owner, approval.deposit, Precision::BestEffort)?; d.approvals.saturating_dec(); Asset::::insert(id.clone(), d); diff --git a/substrate/frame/assets/src/mock.rs b/substrate/frame/assets/src/mock.rs index 32ad02da9041..0aace591531a 100644 --- a/substrate/frame/assets/src/mock.rs +++ b/substrate/frame/assets/src/mock.rs @@ -37,9 +37,9 @@ type Block = frame_system::mocking::MockBlock; construct_runtime!( pub enum Test { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Assets: pallet_assets::{Pallet, Call, Storage, Event}, + System: frame_system, + Balances: pallet_balances, + Assets: pallet_assets, } ); @@ -82,9 +82,9 @@ impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type RuntimeHoldReason = (); + type RuntimeHoldReason = RuntimeHoldReason; type FreezeIdentifier = (); - type MaxHolds = (); + type MaxHolds = ConstU32<4>; type MaxFreezes = (); } @@ -133,10 +133,11 @@ impl AssetsCallbackHandle { impl Config for Test { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = u64; type AssetId = u32; type AssetIdParameter = u32; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; type AssetDeposit = ConstU64<1>; diff --git a/substrate/frame/assets/src/tests.rs b/substrate/frame/assets/src/tests.rs index f1b116a0f4a0..4cd1dd68d620 100644 --- a/substrate/frame/assets/src/tests.rs +++ b/substrate/frame/assets/src/tests.rs @@ -22,9 +22,12 @@ use crate::{mock::*, Error}; use frame_support::{ assert_noop, assert_ok, dispatch::GetDispatchInfo, - traits::{fungibles::InspectEnumerable, tokens::Preservation::Protect, Currency}, + traits::{ + fungible::{InspectHold, Mutate}, + fungibles::InspectEnumerable, + tokens::{fungible::Inspect, Preservation::Protect}, + }, }; -use pallet_balances::Error as BalancesError; use sp_io::storage; use sp_runtime::{traits::ConvertInto, TokenError}; @@ -44,8 +47,8 @@ fn asset_account_counts(asset_id: u32) -> (u32, u32) { fn transfer_should_never_burn() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); + Balances::set_balance(&1, 100); + Balances::set_balance(&2, 100); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_eq!(Assets::balance(0, 1), 100); @@ -104,12 +107,12 @@ fn minting_too_many_insufficient_assets_fails() { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 1, 1, false, 1)); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 2, 1, false, 1)); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 1, 1, 100)); assert_noop!(Assets::mint(RuntimeOrigin::signed(1), 2, 1, 100), TokenError::CannotCreate); - Balances::make_free_balance_be(&2, 1); + Balances::set_balance(&2, 1); assert_ok!(Assets::transfer(RuntimeOrigin::signed(1), 0, 2, 100)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 2, 1, 100)); assert_eq!(asset_ids(), vec![0, 1, 2, 999]); @@ -122,13 +125,13 @@ fn minting_insufficient_asset_with_deposit_should_work_when_consumers_exhausted( assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 1, 1, false, 1)); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 2, 1, false, 1)); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 1, 1, 100)); assert_noop!(Assets::mint(RuntimeOrigin::signed(1), 2, 1, 100), TokenError::CannotCreate); assert_ok!(Assets::touch(RuntimeOrigin::signed(1), 2)); - assert_eq!(Balances::reserved_balance(&1), 10); + assert_eq!(Balances::total_balance_on_hold(&1), 10); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 2, 1, 100)); }); @@ -139,10 +142,10 @@ fn minting_insufficient_assets_with_deposit_without_consumer_should_work() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); assert_noop!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100), TokenError::CannotCreate); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::touch(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - assert_eq!(Balances::reserved_balance(&1), 10); + assert_eq!(Balances::total_balance_on_hold(&1), 10); assert_eq!(System::consumers(&1), 1); }); } @@ -151,11 +154,11 @@ fn minting_insufficient_assets_with_deposit_without_consumer_should_work() { fn refunding_asset_deposit_with_burn_should_work() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::touch(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_ok!(Assets::refund(RuntimeOrigin::signed(1), 0, true)); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); assert_eq!(Assets::balance(1, 0), 0); }); } @@ -164,7 +167,7 @@ fn refunding_asset_deposit_with_burn_should_work() { fn refunding_asset_deposit_with_burn_disallowed_should_fail() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::touch(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_noop!(Assets::refund(RuntimeOrigin::signed(1), 0, false), Error::::WouldBurn); @@ -176,17 +179,17 @@ fn refunding_asset_deposit_without_burn_should_work() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); assert_noop!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100), TokenError::CannotCreate); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::touch(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - Balances::make_free_balance_be(&2, 100); + Balances::set_balance(&2, 100); assert_ok!(Assets::transfer(RuntimeOrigin::signed(1), 0, 2, 100)); assert_eq!(Assets::balance(0, 2), 100); assert_eq!(Assets::balance(0, 1), 0); - assert_eq!(Balances::reserved_balance(&1), 10); + assert_eq!(Balances::total_balance_on_hold(&1), 10); assert_eq!(asset_account_counts(0), (2, 0)); assert_ok!(Assets::refund(RuntimeOrigin::signed(1), 0, false)); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); assert_eq!(Assets::balance(1, 0), 0); assert_eq!(asset_account_counts(0), (1, 0)); }); @@ -197,7 +200,7 @@ fn refunding_asset_deposit_without_burn_should_work() { fn refunding_calls_died_hook() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::touch(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_ok!(Assets::refund(RuntimeOrigin::signed(1), 0, true)); @@ -229,10 +232,10 @@ fn refunding_with_sufficient_existence_reason_should_fail() { fn refunding_with_deposit_from_should_fail() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); // create asset account `2` with deposit from `1` assert_ok!(Assets::touch_other(RuntimeOrigin::signed(1), 0, 2)); - assert_eq!(Balances::reserved_balance(&1), 10); + assert_eq!(Balances::total_balance_on_hold(&1), 10); // fails to refund assert_noop!(Assets::refund(RuntimeOrigin::signed(2), 0, true), Error::::NoDeposit); assert!(Account::::contains_key(0, &2)); @@ -244,8 +247,8 @@ fn refunding_frozen_with_consumer_ref_works() { new_test_ext().execute_with(|| { // 1 will be an admin // 2 will be a frozen account - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); + Balances::set_balance(&1, 100); + Balances::set_balance(&2, 100); // create non-sufficient asset assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); @@ -273,15 +276,15 @@ fn refunding_frozen_with_deposit_works() { new_test_ext().execute_with(|| { // 1 will be an asset admin // 2 will be a frozen account - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); + Balances::set_balance(&1, 100); + Balances::set_balance(&2, 100); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_eq!(System::consumers(&2), 0); assert_ok!(Assets::touch(RuntimeOrigin::signed(2), 0)); // reserve deposit holds one consumer ref assert_eq!(System::consumers(&2), 1); - assert_eq!(Balances::reserved_balance(&2), 10); + assert_eq!(Balances::total_balance_on_hold(&2), 10); assert!(Account::::contains_key(0, &2)); // transfer some assets to `2` assert_ok!(Assets::transfer(RuntimeOrigin::signed(1), 0, 2, 50)); @@ -295,7 +298,7 @@ fn refunding_frozen_with_deposit_works() { // success assert_ok!(Assets::refund(RuntimeOrigin::signed(2), 0, true)); assert!(!Account::::contains_key(0, &2)); - assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::total_balance_on_hold(&2), 0); assert_eq!(System::consumers(&2), 0); assert_eq!(asset_account_counts(0), (1, 0)); }); @@ -312,17 +315,17 @@ fn approval_lifecycle_works() { // so we create it :) assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - Balances::make_free_balance_be(&1, 2); + Balances::set_balance(&1, 2); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50)); assert_eq!(Asset::::get(0).unwrap().approvals, 1); - assert_eq!(Balances::reserved_balance(&1), 1); + assert_eq!(Balances::total_balance_on_hold(&1), 1); assert_ok!(Assets::transfer_approved(RuntimeOrigin::signed(2), 0, 1, 3, 40)); assert_eq!(Asset::::get(0).unwrap().approvals, 1); assert_ok!(Assets::cancel_approval(RuntimeOrigin::signed(1), 0, 2)); assert_eq!(Asset::::get(0).unwrap().approvals, 0); assert_eq!(Assets::balance(0, 1), 60); assert_eq!(Assets::balance(0, 3), 40); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); assert_eq!(asset_ids(), vec![0, 999]); }); } @@ -338,17 +341,17 @@ fn transfer_approved_all_funds() { // so we create it :) assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - Balances::make_free_balance_be(&1, 2); + Balances::set_balance(&1, 2); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50)); assert_eq!(Asset::::get(0).unwrap().approvals, 1); - assert_eq!(Balances::reserved_balance(&1), 1); + assert_eq!(Balances::total_balance_on_hold(&1), 1); // transfer the full amount, which should trigger auto-cleanup assert_ok!(Assets::transfer_approved(RuntimeOrigin::signed(2), 0, 1, 3, 50)); assert_eq!(Asset::::get(0).unwrap().approvals, 0); assert_eq!(Assets::balance(0, 1), 50); assert_eq!(Assets::balance(0, 3), 50); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); }); } @@ -357,19 +360,19 @@ fn approval_deposits_work() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - let e = BalancesError::::InsufficientBalance; + let e = TokenError::FundsUnavailable; assert_noop!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50), e); - Balances::make_free_balance_be(&1, 2); + Balances::set_balance(&1, 2); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50)); - assert_eq!(Balances::reserved_balance(&1), 1); + assert_eq!(Balances::total_balance_on_hold(&1), 1); assert_ok!(Assets::transfer_approved(RuntimeOrigin::signed(2), 0, 1, 3, 50)); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50)); assert_ok!(Assets::cancel_approval(RuntimeOrigin::signed(1), 0, 2)); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); }); } @@ -378,7 +381,7 @@ fn cannot_transfer_more_than_approved() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - Balances::make_free_balance_be(&1, 2); + Balances::set_balance(&1, 2); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50)); let e = Error::::Unapproved; assert_noop!(Assets::transfer_approved(RuntimeOrigin::signed(2), 0, 1, 3, 51), e); @@ -390,7 +393,7 @@ fn cannot_transfer_more_than_exists() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - Balances::make_free_balance_be(&1, 2); + Balances::set_balance(&1, 2); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 101)); let e = Error::::BalanceLow; assert_noop!(Assets::transfer_approved(RuntimeOrigin::signed(2), 0, 1, 3, 101), e); @@ -402,7 +405,7 @@ fn cancel_approval_works() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - Balances::make_free_balance_be(&1, 2); + Balances::set_balance(&1, 2); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50)); assert_eq!(Asset::::get(0).unwrap().approvals, 1); assert_noop!( @@ -432,7 +435,7 @@ fn force_cancel_approval_works() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - Balances::make_free_balance_be(&1, 2); + Balances::set_balance(&1, 2); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50)); assert_eq!(Asset::::get(0).unwrap().approvals, 1); let e = Error::::NoPermission; @@ -462,39 +465,41 @@ fn force_cancel_approval_works() { #[test] fn lifecycle_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::create(RuntimeOrigin::signed(1), 0, 1, 1)); - assert_eq!(Balances::reserved_balance(&1), 1); + assert_eq!(Balances::total_balance_on_hold(&1), 1); assert!(Asset::::contains_key(0)); assert_ok!(Assets::set_metadata(RuntimeOrigin::signed(1), 0, vec![0], vec![0], 12)); - assert_eq!(Balances::reserved_balance(&1), 4); + assert_eq!(Balances::total_balance_on_hold(&1), 4); assert!(Metadata::::contains_key(0)); - Balances::make_free_balance_be(&10, 100); + Balances::set_balance(&10, 100); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 10, 100)); - Balances::make_free_balance_be(&20, 100); + Balances::set_balance(&20, 100); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 20, 100)); assert_eq!(Account::::iter_prefix(0).count(), 2); + assert_ok!(Assets::clear_metadata(RuntimeOrigin::signed(1), 0)); + assert_ok!(Assets::freeze_asset(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::start_destroy(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::destroy_accounts(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::destroy_approvals(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::finish_destroy(RuntimeOrigin::signed(1), 0)); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); assert!(!Asset::::contains_key(0)); assert!(!Metadata::::contains_key(0)); assert_eq!(Account::::iter_prefix(0).count(), 0); assert_ok!(Assets::create(RuntimeOrigin::signed(1), 0, 1, 1)); - assert_eq!(Balances::reserved_balance(&1), 1); + assert_eq!(Balances::total_balance_on_hold(&1), 1); assert!(Asset::::contains_key(0)); assert_ok!(Assets::set_metadata(RuntimeOrigin::signed(1), 0, vec![0], vec![0], 12)); - assert_eq!(Balances::reserved_balance(&1), 4); + assert_eq!(Balances::total_balance_on_hold(&1), 4); assert!(Metadata::::contains_key(0)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 10, 100)); @@ -507,7 +512,7 @@ fn lifecycle_should_work() { assert_ok!(Assets::destroy_approvals(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::finish_destroy(RuntimeOrigin::signed(1), 0)); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); assert!(!Asset::::contains_key(0)); assert!(!Metadata::::contains_key(0)); @@ -518,13 +523,13 @@ fn lifecycle_should_work() { #[test] fn destroy_should_refund_approvals() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 10, 100)); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50)); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 3, 50)); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 4, 50)); - assert_eq!(Balances::reserved_balance(&1), 3); + assert_eq!(Balances::total_balance_on_hold(&1), 3); assert_eq!(asset_ids(), vec![0, 999]); assert_ok!(Assets::freeze_asset(RuntimeOrigin::signed(1), 0)); @@ -534,7 +539,7 @@ fn destroy_should_refund_approvals() { assert_ok!(Assets::destroy_approvals(RuntimeOrigin::signed(1), 0)); assert_ok!(Assets::finish_destroy(RuntimeOrigin::signed(1), 0)); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); assert_eq!(asset_ids(), vec![999]); // all approvals are removed @@ -599,7 +604,7 @@ fn non_providing_should_work() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); - Balances::make_free_balance_be(&0, 100); + Balances::set_balance(&0, 100); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 0, 100)); // Cannot mint into account 2 since it doesn't (yet) exist... @@ -615,8 +620,8 @@ fn non_providing_should_work() { TokenError::CannotCreate ); - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); + Balances::set_balance(&1, 100); + Balances::set_balance(&2, 100); assert_ok!(Assets::transfer(RuntimeOrigin::signed(0), 0, 1, 25)); assert_ok!(Assets::force_transfer(RuntimeOrigin::signed(1), 0, 0, 2, 25)); assert_eq!(asset_ids(), vec![0, 999]); @@ -661,7 +666,7 @@ fn min_balance_should_work() { // Death by `transfer_approved`. assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - Balances::make_free_balance_be(&1, 2); + Balances::set_balance(&1, 2); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 100)); assert_ok!(Assets::transfer_approved(RuntimeOrigin::signed(2), 0, 1, 3, 91)); assert_eq!(take_hooks(), vec![Hook::Died(0, 1)]); @@ -748,7 +753,7 @@ fn transferring_frozen_asset_should_not_work() { #[test] fn approve_transfer_frozen_asset_should_not_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_eq!(Assets::balance(0, 1), 100); @@ -830,16 +835,16 @@ fn origin_guards_should_work() { #[test] fn transfer_owner_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); + Balances::set_balance(&1, 100); + Balances::set_balance(&2, 100); assert_ok!(Assets::create(RuntimeOrigin::signed(1), 0, 1, 1)); assert_eq!(asset_ids(), vec![0, 999]); - assert_eq!(Balances::reserved_balance(&1), 1); + assert_eq!(Balances::total_balance_on_hold(&1), 1); assert_ok!(Assets::transfer_ownership(RuntimeOrigin::signed(1), 0, 2)); - assert_eq!(Balances::reserved_balance(&2), 1); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&2), 1); assert_noop!( Assets::transfer_ownership(RuntimeOrigin::signed(1), 0, 1), @@ -854,9 +859,13 @@ fn transfer_owner_should_work() { vec![0u8; 10], 12 )); + assert_eq!(Balances::total_balance_on_hold(&2), 1 + 10 + 10 + 1); + assert_eq!(Balances::balance(&2), 79); + assert_eq!(Assets::balance(0, &2), 0); + assert_ok!(Assets::transfer_ownership(RuntimeOrigin::signed(2), 0, 1)); - assert_eq!(Balances::reserved_balance(&1), 22); - assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 22); + assert_eq!(Balances::total_balance_on_hold(&2), 0); }); } @@ -896,7 +905,7 @@ fn transferring_from_frozen_account_should_not_work() { fn touching_and_freezing_account_with_zero_asset_balance_should_work() { new_test_ext().execute_with(|| { // need some deposit for the touch - Balances::make_free_balance_be(&2, 100); + Balances::set_balance(&2, 100); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_eq!(Assets::balance(0, 1), 100); @@ -921,9 +930,9 @@ fn touch_other_works() { // 1 will be admin // 2 will be freezer // 4 will be an account attempting to execute `touch_other` - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); - Balances::make_free_balance_be(&4, 100); + Balances::set_balance(&1, 100); + Balances::set_balance(&2, 100); + Balances::set_balance(&4, 100); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); assert_ok!(Assets::set_team(RuntimeOrigin::signed(1), 0, 1, 1, 2)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); @@ -949,7 +958,7 @@ fn touch_other_works() { #[test] fn touch_other_and_freeze_works() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_eq!(Assets::balance(0, 1), 100); @@ -974,15 +983,15 @@ fn account_with_deposit_not_destroyed() { new_test_ext().execute_with(|| { // 1 will be the asset admin // 2 will exist without balance but with deposit - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); + Balances::set_balance(&1, 100); + Balances::set_balance(&2, 100); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); assert_eq!(Assets::balance(0, 1), 100); assert_eq!(Assets::balance(0, 2), 0); // case 1; account `2` not destroyed with a holder's deposit assert_ok!(Assets::touch(RuntimeOrigin::signed(2), 0)); - assert_eq!(Balances::reserved_balance(&2), 10); + assert_eq!(Balances::total_balance_on_hold(&2), 10); assert!(Account::::contains_key(0, &2)); assert_ok!(Assets::transfer(RuntimeOrigin::signed(1), 0, 2, 50)); assert_ok!(Assets::transfer(RuntimeOrigin::signed(2), 0, 1, 50)); @@ -995,7 +1004,7 @@ fn account_with_deposit_not_destroyed() { // case 2; account `2` not destroyed with a deposit from `1` assert_ok!(Assets::touch_other(RuntimeOrigin::signed(1), 0, 2)); - assert_eq!(Balances::reserved_balance(&1), 10); + assert_eq!(Balances::total_balance_on_hold(&1), 10); assert_ok!(Assets::transfer(RuntimeOrigin::signed(1), 0, 2, 50)); assert_ok!(Assets::transfer(RuntimeOrigin::signed(2), 0, 1, 50)); assert!(Account::::contains_key(0, &2)); @@ -1008,16 +1017,16 @@ fn refund_other_should_fails() { // 1 will be the asset admin // 2 will be the asset freezer // 3 will be created with deposit of 2 - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); - Balances::make_free_balance_be(&3, 0); + Balances::set_balance(&1, 100); + Balances::set_balance(&2, 100); + Balances::set_balance(&3, 0); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::set_team(RuntimeOrigin::signed(1), 0, 1, 1, 2)); assert!(!Account::::contains_key(0, &3)); // create asset account `3` with a deposit from freezer `2` assert_ok!(Assets::touch_other(RuntimeOrigin::signed(2), 0, 3)); - assert_eq!(Balances::reserved_balance(&2), 10); + assert_eq!(Balances::total_balance_on_hold(&2), 10); // fail case; non-existing asset account `10` assert_noop!( @@ -1076,8 +1085,8 @@ fn refund_other_works() { // 1 will be the asset admin // 2 will be the asset freezer // 3 will be created with deposit of 2 - Balances::make_free_balance_be(&1, 100); - Balances::make_free_balance_be(&2, 100); + Balances::set_balance(&1, 100); + Balances::set_balance(&2, 100); assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::set_team(RuntimeOrigin::signed(1), 0, 1, 1, 2)); assert!(!Account::::contains_key(0, &3)); @@ -1085,19 +1094,19 @@ fn refund_other_works() { // success case; freezer is depositor assert_ok!(Assets::touch_other(RuntimeOrigin::signed(2), 0, 3)); - assert_eq!(Balances::reserved_balance(&2), 10); + assert_eq!(Balances::total_balance_on_hold(&2), 10); assert_eq!(asset_account_counts(0), (1, 0)); assert_ok!(Assets::refund_other(RuntimeOrigin::signed(2), 0, 3)); - assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::total_balance_on_hold(&2), 0); assert!(!Account::::contains_key(0, &3)); assert_eq!(asset_account_counts(0), (0, 0)); // success case; admin is depositor assert_ok!(Assets::touch_other(RuntimeOrigin::signed(1), 0, 3)); - assert_eq!(Balances::reserved_balance(&1), 10); + assert_eq!(Balances::total_balance_on_hold(&1), 10); assert_eq!(asset_account_counts(0), (1, 0)); assert_ok!(Assets::refund_other(RuntimeOrigin::signed(1), 0, 3)); - assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(Balances::total_balance_on_hold(&1), 0); assert!(!Account::::contains_key(0, &3)); assert_eq!(asset_account_counts(0), (0, 0)); }) @@ -1207,7 +1216,7 @@ fn set_metadata_should_work() { ); // Successfully add metadata and take deposit - Balances::make_free_balance_be(&1, 30); + Balances::set_balance(&1, 30); assert_ok!(Assets::set_metadata( RuntimeOrigin::signed(1), 0, @@ -1238,7 +1247,7 @@ fn set_metadata_should_work() { // Cannot over-reserve assert_noop!( Assets::set_metadata(RuntimeOrigin::signed(1), 0, vec![0u8; 20], vec![0u8; 20], 12), - BalancesError::::InsufficientBalance, + TokenError::FundsUnavailable ); // Clear Metadata @@ -1305,7 +1314,7 @@ fn freezer_should_work() { ); // create an approved transfer... - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::approve_transfer(RuntimeOrigin::signed(1), 0, 2, 50)); let e = Error::::BalanceLow; // ...but that wont work either: @@ -1431,8 +1440,8 @@ fn force_metadata_should_work() { #[test] fn force_asset_status_should_work() { new_test_ext().execute_with(|| { - Balances::make_free_balance_be(&1, 10); - Balances::make_free_balance_be(&2, 10); + Balances::set_balance(&1, 10); + Balances::set_balance(&2, 10); assert_ok!(Assets::create(RuntimeOrigin::signed(1), 0, 1, 30)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 50)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 2, 150)); @@ -1494,7 +1503,7 @@ fn force_asset_status_should_work() { fn set_min_balance_should_work() { new_test_ext().execute_with(|| { let id = 42; - Balances::make_free_balance_be(&1, 10); + Balances::set_balance(&1, 10); assert_ok!(Assets::create(RuntimeOrigin::signed(1), id, 1, 30)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), id, 1, 100)); @@ -1613,7 +1622,7 @@ fn querying_allowance_should_work() { use frame_support::traits::fungibles::approvals::{Inspect, Mutate}; assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 1, 100)); - Balances::make_free_balance_be(&1, 2); + Balances::set_balance(&1, 2); assert_ok!(Assets::approve(0, &1, &2, 50)); assert_eq!(Assets::allowance(0, &1, &2), 50); // Transfer asset 0, from owner 1 and delegate 2 to destination 3 @@ -1660,7 +1669,7 @@ fn normal_asset_create_and_destroy_callbacks_should_work() { assert!(storage::get(AssetsCallbackHandle::CREATED.as_bytes()).is_none()); assert!(storage::get(AssetsCallbackHandle::DESTROYED.as_bytes()).is_none()); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_ok!(Assets::create(RuntimeOrigin::signed(1), 0, 1, 1)); assert!(storage::get(AssetsCallbackHandle::CREATED.as_bytes()).is_some()); assert!(storage::get(AssetsCallbackHandle::DESTROYED.as_bytes()).is_none()); @@ -1691,7 +1700,7 @@ fn asset_create_and_destroy_is_reverted_if_callback_fails() { new_test_ext().execute_with(|| { // Asset creation fails due to callback failure AssetsCallbackHandle::set_return_error(); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); assert_noop!( Assets::create(RuntimeOrigin::signed(1), 0, 1, 1), Error::::CallbackFailed @@ -1746,32 +1755,32 @@ fn weights_sane() { fn asset_destroy_refund_existence_deposit() { new_test_ext().execute_with(|| { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, false, 1)); - Balances::make_free_balance_be(&1, 100); + Balances::set_balance(&1, 100); let admin = 1; let admin_origin = RuntimeOrigin::signed(admin); let account2 = 2; // account with own deposit let account3 = 3; // account with admin's deposit - Balances::make_free_balance_be(&account2, 100); + Balances::set_balance(&account2, 100); - assert_eq!(Balances::reserved_balance(&account2), 0); - assert_eq!(Balances::reserved_balance(&account3), 0); - assert_eq!(Balances::reserved_balance(&admin), 0); + assert_eq!(Balances::total_balance_on_hold(&account2), 0); + assert_eq!(Balances::total_balance_on_hold(&account3), 0); + assert_eq!(Balances::total_balance_on_hold(&admin), 0); assert_ok!(Assets::touch(RuntimeOrigin::signed(account2), 0)); assert_ok!(Assets::touch_other(admin_origin.clone(), 0, account3)); - assert_eq!(Balances::reserved_balance(&account2), 10); - assert_eq!(Balances::reserved_balance(&account3), 0); - assert_eq!(Balances::reserved_balance(&admin), 10); + assert_eq!(Balances::total_balance_on_hold(&account2), 10); + assert_eq!(Balances::total_balance_on_hold(&account3), 0); + assert_eq!(Balances::total_balance_on_hold(&admin), 10); assert_ok!(Assets::start_destroy(admin_origin.clone(), 0)); assert_ok!(Assets::destroy_accounts(admin_origin.clone(), 0)); assert_ok!(Assets::destroy_approvals(admin_origin.clone(), 0)); assert_ok!(Assets::finish_destroy(admin_origin.clone(), 0)); - assert_eq!(Balances::reserved_balance(&account2), 0); - assert_eq!(Balances::reserved_balance(&account3), 0); - assert_eq!(Balances::reserved_balance(&admin), 0); + assert_eq!(Balances::total_balance_on_hold(&account2), 0); + assert_eq!(Balances::total_balance_on_hold(&account3), 0); + assert_eq!(Balances::total_balance_on_hold(&admin), 0); }); } diff --git a/substrate/frame/assets/src/types.rs b/substrate/frame/assets/src/types.rs index 67f9bf07f5e7..6fae343e66f5 100644 --- a/substrate/frame/assets/src/types.rs +++ b/substrate/frame/assets/src/types.rs @@ -25,7 +25,7 @@ use frame_support::{ use sp_runtime::{traits::Convert, FixedPointNumber, FixedU128}; pub(super) type DepositBalanceOf = - <>::Currency as Currency<::AccountId>>::Balance; + <>::NativeToken as fungible::Inspect<::AccountId>>::Balance; pub(super) type AssetAccountOf = AssetAccount< >::Balance, DepositBalanceOf, diff --git a/substrate/frame/nft-fractionalization/src/mock.rs b/substrate/frame/nft-fractionalization/src/mock.rs index c690f0e580ed..051c881860d8 100644 --- a/substrate/frame/nft-fractionalization/src/mock.rs +++ b/substrate/frame/nft-fractionalization/src/mock.rs @@ -93,11 +93,12 @@ impl pallet_balances::Config for Test { impl pallet_assets::Config for Test { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = u64; type RemoveItemsLimit = ConstU32<1000>; type AssetId = u32; type AssetIdParameter = u32; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; type AssetDeposit = ConstU64<1>; diff --git a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs index bfbe8b4178ce..bd46abb94868 100644 --- a/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-conversion-tx-payment/src/mock.rs @@ -120,8 +120,8 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type FreezeIdentifier = (); type MaxFreezes = (); - type RuntimeHoldReason = (); - type MaxHolds = (); + type RuntimeHoldReason = RuntimeHoldReason; + type MaxHolds = ConstU32<4>; } impl WeightToFeeT for WeightToFee { @@ -174,10 +174,11 @@ type AssetId = u32; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = AssetId; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; type AssetDeposit = ConstU64<2>; @@ -198,11 +199,12 @@ impl pallet_assets::Config for Runtime { impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = u64; type RemoveItemsLimit = ConstU32<1000>; type AssetId = u32; type AssetIdParameter = u32; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = frame_system::EnsureRoot; type AssetDeposit = ConstU64<0>; diff --git a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs index b8d7b523ca25..4f893d752f0f 100644 --- a/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs +++ b/substrate/frame/transaction-payment/asset-tx-payment/src/mock.rs @@ -112,8 +112,8 @@ impl pallet_balances::Config for Runtime { type ReserveIdentifier = [u8; 8]; type FreezeIdentifier = (); type MaxFreezes = (); - type RuntimeHoldReason = (); - type MaxHolds = (); + type RuntimeHoldReason = RuntimeHoldReason; + type MaxHolds = ConstU32<4>; // assets } impl WeightToFeeT for WeightToFee { @@ -147,10 +147,11 @@ type AssetId = u32; impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type RuntimeHoldReason = RuntimeHoldReason; type Balance = Balance; type AssetId = AssetId; type AssetIdParameter = codec::Compact; - type Currency = Balances; + type NativeToken = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; type AssetDeposit = ConstU64<2>;