Statemint Reserve Asset Transfer (#552)

* add AssetId type alias in statemint-common

* add FungiblesAdapter to allow for asset transactions via XCM

* use custom Polkadot

* fix FungiblesAdapter usage and add CheckingAccount

* update deps

* remove polkadot overrides

* update deps

* pull NonZeroIssuance struct into common + add FungiblesTransactor to Statemine and Westmint

* remove unnecessary tuple wrapping + adjust asset transactor comments

* accept statemint as reserve in rococo test parachain

* adjust parachain config (add Statemint as reserve)

* add test and docs for AssetsFrom

* cargo fmt

Co-authored-by: Ricardo Rius <ricardo@parity.io>
Co-authored-by: Shawn Tabrizi <shawntabrizi@gmail.com>
This commit is contained in:
Alexander Popiak
2021-10-05 11:35:03 +02:00
committed by GitHub
parent bd6b147235
commit ca77ce153f
9 changed files with 237 additions and 51 deletions
@@ -16,7 +16,11 @@
//! Auxillary struct/enums for parachain runtimes.
//! Taken from polkadot/runtime/common (at a21cd64) and adapted for parachains.
use frame_support::traits::{Currency, Imbalance, OnUnbalanced};
use frame_support::traits::{fungibles, Contains, Currency, Get, Imbalance, OnUnbalanced};
use sp_runtime::traits::Zero;
use sp_std::marker::PhantomData;
use xcm::latest::{AssetId, Fungibility::Fungible, MultiAsset, MultiLocation};
use xcm_executor::traits::FilterAssetLocation;
pub type NegativeImbalance<T> = <pallet_balances::Pallet<T> as Currency<
<T as frame_system::Config>::AccountId,
@@ -42,6 +46,7 @@ where
}
}
/// Merge the fees into one item and pass them on to the staking pot.
pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<NegativeImbalance<R>> for DealWithFees<R>
where
@@ -60,6 +65,29 @@ where
}
}
/// Allow checking in assets that have issuance > 0.
pub struct NonZeroIssuance<AccountId, Assets>(PhantomData<(AccountId, Assets)>);
impl<AccountId, Assets> Contains<<Assets as fungibles::Inspect<AccountId>>::AssetId>
for NonZeroIssuance<AccountId, Assets>
where
Assets: fungibles::Inspect<AccountId>,
{
fn contains(id: &<Assets as fungibles::Inspect<AccountId>>::AssetId) -> bool {
!Assets::total_issuance(*id).is_zero()
}
}
/// Asset filter that allows all assets from a certain location.
pub struct AssetsFrom<T>(PhantomData<T>);
impl<T: Get<MultiLocation>> FilterAssetLocation for AssetsFrom<T> {
fn filter_asset_location(asset: &MultiAsset, origin: &MultiLocation) -> bool {
let loc = T::get();
&loc == origin &&
matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) }
if asset_loc.match_and_split(&loc).is_some())
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -77,6 +105,7 @@ mod tests {
traits::{BlakeTwo256, IdentityLookup},
Perbill,
};
use xcm::prelude::*;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
@@ -207,4 +236,24 @@ mod tests {
assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 30);
});
}
#[test]
fn assets_from_filters_correctly() {
parameter_types! {
pub SomeSiblingParachain: MultiLocation = MultiLocation::new(1, X1(Parachain(1234)));
}
let asset_location = SomeSiblingParachain::get()
.clone()
.pushed_with_interior(GeneralIndex(42))
.expect("multilocation will only have 2 junctions; qed");
let asset = MultiAsset { id: Concrete(asset_location), fun: 1_000_000.into() };
assert!(
AssetsFrom::<SomeSiblingParachain>::filter_asset_location(
&asset,
&SomeSiblingParachain::get()
),
"AssetsFrom should allow assets from any of its interior locations"
);
}
}
@@ -51,6 +51,9 @@ mod types {
// Aura consensus authority.
pub type AuraId = sp_consensus_aura::sr25519::AuthorityId;
// Id used for identifying assets.
pub type AssetId = u32;
}
/// Common constants of parachains.