From 3901a910c55376a3c4691e3955d4d909bd9cbda2 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Wed, 9 Nov 2022 17:02:33 +0000 Subject: [PATCH 1/3] Make it easier for other pallets to check asset ids. --- frame/assets/src/impl_fungibles.rs | 9 +++++++ frame/assets/src/tests.rs | 26 ++++++++++++++++--- frame/support/src/traits/tokens/fungibles.rs | 2 ++ .../src/traits/tokens/fungibles/enumerable.rs | 25 ++++++++++++++++++ 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 frame/support/src/traits/tokens/fungibles/enumerable.rs diff --git a/frame/assets/src/impl_fungibles.rs b/frame/assets/src/impl_fungibles.rs index 842ee5c102c1d..69c0d25dd19b6 100644 --- a/frame/assets/src/impl_fungibles.rs +++ b/frame/assets/src/impl_fungibles.rs @@ -283,3 +283,12 @@ impl, I: 'static> fungibles::roles::Inspect<::Ac Asset::::get(asset).map(|x| x.freezer) } } + +impl, I: 'static> fungibles::InspectEnumerable for Pallet { + /// Returns an iterator of the assets in existence. + /// + /// NOTE: iterating this list invokes a storage read per item. + fn asset_ids() -> Box> { + Box::new(Asset::::iter_keys()) + } +} diff --git a/frame/assets/src/tests.rs b/frame/assets/src/tests.rs index 48cfad45a49fc..65e8b66705290 100644 --- a/frame/assets/src/tests.rs +++ b/frame/assets/src/tests.rs @@ -19,10 +19,19 @@ use super::*; use crate::{mock::*, Error}; -use frame_support::{assert_noop, assert_ok, traits::Currency}; +use frame_support::{ + assert_noop, assert_ok, + traits::{fungibles::InspectEnumerable, Currency}, +}; use pallet_balances::Error as BalancesError; use sp_runtime::{traits::ConvertInto, TokenError}; +fn asset_ids() -> Vec { + let mut s: Vec<_> = Assets::asset_ids().collect(); + s.sort(); + s +} + #[test] fn basic_minting_should_work() { new_test_ext().execute_with(|| { @@ -31,6 +40,7 @@ fn basic_minting_should_work() { assert_eq!(Assets::balance(0, 1), 100); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 2, 100)); assert_eq!(Assets::balance(0, 2), 100); + assert_eq!(asset_ids(), vec![0, 999]); }); } @@ -48,6 +58,7 @@ fn minting_too_many_insufficient_assets_fails() { Balances::make_free_balance_be(&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]); }); } @@ -137,6 +148,7 @@ fn refunding_calls_died_hook() { assert_eq!(Asset::::get(0).unwrap().accounts, 0); assert_eq!(hooks(), vec![Hook::Died(0, 1)]); + assert_eq!(asset_ids(), vec![0, 999]); }); } @@ -162,6 +174,7 @@ fn approval_lifecycle_works() { assert_eq!(Assets::balance(0, 1), 60); assert_eq!(Assets::balance(0, 3), 40); assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(asset_ids(), vec![0, 999]); }); } @@ -352,12 +365,14 @@ fn destroy_with_bad_witness_should_not_work() { assert_ok!(Assets::force_create(RuntimeOrigin::root(), 0, 1, true, 1)); let mut w = Asset::::get(0).unwrap().destroy_witness(); assert_ok!(Assets::mint(RuntimeOrigin::signed(1), 0, 10, 100)); + assert_eq!(asset_ids(), vec![0, 999]); // witness too low assert_noop!(Assets::destroy(RuntimeOrigin::signed(1), 0, w), Error::::BadWitness); // witness too high is okay though w.accounts += 2; w.sufficients += 2; assert_ok!(Assets::destroy(RuntimeOrigin::signed(1), 0, w)); + assert_eq!(asset_ids(), vec![999]); }); } @@ -371,10 +386,12 @@ fn destroy_should_refund_approvals() { 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!(asset_ids(), vec![0, 999]); let w = Asset::::get(0).unwrap().destroy_witness(); assert_ok!(Assets::destroy(RuntimeOrigin::signed(1), 0, w)); assert_eq!(Balances::reserved_balance(&1), 0); + assert_eq!(asset_ids(), vec![999]); // all approvals are removed assert!(Approvals::::iter().count().is_zero()) @@ -406,6 +423,7 @@ fn non_providing_should_work() { Balances::make_free_balance_be(&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]); }); } @@ -498,6 +516,7 @@ fn transferring_enough_to_kill_source_when_keep_alive_should_fail() { assert_eq!(Assets::balance(0, 1), 10); assert_eq!(Assets::balance(0, 2), 90); assert!(hooks().is_empty()); + assert_eq!(asset_ids(), vec![0, 999]); }); } @@ -582,6 +601,7 @@ fn transfer_owner_should_work() { Balances::make_free_balance_be(&1, 100); Balances::make_free_balance_be(&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); @@ -1012,7 +1032,7 @@ fn balance_conversion_should_work() { assert_ok!(Assets::force_create(RuntimeOrigin::root(), id, 1, true, 10)); let not_sufficient = 23; assert_ok!(Assets::force_create(RuntimeOrigin::root(), not_sufficient, 1, false, 10)); - + assert_eq!(asset_ids(), vec![23, 42, 999]); assert_eq!( BalanceToAssetBalance::::to_asset_balance(100, 1234), Err(ConversionError::AssetMissing) @@ -1035,7 +1055,7 @@ fn balance_conversion_should_work() { #[test] fn assets_from_genesis_should_exist() { new_test_ext().execute_with(|| { - assert!(Asset::::contains_key(999)); + assert_eq!(asset_ids(), vec![999]); assert!(Metadata::::contains_key(999)); assert_eq!(Assets::balance(999, 1), 100); assert_eq!(Assets::total_supply(999), 100); diff --git a/frame/support/src/traits/tokens/fungibles.rs b/frame/support/src/traits/tokens/fungibles.rs index e4108b7f80a98..9bdd5a10d7944 100644 --- a/frame/support/src/traits/tokens/fungibles.rs +++ b/frame/support/src/traits/tokens/fungibles.rs @@ -27,6 +27,8 @@ use sp_std::vec::Vec; pub mod approvals; mod balanced; +pub mod enumerable; +pub use enumerable::InspectEnumerable; pub mod metadata; pub use balanced::{Balanced, Unbalanced}; mod imbalance; diff --git a/frame/support/src/traits/tokens/fungibles/enumerable.rs b/frame/support/src/traits/tokens/fungibles/enumerable.rs new file mode 100644 index 0000000000000..7f8991131d5eb --- /dev/null +++ b/frame/support/src/traits/tokens/fungibles/enumerable.rs @@ -0,0 +1,25 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::traits::fungibles::Inspect; +use sp_std::boxed::Box; + +/// Interface for enumerating assets in existence or owned by a given account. +pub trait InspectEnumerable: Inspect { + /// Returns an iterator of the collections in existence. + fn asset_ids() -> Box>; +} From f6f6cf0059d9cc5a027c09894a0f2e77e351a6a6 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Fri, 11 Nov 2022 13:12:50 +0000 Subject: [PATCH 2/3] Avoid boxing --- frame/assets/src/impl_fungibles.rs | 6 ++++-- frame/assets/src/lib.rs | 1 + frame/support/src/traits/tokens/fungibles/enumerable.rs | 7 ++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/frame/assets/src/impl_fungibles.rs b/frame/assets/src/impl_fungibles.rs index 69c0d25dd19b6..5cddf23680ac2 100644 --- a/frame/assets/src/impl_fungibles.rs +++ b/frame/assets/src/impl_fungibles.rs @@ -285,10 +285,12 @@ impl, I: 'static> fungibles::roles::Inspect<::Ac } impl, I: 'static> fungibles::InspectEnumerable for Pallet { + type AssetsIterator = KeyPrefixIterator<>::AssetId>; + /// Returns an iterator of the assets in existence. /// /// NOTE: iterating this list invokes a storage read per item. - fn asset_ids() -> Box> { - Box::new(Asset::::iter_keys()) + fn asset_ids() -> Self::AssetsIterator { + Asset::::iter_keys() } } diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 28743f917d323..9f319866272cb 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -153,6 +153,7 @@ use frame_support::{ dispatch::{DispatchError, DispatchResult}, ensure, pallet_prelude::DispatchResultWithPostInfo, + storage::KeyPrefixIterator, traits::{ tokens::{fungibles, DepositConsequence, WithdrawConsequence}, BalanceStatus::Reserved, diff --git a/frame/support/src/traits/tokens/fungibles/enumerable.rs b/frame/support/src/traits/tokens/fungibles/enumerable.rs index 7f8991131d5eb..fc78454833599 100644 --- a/frame/support/src/traits/tokens/fungibles/enumerable.rs +++ b/frame/support/src/traits/tokens/fungibles/enumerable.rs @@ -16,10 +16,11 @@ // limitations under the License. use crate::traits::fungibles::Inspect; -use sp_std::boxed::Box; /// Interface for enumerating assets in existence or owned by a given account. pub trait InspectEnumerable: Inspect { + type AssetsIterator; + /// Returns an iterator of the collections in existence. - fn asset_ids() -> Box>; -} + fn asset_ids() -> Self::AssetsIterator; +} \ No newline at end of file From 8b03519320bea99e147644adb0a81866ce0c06f8 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Fri, 11 Nov 2022 13:21:43 +0000 Subject: [PATCH 3/3] cargo fmt --- frame/support/src/traits/tokens/fungibles/enumerable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/support/src/traits/tokens/fungibles/enumerable.rs b/frame/support/src/traits/tokens/fungibles/enumerable.rs index fc78454833599..151d15b3684a5 100644 --- a/frame/support/src/traits/tokens/fungibles/enumerable.rs +++ b/frame/support/src/traits/tokens/fungibles/enumerable.rs @@ -23,4 +23,4 @@ pub trait InspectEnumerable: Inspect { /// Returns an iterator of the collections in existence. fn asset_ids() -> Self::AssetsIterator; -} \ No newline at end of file +}