Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
e170f4c
Add statemine like runtime for xcm tests
girazoki Jan 10, 2022
ef6ae21
Be able to receive both prefixes from statemine, while add an extrins…
girazoki Jan 10, 2022
32cdb42
Add statemine/statemint tests
girazoki Jan 10, 2022
a15613b
add statemine runtime test
girazoki Jan 10, 2022
9d44c8f
refactor
girazoki Jan 10, 2022
bf39e2e
More rust and typescript tests
girazoki Jan 11, 2022
aeef2b3
NPX
girazoki Jan 11, 2022
306bb0e
Document tests
girazoki Jan 11, 2022
6bc863c
editorconfig
girazoki Jan 11, 2022
01b0618
Merge remote-tracking branch 'upstream/master' into girazoki-avoid-st…
girazoki Jan 11, 2022
bdeaebf
Update benchmark
girazoki Jan 11, 2022
14c2599
Update weights
girazoki Jan 11, 2022
8b4dcbb
Update message
girazoki Jan 11, 2022
8aa9b70
Merge remote-tracking branch 'upstream/master' into girazoki-avoid-st…
girazoki Jan 12, 2022
c7112a7
Update estamite for assets transfer
girazoki Jan 13, 2022
1895e6c
Adapt test and package-lock to run all tests correctly
girazoki Jan 13, 2022
723dd97
Prettier
girazoki Jan 13, 2022
1b4e8e0
Merge remote-tracking branch 'upstream/master' into girazoki-avoid-st…
girazoki Jan 17, 2022
5ec2c1f
Update test with AssetDoesNotExist
girazoki Jan 17, 2022
2667fef
Update to 3 in alphanet
girazoki Jan 17, 2022
982b6ec
New storage item with mapping from assetType -> AssetId
girazoki Jan 18, 2022
fd2e0dc
Migration referencing units per second by assetType and not by assetId
girazoki Jan 18, 2022
34344aa
Add migrations
girazoki Jan 18, 2022
82f30eb
Add test for new migration
girazoki Jan 18, 2022
67b0aae
adapt traits to new storage item in pallet-asset-amanger
girazoki Jan 18, 2022
13852c4
Remove AsserId bound in FirstAssetTrader
girazoki Jan 18, 2022
5c82ee9
Update all tests to new design
girazoki Jan 18, 2022
c0fc100
Test third migration: migrate prefixes from previous statemine to new…
girazoki Jan 18, 2022
d2694d0
Integration tests change
girazoki Jan 18, 2022
e0cb77f
Update moonriver integration tests
girazoki Jan 18, 2022
e31d450
Merge remote-tracking branch 'upstream/master' into girazoki-avoid-st…
girazoki Jan 19, 2022
cdc8f42
Adapt moonbeam to migrations and statemint
girazoki Jan 19, 2022
42399ad
Make all migrations be independent from each other, and thus they can…
girazoki Jan 19, 2022
fff3b82
Define how we are going to pass statemine info to migration
girazoki Jan 19, 2022
94dbdfa
Update names of migrations
girazoki Jan 19, 2022
eccdb27
Include migration to all runtimes
girazoki Jan 19, 2022
555d0bf
Adapt tests to changes in set assets units per second plus statemint …
girazoki Jan 19, 2022
b23dcf7
Toml sort
girazoki Jan 19, 2022
437d089
Add statemine like to moonbeam
girazoki Jan 19, 2022
f7ef5c0
Prettier
girazoki Jan 19, 2022
a8e899c
EditorConfig
girazoki Jan 19, 2022
ee85d85
Fmt
girazoki Jan 19, 2022
c025e17
Editorconfig
girazoki Jan 19, 2022
c7cdf07
EditorCOnfig too
girazoki Jan 19, 2022
988eb26
Update benchmarks too
girazoki Jan 19, 2022
c7650bd
Editorconfig third try
girazoki Jan 19, 2022
90a2026
Update weights
girazoki Jan 19, 2022
8392853
Remove unused variable
girazoki Jan 19, 2022
9a97266
Remove silly comment
girazoki Jan 19, 2022
239964b
Tests for regular users cannot call root extrinsics
girazoki Jan 19, 2022
4b8faef
Add PR suggestions
girazoki Jan 20, 2022
08452c5
Documentation about migrations
girazoki Jan 20, 2022
5086d17
Merge remote-tracking branch 'upstream/master' into girazoki-avoid-st…
girazoki Jan 20, 2022
fc91d87
Comments in storage items
girazoki Jan 20, 2022
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
2 changes: 2 additions & 0 deletions Cargo.lock

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

890 changes: 153 additions & 737 deletions moonbeam-types-bundle/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pallets/asset-manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2018"
version = "0.1.0"

[dependencies]
log = { version = "0.4", default-features = false }
serde = { version = "1.0.124", optional = true }

