Lines
89.8 %
Functions
57.5 %
Branches
100 %
// Copyright 2019-2025 PureStake Inc.
// This file is part of Moonbeam.
// Moonbeam is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Moonbeam is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Moonbeam. If not, see <http://www.gnu.org/licenses/>.
use frame_support::traits::{ContainsPair, Get, OriginTrait};
use sp_runtime::traits::TryConvert;
use sp_std::{convert::TryInto, marker::PhantomData};
use xcm::latest::{Asset, AssetId, Fungibility, Junction, Location, NetworkId};
pub trait Reserve {
/// Returns assets reserve location.
fn reserve(asset: &Asset) -> Option<Location>;
}
/// Instructs how to convert a 20 byte accountId into a Location
pub struct AccountIdToLocation<AccountId>(sp_std::marker::PhantomData<AccountId>);
impl<AccountId> sp_runtime::traits::Convert<AccountId, Location> for AccountIdToLocation<AccountId>
where
AccountId: Into<[u8; 20]>,
{
fn convert(account: AccountId) -> Location {
Location {
parents: 0,
interior: [Junction::AccountKey20 {
network: None,
key: account.into(),
}]
.into(),
// Convert a local Origin (i.e., a signed 20 byte account Origin) to a Multilocation
pub struct SignedToAccountId20<Origin, AccountId, Network>(
sp_std::marker::PhantomData<(Origin, AccountId, Network)>,
);
impl<Origin: OriginTrait + Clone, AccountId: Into<[u8; 20]>, Network: Get<NetworkId>>
TryConvert<Origin, Location> for SignedToAccountId20<Origin, AccountId, Network>
Origin::PalletsOrigin: From<frame_system::RawOrigin<AccountId>>
+ TryInto<frame_system::RawOrigin<AccountId>, Error = Origin::PalletsOrigin>,
fn try_convert(o: Origin) -> Result<Location, Origin> {
o.try_with_caller(|caller| match caller.try_into() {
Ok(frame_system::RawOrigin::Signed(who)) => Ok(Junction::AccountKey20 {
key: who.into(),
network: Some(Network::get()),
.into()),
Ok(other) => Err(other.into()),
Err(other) => Err(other),
})
/// A `ContainsPair` implementation. Filters multi native assets whose
/// reserve is same with `origin`.
pub struct MultiNativeAsset<ReserveProvider>(PhantomData<ReserveProvider>);
impl<ReserveProvider> ContainsPair<Asset, Location> for MultiNativeAsset<ReserveProvider>
ReserveProvider: Reserve,
fn contains(asset: &Asset, origin: &Location) -> bool {
if let Some(ref reserve) = ReserveProvider::reserve(asset) {
if reserve == origin {
return true;
false
// Provide reserve in relative path view
// Self tokens are represeneted as Here
pub struct RelativeReserveProvider;
impl Reserve for RelativeReserveProvider {
fn reserve(asset: &Asset) -> Option<Location> {
let AssetId(location) = &asset.id;
if location.parents == 0
&& !matches!(location.first_interior(), Some(Junction::Parachain(_)))
Some(Location::here())
} else {
Some(location.chain_location())
/// This struct offers uses RelativeReserveProvider to output relative views of multilocations
/// However, additionally accepts a Location that aims at representing the chain part
/// (parent: 1, Parachain(paraId)) of the absolute representation of our chain.
/// If a token reserve matches against this absolute view, we return Some(Location::here())
/// This helps users by preventing errors when they try to transfer a token through xtokens
/// to our chain (either inserting the relative or the absolute value).
pub struct AbsoluteAndRelativeReserve<AbsoluteMultiLocation>(PhantomData<AbsoluteMultiLocation>);
impl<AbsoluteMultiLocation> Reserve for AbsoluteAndRelativeReserve<AbsoluteMultiLocation>
AbsoluteMultiLocation: Get<Location>,
RelativeReserveProvider::reserve(asset).map(|relative_reserve| {
if relative_reserve == AbsoluteMultiLocation::get() {
Location::here()
relative_reserve
/// Matches foreign assets from a given origin.
/// Foreign assets are assets bridged from other consensus systems. i.e parents > 1.
pub struct IsBridgedConcreteAssetFrom<Origin>(PhantomData<Origin>);
impl<Origin> ContainsPair<Asset, Location> for IsBridgedConcreteAssetFrom<Origin>
Origin: Get<Location>,
let loc = Origin::get();
&loc == origin
&& matches!(
asset,
Asset {
id: AssetId(Location { parents: 2, .. }),
fun: Fungibility::Fungible(_)
},
)