Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 19 additions & 1 deletion pallets/asset-index/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use xcm::v0::MultiLocation;

benchmarks! {
add_asset {
let asset_id = 42.into();
let asset_id = 42_u32.into();
let caller: T::AccountId = whitelisted_caller();
let million = 1_000_000u32.into();
T::IndexToken::deposit_creating(&caller, million);
Expand All @@ -28,4 +28,22 @@ benchmarks! {
))
);
}

set_metadata {
let asset_id = 0_u32.into();
let name = b"pint".to_vec();
let symbol = b"pint".to_vec();
let decimals = 8_u8;
}: _(
RawOrigin::Signed(whitelisted_caller()),
asset_id,
name.clone(),
symbol.clone(),
decimals
) verify {
let metadata = <Metadata<T>>::get(asset_id);
assert_eq!(metadata.name.as_slice(), name.as_slice());
assert_eq!(metadata.symbol.as_slice(), symbol.as_slice());
assert_eq!(metadata.decimals, decimals);
}
}
78 changes: 75 additions & 3 deletions pallets/asset-index/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ mod tests;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
pub mod traits;
mod types;
pub mod types;

#[frame_support::pallet]
// this is requires as the #[pallet::event] proc macro generates code that violates this lint
Expand Down Expand Up @@ -49,7 +49,8 @@ pub mod pallet {
pub use crate::traits::{AssetRecorder, MultiAssetRegistry};
pub use crate::types::MultiAssetAdapter;
use crate::types::{
AssetAvailability, AssetWithdrawal, IndexAssetData, PendingRedemption, RedemptionState,
AssetAvailability, AssetMetadata, AssetWithdrawal, IndexAssetData, PendingRedemption,
RedemptionState,
};

type AccountIdFor<T> = <T as frame_system::Config>::AccountId;
Expand Down Expand Up @@ -91,7 +92,7 @@ pub mod pallet {
Self::Balance,
>;
/// Type used to identify assets
type AssetId: Parameter + Member + From<u32> + Copy;
type AssetId: Parameter + Member + AtLeast32BitUnsigned + Copy;
/// Handles asset depositing and withdrawing from sovereign user accounts
type MultiAssetDepository: MultiAssetDepository<
Self::AssetId,
Expand All @@ -107,6 +108,9 @@ pub mod pallet {
type TreasuryPalletId: Get<PalletId>;
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;

/// The maximum length of a name or symbol stored on-chain.
type StringLimit: Get<u32>;

/// The weight for this pallet's extrinsics.
type WeightInfo: WeightInfo;
}
Expand All @@ -130,6 +134,18 @@ pub mod pallet {
OptionQuery,
>;

#[pallet::storage]
/// Metadata of an asset ( for reversed usage now ).
pub(super) type Metadata<T: Config> = StorageMap<
_,
Blake2_128Concat,
T::AssetId,
AssetMetadata<BoundedVec<u8, T::StringLimit>>,
ValueQuery,
GetDefault,
ConstU32<300_000>,
>;

#[pallet::event]
#[pallet::metadata(T::AssetId = "AccountId", AccountIdFor < T > = "AccountId", T::Balance = "Balance")]
#[pallet::generate_deposit(pub (super) fn deposit_event)]
Expand All @@ -152,12 +168,18 @@ pub mod pallet {
AccountIdFor<T>,
Vec<AssetWithdrawal<T::AssetId, T::Balance>>,
),
/// New metadata has been set for an asset. \[asset_id, name, symbol, decimals\]
MetadataSet(T::AssetId, Vec<u8>, Vec<u8>, u8),
}

#[pallet::error]
pub enum Error<T> {
/// Thrown if adding units to an asset holding causes its numerical type to overflow
AssetUnitsOverflow,
/// The given asset ID is unknown.
UnknownAsset,
/// Invalid metadata given.
BadMetadata,
/// Thrown if no index could be found for an asset identifier.
UnsupportedAsset,
/// Thrown if calculating the volume of units of an asset with it's price overflows.
Expand Down Expand Up @@ -207,6 +229,51 @@ pub mod pallet {
Ok(().into())
}

/// Force the metadata for an asset to some value.
///
/// Origin must be ForceOrigin.
///
/// Any deposit is left alone.
///
/// - `id`: The identifier of the asset to update.
/// - `name`: The user friendly name of this asset. Limited in length by `StringLimit`.
/// - `symbol`: The exchange symbol for this asset. Limited in length by `StringLimit`.
/// - `decimals`: The number of decimals this asset uses to represent one unit.
///
/// Emits `MetadataSet`.
///
/// Weight: `O(N + S)` where N and S are the length of the name and symbol respectively.
#[pallet::weight(T::WeightInfo::add_asset())]
pub fn set_metadata(
origin: OriginFor<T>,
#[pallet::compact] id: T::AssetId,
name: Vec<u8>,
symbol: Vec<u8>,
decimals: u8,
) -> DispatchResult {
T::AdminOrigin::ensure_origin(origin)?;

let bounded_name: BoundedVec<u8, T::StringLimit> = name
.clone()
.try_into()
.map_err(|_| <Error<T>>::BadMetadata)?;
let bounded_symbol: BoundedVec<u8, T::StringLimit> = symbol
.clone()
.try_into()
.map_err(|_| <Error<T>>::BadMetadata)?;

<Metadata<T>>::try_mutate_exists(id, |metadata| {
*metadata = Some(AssetMetadata {
name: bounded_name,
symbol: bounded_symbol,
decimals,
});

Self::deposit_event(Event::MetadataSet(id, name, symbol, decimals));
Ok(())
})
}

/// Initiate a transfer from the user's sovereign account into the index.
///
/// This will withdraw the given amount from the user's sovereign account and mints PINT
Expand Down Expand Up @@ -568,12 +635,17 @@ pub mod pallet {
/// Trait for the asset-index pallet extrinsic weights.
pub trait WeightInfo {
fn add_asset() -> Weight;
fn set_metadata() -> Weight;
}

/// For backwards compatibility and tests
impl WeightInfo for () {
fn add_asset() -> Weight {
Default::default()
}

fn set_metadata() -> Weight {
Default::default()
}
}
}
2 changes: 2 additions & 0 deletions pallets/asset-index/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ parameter_types! {
pub WithdrawalPeriod: <Test as system::Config>::BlockNumber = 10;
pub DOTContributionLimit: Balance = 999;
pub TreasuryPalletId: PalletId = PalletId(*b"12345678");
pub StringLimit: u32 = 4;
}

impl pallet_asset_index::Config for Test {
Expand All @@ -139,6 +140,7 @@ impl pallet_asset_index::Config for Test {
type MultiAssetDepository = AssetDepository;
type PriceFeed = MockPriceFeed;
type TreasuryPalletId = TreasuryPalletId;
type StringLimit = StringLimit;
type WithdrawalFee = ();
type WeightInfo = ();
}
Expand Down
67 changes: 67 additions & 0 deletions pallets/asset-index/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,66 @@ fn admin_can_add_asset_twice_and_units_accumulate() {
});
}

#[test]
fn non_admin_cannot_set_metadata() {
new_test_ext(vec![]).execute_with(|| {
assert_noop!(
AssetIndex::set_metadata(
Origin::signed(ASHLEY),
ASSET_A_ID,
b"dot".to_vec(),
b"dot".to_vec(),
8,
),
BadOrigin
);
});
}

#[test]
fn admin_can_set_metadata() {
new_test_ext(vec![]).execute_with(|| {
assert_ok!(AssetIndex::set_metadata(
Origin::signed(ADMIN_ACCOUNT_ID),
ASSET_A_ID,
b"dot".to_vec(),
b"dot".to_vec(),
8,
));
});
}

#[test]
fn admin_can_update_metadata() {
new_test_ext(vec![]).execute_with(|| {
assert_ok!(AssetIndex::set_metadata(
Origin::signed(ADMIN_ACCOUNT_ID),
ASSET_A_ID,
b"dot".to_vec(),
b"dot".to_vec(),
8,
));

assert_eq!(
<pallet::Metadata<Test>>::get(ASSET_A_ID).name,
b"dot".to_vec()
);

assert_ok!(AssetIndex::set_metadata(
Origin::signed(ADMIN_ACCOUNT_ID),
ASSET_A_ID,
b"pint".to_vec(),
b"pint".to_vec(),
8,
));

assert_eq!(
<pallet::Metadata<Test>>::get(ASSET_A_ID).name,
b"pint".to_vec()
);
});
}

#[test]
fn deposit_only_works_for_added_liquid_assets() {
let initial_balances: Vec<(AccountId, Balance)> = vec![(ADMIN_ACCOUNT_ID, 0)];
Expand Down Expand Up @@ -148,6 +208,13 @@ fn deposit_works_with_user_balance() {
fn deposit_fails_for_unknown_assets() {
let initial_balances: Vec<(AccountId, Balance)> = vec![(ADMIN_ACCOUNT_ID, 0)];
new_test_ext(initial_balances).execute_with(|| {
assert_ok!(AssetIndex::add_asset(
Origin::signed(ADMIN_ACCOUNT_ID),
ASSET_A_ID,
100,
AssetAvailability::Liquid(MultiLocation::Null),
5
));
assert_noop!(
AssetIndex::deposit(Origin::signed(ASHLEY), UNKNOWN_ASSET_ID, 1_000),
pallet::Error::<Test>::UnsupportedAsset
Expand Down
5 changes: 2 additions & 3 deletions pallets/asset-index/src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// Copyright 2021 ChainSafe Systems
// SPDX-License-Identifier: LGPL-3.0-only

pub use crate::types::AssetAvailability;
use frame_support::dispatch::DispatchResult;
use frame_support::sp_runtime::traits::AtLeast32BitUnsigned;
pub use crate::types::{AssetAvailability, AssetMetadata};
use frame_support::{dispatch::DispatchResult, sp_runtime::traits::AtLeast32BitUnsigned};
use xcm::v0::MultiLocation;

pub trait AssetRecorder<AssetId, Balance> {
Expand Down
8 changes: 8 additions & 0 deletions pallets/asset-index/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ pub enum AssetAvailability {
Saft,
}

/// Metadata for an asset
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode, RuntimeDebug)]
pub struct AssetMetadata<BoundedString> {
pub name: BoundedString,
pub symbol: BoundedString,
pub decimals: u8,
}

#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug)]
/// A representation of some number of assets that are managed by the index
pub struct IndexAssetData<Balance> {
Expand Down
7 changes: 6 additions & 1 deletion pallets/saft-registry/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ benchmarks! {
// }

report_nav {
assert_ok!(<Pallet<T>>::add_saft(<Origin<T>>::Root.into(), 0.into(), 100_u32.into(), 20_u32.into()));
assert_ok!(<Pallet<T>>::add_saft(
<Origin<T>>::Root.into(),
0.into(),
100_u32.into(),
20_u32.into(),
));
}: _(
<Origin<T>>::Root,
0.into(),
Expand Down
Loading