# Moonbeam
Expand Down Expand Up @@ -47,3 +48,4 @@ std = [
runtime-benchmarks = [
"frame-benchmarking",
]
try-runtime = [ "frame-support/try-runtime" ]
17 changes: 15 additions & 2 deletions pallets/asset-manager/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,22 @@ benchmarks! {
let asset_id: T::AssetId = asset_type.clone().into();
Pallet::<T>::register_asset(RawOrigin::Root.into(), asset_type.clone(), metadata, amount, true)?;

}: _(RawOrigin::Root, asset_id, 1)
}: _(RawOrigin::Root, asset_type.clone(), 1)
verify {
assert_eq!(Pallet::<T>::asset_id_units_per_second(asset_id), Some(1));
assert_eq!(Pallet::<T>::asset_type_units_per_second(asset_type), Some(1));
}

change_existing_asset_type {
// does not really matter what we register
let asset_type = T::AssetType::default();
let metadata = T::AssetRegistrarMetadata::default();
let amount = 1u32.into();
let asset_id: T::AssetId = asset_type.clone().into();
Pallet::<T>::register_asset(RawOrigin::Root.into(), asset_type.clone(), metadata, amount, true)?;

}: _(RawOrigin::Root, asset_id, asset_type.clone())
verify {
assert_eq!(Pallet::<T>::asset_id_type(asset_id), Some(asset_type));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it's (1) changing from one asset type to the same asset type, and (2) expecting the implementation of change_existing_asset_type() to not short-circuit this case.

This works for now because that is actually how change_existing_asset_type() is implemented, but it's probably more future-proof to write this test so that it actually changes the type (that way a future "optimization" or similar won't cause the benchmark to become ineffective).

Copy link
Copy Markdown
Collaborator Author

@girazoki girazoki Jan 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to write this benchmark like you described, but I have two associated types (assetId, assetType) that I need to generate and in order to be generic (over the mock runtime and over the proper runtime where this is included) I can only generate the default one. Still I think the benchmarking is correct

Copy link
Copy Markdown
Collaborator Author

@girazoki girazoki Jan 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option is to require that AssetType: From<MultiLocation> in the config, and in that case I can generate several. But to be honest the pallet is so simple that I did not even bother requiring this. Let me know if this is something we think we should add

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I don't think my concern is worth a lot of effort...

}
}

Expand Down
79 changes: 62 additions & 17 deletions pallets/asset-manager/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,24 @@
//! The main goal of this pallet is to allow moonbeam to register XCM assets
//! The assumption is we work with AssetTypes, which can then be comperted to AssetIds
//!
//! This pallet has two storage items: AssetIdType, which holds a mapping from AssetId->AssetType
//! AssetIdUnitsPerSecond: an AssetId->u128 mapping that holds how much each AssetId should be
//! charged per unit of second, in the case such an Asset is received as a XCM asset.
//! This pallet has three storage items: AssetIdType, which holds a mapping from AssetId->AssetType
//! AssetTypeUnitsPerSecond: an AssetType->u128 mapping that holds how much each AssetType should be
//! charged per unit of second, in the case such an Asset is received as a XCM asset. Finally,
//! AssetTypeId holds a mapping from AssetType -> AssetId.
//!
//! This pallet has two extrinsics: register_asset, which registers an Asset in this pallet and
//! This pallet has three extrinsics: register_asset, which registers an Asset in this pallet and
//! creates the asset as dictated by the AssetRegistrar trait. set_asset_units_per_second: which
//! sets the unit per second that should be charged for a particular asset.
//! change_existing_asset_type: which allows to update the correspondence between AssetId and
//! AssetType

#![cfg_attr(not(feature = "std"), no_std)]

use frame_support::pallet;
pub use pallet::*;
#[cfg(any(test, feature = "runtime-benchmarks"))]
mod benchmarks;
pub mod migrations;
#[cfg(test)]
pub mod mock;
#[cfg(test)]
Expand Down Expand Up @@ -73,11 +77,15 @@ pub mod pallet {
fn get_asset_type(asset_id: T::AssetId) -> Option<T::AssetType> {
AssetIdType::<T>::get(asset_id)
}

fn get_asset_id(asset_type: T::AssetType) -> Option<T::AssetId> {
AssetTypeId::<T>::get(asset_type)
}
Comment on lines +81 to +83
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implies a 1:1 mapping between an AssetId and an AssetType (instead of a many-to-one). I previously thought it made sense to support multiple AssetIds mapping to a single AssetType, is this categorically wrong? Or is it not the AssetManagers responsibility to handle this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is wrong. We need the asset-manager to provide one specific multiLocation when a user says: "I want to transact asset X".

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assetType exists mainly to be able to reference distinct type of tokens in the future. Right now its an enum containing XCM(MultiLocation) but in the future we might want to distinguish between, e.g., fungible and non-fungible tokens, which should probably go into different pallets. But since our approach is to retrieve the Id through a hash, there is low risk of collision

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that's right. This constraint is about communicating back to another chain, right?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

}

