Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Allow other pallets to check asset ids. (#12666)
Browse files Browse the repository at this point in the history
* Make it easier for other pallets to check asset ids.

* Avoid boxing

* cargo fmt
  • Loading branch information
gilescope authored Nov 11, 2022
1 parent 7763a32 commit b042ebd
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 3 deletions.
11 changes: 11 additions & 0 deletions frame/assets/src/impl_fungibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,14 @@ impl<T: Config<I>, I: 'static> fungibles::roles::Inspect<<T as SystemConfig>::Ac
Asset::<T, I>::get(asset).map(|x| x.freezer)
}
}

impl<T: Config<I>, I: 'static> fungibles::InspectEnumerable<T::AccountId> for Pallet<T, I> {
type AssetsIterator = KeyPrefixIterator<<T as Config<I>>::AssetId>;

/// Returns an iterator of the assets in existence.
///
/// NOTE: iterating this list invokes a storage read per item.
fn asset_ids() -> Self::AssetsIterator {
Asset::<T, I>::iter_keys()
}
}
1 change: 1 addition & 0 deletions frame/assets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ use frame_support::{
dispatch::{DispatchError, DispatchResult},
ensure,
pallet_prelude::DispatchResultWithPostInfo,
storage::KeyPrefixIterator,
traits::{
tokens::{fungibles, DepositConsequence, WithdrawConsequence},
BalanceStatus::Reserved,
Expand Down
26 changes: 23 additions & 3 deletions frame/assets/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u32> {
let mut s: Vec<_> = Assets::asset_ids().collect();
s.sort();
s
}

#[test]
fn basic_minting_should_work() {
new_test_ext().execute_with(|| {
Expand All @@ -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]);
});
}

Expand All @@ -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]);
});
}

Expand Down Expand Up @@ -137,6 +148,7 @@ fn refunding_calls_died_hook() {

assert_eq!(Asset::<Test>::get(0).unwrap().accounts, 0);
assert_eq!(hooks(), vec![Hook::Died(0, 1)]);
assert_eq!(asset_ids(), vec![0, 999]);
});
}

Expand All @@ -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]);
});
}

Expand Down Expand Up @@ -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::<Test>::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::<Test>::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]);
});
}

Expand All @@ -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::<Test>::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::<Test>::iter().count().is_zero())
Expand Down Expand Up @@ -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]);
});
}

Expand Down Expand Up @@ -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]);
});
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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::<Balances, Test, ConvertInto>::to_asset_balance(100, 1234),
Err(ConversionError::AssetMissing)
Expand All @@ -1035,7 +1055,7 @@ fn balance_conversion_should_work() {
#[test]
fn assets_from_genesis_should_exist() {
new_test_ext().execute_with(|| {
assert!(Asset::<Test>::contains_key(999));
assert_eq!(asset_ids(), vec![999]);
assert!(Metadata::<Test>::contains_key(999));
assert_eq!(Assets::balance(999, 1), 100);
assert_eq!(Assets::total_supply(999), 100);
Expand Down
2 changes: 2 additions & 0 deletions frame/support/src/traits/tokens/fungibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
26 changes: 26 additions & 0 deletions frame/support/src/traits/tokens/fungibles/enumerable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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;

/// Interface for enumerating assets in existence or owned by a given account.
pub trait InspectEnumerable<AccountId>: Inspect<AccountId> {
type AssetsIterator;

/// Returns an iterator of the collections in existence.
fn asset_ids() -> Self::AssetsIterator;
}

0 comments on commit b042ebd

Please sign in to comment.