impl<T: Config> xcm_primitives::UnitsToWeightRatio<T::AssetId> for Pallet<T> {
fn get_units_per_second(asset_id: T::AssetId) -> Option<u128> {
AssetIdUnitsPerSecond::<T>::get(asset_id)
impl<T: Config> xcm_primitives::UnitsToWeightRatio<T::AssetType> for Pallet<T> {
fn get_units_per_second(asset_type: T::AssetType) -> Option<u128> {
AssetTypeUnitsPerSecond::<T>::get(asset_type)
}
}

Expand Down Expand Up @@ -118,19 +126,32 @@ pub mod pallet {
#[pallet::generate_deposit(pub(crate) fn deposit_event)]
pub enum Event<T: Config> {
AssetRegistered(T::AssetId, T::AssetType, T::AssetRegistrarMetadata),
UnitsPerSecondChanged(T::AssetId, u128),
UnitsPerSecondChanged(T::AssetType, u128),
AssetTypeChanged(T::AssetId, T::AssetType),
}

/// Stores the asset TYPE
/// Mapping from an asset id to asset type.
/// This is mostly used when receiving transaction specifying an asset directly,
/// like transferring an asset from this chain to another.
#[pallet::storage]
#[pallet::getter(fn asset_id_type)]
pub type AssetIdType<T: Config> = StorageMap<_, Blake2_128Concat, T::AssetId, T::AssetType>;

// Stores the units per second for local execution.
// Not all assets might contain units per second, hence the different storage
/// Reverse mapping of AssetIdType. Mapping from an asset type to an asset id.
/// This is mostly used when receiving a multilocation XCM message to retrieve
/// the corresponding asset in which tokens should me minted.
#[pallet::storage]
#[pallet::getter(fn asset_id_units_per_second)]
pub type AssetIdUnitsPerSecond<T: Config> = StorageMap<_, Blake2_128Concat, T::AssetId, u128>;
#[pallet::getter(fn asset_type_id)]
pub type AssetTypeId<T: Config> = StorageMap<_, Blake2_128Concat, T::AssetType, T::AssetId>;

/// Stores the units per second for local execution for a AssetType.
/// This is used to know how to charge for XCM execution in a particular
/// asset
/// Not all assets might contain units per second, hence the different storage
#[pallet::storage]
#[pallet::getter(fn asset_type_units_per_second)]
pub type AssetTypeUnitsPerSecond<T: Config> =
StorageMap<_, Blake2_128Concat, T::AssetType, u128>;

#[pallet::call]
impl<T: Config> Pallet<T> {
Expand All @@ -154,6 +175,7 @@ pub mod pallet {
.map_err(|_| Error::<T>::ErrorCreatingAsset)?;

AssetIdType::<T>::insert(&asset_id, &asset);
AssetTypeId::<T>::insert(&asset, &asset_id);

Self::deposit_event(Event::AssetRegistered(asset_id, asset, metadata));
Ok(())
Expand All @@ -163,19 +185,42 @@ pub mod pallet {
#[pallet::weight(T::WeightInfo::set_asset_units_per_second())]
pub fn set_asset_units_per_second(
origin: OriginFor<T>,
asset_id: T::AssetId,
asset_type: T::AssetType,
units_per_second: u128,
) -> DispatchResult {
T::AssetModifierOrigin::ensure_origin(origin)?;

ensure!(
AssetIdType::<T>::get(&asset_id).is_some(),
AssetTypeId::<T>::get(&asset_type).is_some(),
Error::<T>::AssetDoesNotExist
);

AssetIdUnitsPerSecond::<T>::insert(&asset_id, &units_per_second);
AssetTypeUnitsPerSecond::<T>::insert(&asset_type, &units_per_second);

Self::deposit_event(Event::UnitsPerSecondChanged(asset_type, units_per_second));
Ok(())
}

/// Change the xcm type mapping for a given assetId
#[pallet::weight(T::WeightInfo::set_asset_units_per_second())]
pub fn change_existing_asset_type(
origin: OriginFor<T>,
asset_id: T::AssetId,
new_asset_type: T::AssetType,
) -> DispatchResult {
T::AssetModifierOrigin::ensure_origin(origin)?;

let previous_asset_type =
AssetIdType::<T>::get(&asset_id).ok_or(Error::<T>::AssetDoesNotExist)?;

// Insert new asset type info
AssetIdType::<T>::insert(&asset_id, &new_asset_type);
AssetTypeId::<T>::insert(&new_asset_type, &asset_id);

// Remove previous asset type info
AssetTypeId::<T>::remove(&previous_asset_type);

Self::deposit_event(Event::UnitsPerSecondChanged(asset_id, units_per_second));
Self::deposit_event(Event::AssetTypeChanged(asset_id, new_asset_type));
Ok(())
}
}
Expand Down
Loading