use super::{
governance, AccountId, AssetId, AssetManager, Balance, Balances, EmergencyParaXcm,
Erc20XcmBridge, MaintenanceMode, MessageQueue, OpenTechCommitteeInstance, ParachainInfo,
ParachainSystem, Perbill, PolkadotXcm, Runtime, RuntimeBlockWeights, RuntimeCall, RuntimeEvent,
RuntimeOrigin, Treasury, XcmpQueue,
};
use super::moonbeam_weights;
use frame_support::{
parameter_types,
traits::{EitherOfDiverse, Everything, Nothing, PalletInfoAccess, TransformOrigin},
};
use moonkit_xcm_primitives::AccountIdAssetIdConversion;
use sp_runtime::{
traits::{Hash as THash, MaybeEquivalence, PostDispatchInfoOf},
DispatchErrorWithPostInfo,
};
use sp_weights::Weight;
use frame_system::{EnsureRoot, RawOrigin};
use sp_core::{ConstU32, H160, H256};
use xcm_builder::{
AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, Case, ConvertedConcreteId, DescribeAllTerminal, DescribeFamily,
EnsureXcmOrigin, FungibleAdapter as XcmCurrencyAdapter, FungiblesAdapter, HashedDescription,
NoChecking, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation,
TakeWeightCredit, WeightInfoBounds, WithComputedOrigin,
};
use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling};
use xcm::latest::prelude::{
AllOf, Asset, AssetFilter, GlobalConsensus, InteriorLocation, Junction, Location, NetworkId,
PalletInstance, Parachain, Wild, WildFungible,
};
use xcm_executor::traits::{CallDispatcher, ConvertLocation, JustTry};
use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use xcm_primitives::{
AbsoluteAndRelativeReserve, AccountIdToCurrencyId, AccountIdToLocation, AsAssetType,
IsBridgedConcreteAssetFrom, MultiNativeAsset, SignedToAccountId20, UtilityAvailableCalls,
UtilityEncodeCall, XcmTransact,
};
use parity_scale_codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_core::Get;
use sp_std::{
convert::{From, Into, TryFrom},
prelude::*,
};
use crate::governance::referenda::{FastGeneralAdminOrRoot, GeneralAdminOrRoot};
parameter_types! {
pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into();
pub UniversalLocation: InteriorLocation =
[GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())].into();
pub SelfReserve: Location = Location {
parents:0,
interior: [
PalletInstance(<Balances as PalletInfoAccess>::index() as u8)
].into()
};
}
pub type LocationToAccountId = (
ParentIsPreset<AccountId>,
SiblingParachainConvertsVia<polkadot_parachain::primitives::Sibling, AccountId>,
AccountKey20Aliases<RelayNetwork, AccountId>,
HashedDescription<AccountId, DescribeFamily<DescribeAllTerminal>>,
);
pub struct LocationToH160;
impl ConvertLocation<H160> for LocationToH160 {
fn convert_location(location: &Location) -> Option<H160> {
<LocationToAccountId as ConvertLocation<AccountId>>::convert_location(location)
.map(Into::into)
}
}
pub type ForeignFungiblesTransactor = FungiblesAdapter<
super::Assets,
(
ConvertedConcreteId<
AssetId,
Balance,
AsAssetType<AssetId, AssetType, AssetManager>,
JustTry,
>,
),
LocationToAccountId,
AccountId,
NoChecking,
(),
>;
pub type LocalAssetTransactor = XcmCurrencyAdapter<
Balances,
xcm_builder::IsConcrete<SelfReserve>,
LocationToAccountId,
AccountId,
(),
>;
pub type AssetTransactors = (
LocalAssetTransactor,
ForeignFungiblesTransactor,
Erc20XcmBridge,
);
pub type XcmOriginToTransactDispatchOrigin = (
SovereignSignedViaLocation<LocationToAccountId, RuntimeOrigin>,
RelayChainAsNative<RelayChainOrigin, RuntimeOrigin>,
SiblingParachainAsNative<cumulus_pallet_xcm::Origin, RuntimeOrigin>,
pallet_xcm::XcmPassthrough<RuntimeOrigin>,
SignedAccountKey20AsNative<RelayNetwork, RuntimeOrigin>,
);
parameter_types! {
pub MaxInstructions: u32 = 100;
}
pub type XcmWeigher = WeightInfoBounds<
moonbeam_xcm_benchmarks::weights::XcmWeight<Runtime, RuntimeCall>,
RuntimeCall,
MaxInstructions,
>;
pub type XcmBarrier = (
TakeWeightCredit,
AllowKnownQueryResponses<PolkadotXcm>,
WithComputedOrigin<
(
AllowTopLevelPaidExecutionFrom<Everything>,
AllowSubscriptionsFrom<Everything>,
),
UniversalLocation,
ConstU32<8>,
>,
);
parameter_types! {
pub XcmFeesAccount: AccountId = Treasury::account_id();
}
pub struct SafeCallFilter;
impl frame_support::traits::Contains<RuntimeCall> for SafeCallFilter {
fn contains(_call: &RuntimeCall) -> bool {
true
}
}
parameter_types! {
pub AssetHubLocation: Location = Location::new(1, [Parachain(1000)]);
pub const RelayLocation: Location = Location::parent();
pub RelayLocationFilter: AssetFilter = Wild(AllOf {
fun: WildFungible,
id: xcm::prelude::AssetId(RelayLocation::get()),
});
pub RelayChainNativeAssetFromAssetHub: (AssetFilter, Location) = (
RelayLocationFilter::get(),
AssetHubLocation::get()
);
pub const MaxAssetsIntoHolding: u32 = xcm_primitives::MAX_ASSETS;
}
type Reserves = (
IsBridgedConcreteAssetFrom<AssetHubLocation>,
Case<RelayChainNativeAssetFromAssetHub>,
MultiNativeAsset<AbsoluteAndRelativeReserve<SelfLocationAbsolute>>,
);
#[cfg(not(feature = "evm-tracing"))]
moonbeam_runtime_common::impl_moonbeam_xcm_call!();
#[cfg(feature = "evm-tracing")]
moonbeam_runtime_common::impl_moonbeam_xcm_call_tracing!();
moonbeam_runtime_common::impl_evm_runner_precompile_or_eth_xcm!();
pub struct XcmExecutorConfig;
impl xcm_executor::Config for XcmExecutorConfig {
type RuntimeCall = RuntimeCall;
type XcmSender = XcmRouter;
type AssetTransactor = AssetTransactors;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = Reserves;
type IsTeleporter = (); type UniversalLocation = UniversalLocation;
type Barrier = XcmBarrier;
type Weigher = XcmWeigher;
type Trader = pallet_xcm_weight_trader::Trader<Runtime>;
type ResponseHandler = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
type AssetTrap = pallet_erc20_xcm_bridge::AssetTrapWrapper<PolkadotXcm, Runtime>;
type AssetClaims = PolkadotXcm;
type CallDispatcher = MoonbeamCall;
type PalletInstancesInfo = crate::AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type AssetLocker = ();
type AssetExchanger = ();
type FeeManager = ();
type MessageExporter = ();
type UniversalAliases = Nothing;
type SafeCallFilter = SafeCallFilter;
type Aliasers = Nothing;
type TransactionalProcessor = xcm_builder::FrameTransactionalProcessor;
type HrmpNewChannelOpenRequestHandler = ();
type HrmpChannelAcceptedHandler = ();
type HrmpChannelClosingHandler = ();
type XcmRecorder = PolkadotXcm;
}
type XcmExecutor = pallet_erc20_xcm_bridge::XcmExecutorWrapper<
XcmExecutorConfig,
xcm_executor::XcmExecutor<XcmExecutorConfig>,
>;
pub type LocalOriginToLocation = SignedToAccountId20<RuntimeOrigin, AccountId, RelayNetwork>;
pub type XcmRouter = (
cumulus_primitives_utility::ParentAsUmp<ParachainSystem, PolkadotXcm, ()>,
XcmpQueue,
);
impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmRouter = XcmRouter;
type ExecuteXcmOrigin = EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmExecuteFilter = Nothing;
type XcmExecutor = XcmExecutor;
type XcmTeleportFilter = Nothing;
type XcmReserveTransferFilter = Everything;
type Weigher = XcmWeigher;
type UniversalLocation = UniversalLocation;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
type Currency = Balances;
type CurrencyMatcher = ();
type TrustedLockers = ();
type SovereignAccountOf = LocationToAccountId;
type MaxLockers = ConstU32<8>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
type WeightInfo = moonbeam_weights::pallet_xcm::WeightInfo<Runtime>;
type AdminOrigin = EnsureRoot<AccountId>;
}
impl cumulus_pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type XcmExecutor = XcmExecutor;
}
impl cumulus_pallet_xcmp_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ChannelInfo = ParachainSystem;
type VersionWrapper = PolkadotXcm;
type XcmpQueue = TransformOrigin<MessageQueue, AggregateMessageOrigin, ParaId, ParaIdToSibling>;
type MaxInboundSuspended = sp_core::ConstU32<1_000>;
type ControllerOrigin = EnsureRoot<AccountId>;
type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
type WeightInfo = moonbeam_weights::cumulus_pallet_xcmp_queue::WeightInfo<Runtime>;
type PriceForSiblingDelivery = polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery<
cumulus_primitives_core::ParaId,
>;
type MaxActiveOutboundChannels = ConstU32<128>;
type MaxPageSize = MessageQueueHeapSize;
}
parameter_types! {
pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
}
parameter_types! {
pub MessageQueueServiceWeight: Weight =
Perbill::from_percent(25) * RuntimeBlockWeights::get().max_block;
pub const MessageQueueMaxStale: u32 = 8;
pub const MessageQueueHeapSize: u32 = 103 * 1024;
}
impl pallet_message_queue::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
#[cfg(feature = "runtime-benchmarks")]
type MessageProcessor = pallet_message_queue::mock_helpers::NoopMessageProcessor<
cumulus_primitives_core::AggregateMessageOrigin,
>;
#[cfg(not(feature = "runtime-benchmarks"))]
type MessageProcessor = pallet_ethereum_xcm::MessageProcessorWrapper<
xcm_builder::ProcessXcmMessage<AggregateMessageOrigin, XcmExecutor, RuntimeCall>,
>;
type Size = u32;
type HeapSize = MessageQueueHeapSize;
type MaxStale = MessageQueueMaxStale;
type ServiceWeight = MessageQueueServiceWeight;
type QueueChangeHandler = NarrowOriginToSibling<XcmpQueue>;
type QueuePausedQuery = EmergencyParaXcm;
type WeightInfo = moonbeam_weights::pallet_message_queue::WeightInfo<Runtime>;
type IdleMaxServiceWeight = MessageQueueServiceWeight;
}
pub type FastAuthorizeUpgradeOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionAtLeast<AccountId, OpenTechCommitteeInstance, 5, 9>,
>;
pub type ResumeXcmOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionAtLeast<AccountId, OpenTechCommitteeInstance, 5, 9>,
>;
impl pallet_emergency_para_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type CheckAssociatedRelayNumber =
cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases;
type QueuePausedQuery = (MaintenanceMode, NarrowOriginToSibling<XcmpQueue>);
type PausedThreshold = ConstU32<300>;
type FastAuthorizeUpgradeOrigin = FastAuthorizeUpgradeOrigin;
type PausedToNormalOrigin = ResumeXcmOrigin;
}
#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
pub enum AssetType {
Xcm(xcm::v3::Location),
}
impl Default for AssetType {
fn default() -> Self {
Self::Xcm(xcm::v3::Location::here())
}
}
impl From<xcm::v3::Location> for AssetType {
fn from(location: xcm::v3::Location) -> Self {
Self::Xcm(location)
}
}
impl TryFrom<Location> for AssetType {
type Error = ();
fn try_from(location: Location) -> Result<Self, Self::Error> {
Ok(Self::Xcm(location.try_into()?))
}
}
impl Into<Option<xcm::v3::Location>> for AssetType {
fn into(self) -> Option<xcm::v3::Location> {
match self {
Self::Xcm(location) => Some(location),
}
}
}
impl Into<Option<Location>> for AssetType {
fn into(self) -> Option<Location> {
match self {
Self::Xcm(location) => {
xcm_builder::WithLatestLocationConverter::convert_back(&location)
}
}
}
}
impl From<AssetType> for AssetId {
fn from(asset: AssetType) -> AssetId {
match asset {
AssetType::Xcm(id) => {
let mut result: [u8; 16] = [0u8; 16];
let hash: H256 = id.using_encoded(<Runtime as frame_system::Config>::Hashing::hash);
result.copy_from_slice(&hash.as_fixed_bytes()[0..16]);
u128::from_le_bytes(result)
}
}
}
}
#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
pub enum CurrencyId {
SelfReserve,
ForeignAsset(AssetId),
Erc20 { contract_address: H160 },
}
impl AccountIdToCurrencyId<AccountId, CurrencyId> for Runtime {
fn account_to_currency_id(account: AccountId) -> Option<CurrencyId> {
Some(match account {
a if a == H160::from_low_u64_be(2050).into() => CurrencyId::SelfReserve,
_ => match Runtime::account_to_asset_id(account) {
Some((_prefix, asset_id)) => CurrencyId::ForeignAsset(asset_id),
None => CurrencyId::Erc20 {
contract_address: account.into(),
},
},
})
}
}
pub struct CurrencyIdToLocation<AssetXConverter>(sp_std::marker::PhantomData<AssetXConverter>);
impl<AssetXConverter> sp_runtime::traits::Convert<CurrencyId, Option<Location>>
for CurrencyIdToLocation<AssetXConverter>
where
AssetXConverter: sp_runtime::traits::MaybeEquivalence<Location, AssetId>,
{
fn convert(currency: CurrencyId) -> Option<Location> {
match currency {
CurrencyId::SelfReserve => {
let multi: Location = SelfReserve::get();
Some(multi)
}
CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset),
CurrencyId::Erc20 { contract_address } => {
let mut location = Erc20XcmBridgePalletLocation::get();
location
.push_interior(Junction::AccountKey20 {
key: contract_address.0,
network: None,
})
.ok();
Some(location)
}
}
}
}
parameter_types! {
pub const BaseXcmWeight: Weight = Weight::from_parts(200_000_000u64, 0);
pub const MaxAssetsForTransfer: usize = 2;
pub SelfLocation: Location = Location::here();
pub SelfLocationAbsolute: Location = Location {
parents:1,
interior: [
Parachain(ParachainInfo::parachain_id().into())
].into()
};
}
parameter_types! {
pub MaxHrmpRelayFee: Asset = (Location::parent(), 1_000_000_000_000u128).into();
}
#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]
pub enum Transactors {
Relay,
}
#[cfg(feature = "runtime-benchmarks")]
impl Default for Transactors {
fn default() -> Self {
Transactors::Relay
}
}
impl TryFrom<u8> for Transactors {
type Error = ();
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
0u8 => Ok(Transactors::Relay),
_ => Err(()),
}
}
}
impl UtilityEncodeCall for Transactors {
fn encode_call(self, call: UtilityAvailableCalls) -> Vec<u8> {
match self {
Transactors::Relay => pallet_xcm_transactor::Pallet::<Runtime>::encode_call(
pallet_xcm_transactor::Pallet(sp_std::marker::PhantomData::<Runtime>),
call,
),
}
}
}
impl XcmTransact for Transactors {
fn destination(self) -> Location {
match self {
Transactors::Relay => Location::parent(),
}
}
}
pub type DerivativeAddressRegistrationOrigin =
EitherOfDiverse<EnsureRoot<AccountId>, governance::custom_origins::GeneralAdmin>;
impl pallet_xcm_transactor::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type Transactor = Transactors;
type DerivativeAddressRegistrationOrigin = DerivativeAddressRegistrationOrigin;
type SovereignAccountDispatcherOrigin = EnsureRoot<AccountId>;
type CurrencyId = CurrencyId;
type AccountIdToLocation = AccountIdToLocation<AccountId>;
type CurrencyIdToLocation = CurrencyIdToLocation<AsAssetType<AssetId, AssetType, AssetManager>>;
type XcmSender = XcmRouter;
type SelfLocation = SelfLocation;
type Weigher = XcmWeigher;
type UniversalLocation = UniversalLocation;
type BaseXcmWeight = BaseXcmWeight;
type AssetTransactor = AssetTransactors;
type ReserveProvider = AbsoluteAndRelativeReserve<SelfLocationAbsolute>;
type WeightInfo = moonbeam_weights::pallet_xcm_transactor::WeightInfo<Runtime>;
type HrmpManipulatorOrigin = GeneralAdminOrRoot;
type HrmpOpenOrigin = FastGeneralAdminOrRoot;
type MaxHrmpFee = xcm_builder::Case<MaxHrmpRelayFee>;
}
parameter_types! {
pub Erc20XcmBridgePalletLocation: Location = Location {
parents:0,
interior: [
PalletInstance(<Erc20XcmBridge as PalletInfoAccess>::index() as u8)
].into()
};
pub Erc20XcmBridgeTransferGasLimit: u64 = 800_000;
}
impl pallet_erc20_xcm_bridge::Config for Runtime {
type AccountIdConverter = LocationToH160;
type Erc20MultilocationPrefix = Erc20XcmBridgePalletLocation;
type Erc20TransferGasLimit = Erc20XcmBridgeTransferGasLimit;
type EvmRunner = EvmRunnerPrecompileOrEthXcm<MoonbeamCall, Self>;
}
pub struct AccountIdToH160;
impl sp_runtime::traits::Convert<AccountId, H160> for AccountIdToH160 {
fn convert(account_id: AccountId) -> H160 {
account_id.into()
}
}
pub struct EvmForeignAssetIdFilter;
impl frame_support::traits::Contains<AssetId> for EvmForeignAssetIdFilter {
fn contains(asset_id: &AssetId) -> bool {
use xcm_primitives::AssetTypeGetter as _;
AssetManager::get_asset_type(*asset_id).is_none()
}
}
pub type ForeignAssetManagerOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
EitherOfDiverse<
pallet_collective::EnsureProportionMoreThan<AccountId, OpenTechCommitteeInstance, 5, 9>,
governance::custom_origins::FastGeneralAdmin,
>,
>;
impl pallet_moonbeam_foreign_assets::Config for Runtime {
type AccountIdToH160 = AccountIdToH160;
type AssetIdFilter = EvmForeignAssetIdFilter;
type EvmRunner = EvmRunnerPrecompileOrEthXcm<MoonbeamCall, Self>;
type ForeignAssetCreatorOrigin = ForeignAssetManagerOrigin;
type ForeignAssetFreezerOrigin = ForeignAssetManagerOrigin;
type ForeignAssetModifierOrigin = ForeignAssetManagerOrigin;
type ForeignAssetUnfreezerOrigin = ForeignAssetManagerOrigin;
type OnForeignAssetCreated = ();
type MaxForeignAssets = ConstU32<256>;
type RuntimeEvent = RuntimeEvent;
type WeightInfo = moonbeam_weights::pallet_moonbeam_foreign_assets::WeightInfo<Runtime>;
type XcmLocationToH160 = LocationToH160;
}
pub struct AssetFeesFilter;
impl frame_support::traits::Contains<Location> for AssetFeesFilter {
fn contains(location: &Location) -> bool {
location.parent_count() > 0
&& location.first_interior() != Erc20XcmBridgePalletLocation::get().first_interior()
}
}
pub type AddSupportedAssetOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
EitherOfDiverse<
pallet_collective::EnsureProportionMoreThan<AccountId, OpenTechCommitteeInstance, 5, 9>,
governance::custom_origins::GeneralAdmin,
>,
>;
pub type EditSupportedAssetOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
EitherOfDiverse<
pallet_collective::EnsureProportionMoreThan<AccountId, OpenTechCommitteeInstance, 5, 9>,
governance::custom_origins::FastGeneralAdmin,
>,
>;
pub type RemoveSupportedAssetOrigin = EitherOfDiverse<
EnsureRoot<AccountId>,
pallet_collective::EnsureProportionMoreThan<AccountId, OpenTechCommitteeInstance, 5, 9>,
>;
impl pallet_xcm_weight_trader::Config for Runtime {
type AccountIdToLocation = AccountIdToLocation<AccountId>;
type AddSupportedAssetOrigin = AddSupportedAssetOrigin;
type AssetLocationFilter = AssetFeesFilter;
type AssetTransactor = AssetTransactors;
type Balance = Balance;
type EditSupportedAssetOrigin = EditSupportedAssetOrigin;
type NativeLocation = SelfReserve;
type PauseSupportedAssetOrigin = EditSupportedAssetOrigin;
type RemoveSupportedAssetOrigin = RemoveSupportedAssetOrigin;
type RuntimeEvent = RuntimeEvent;
type ResumeSupportedAssetOrigin = RemoveSupportedAssetOrigin;
type WeightInfo = moonbeam_weights::pallet_xcm_weight_trader::WeightInfo<Runtime>;
type WeightToFee = <Runtime as pallet_transaction_payment::Config>::WeightToFee;
type XcmFeesAccount = XcmFeesAccount;
#[cfg(feature = "runtime-benchmarks")]
type NotFilteredLocation = RelayLocation;
}
#[cfg(feature = "runtime-benchmarks")]
mod testing {
use super::*;
use xcm_builder::WithLatestLocationConverter;
impl From<Location> for CurrencyId {
fn from(location: Location) -> CurrencyId {
use xcm_primitives::AssetTypeGetter;
let asset_id = if let Some(asset_id) =
AsAssetType::<AssetId, AssetType, AssetManager>::convert_location(&location)
{
asset_id
} else {
let asset_type = AssetType::Xcm(
WithLatestLocationConverter::convert(&location).expect("convert to v3"),
);
let asset_id: AssetId = asset_type.clone().into();
AssetManager::set_asset_type_asset_id(asset_type, asset_id);
asset_id
};
CurrencyId::ForeignAsset(asset_id)
}
}
}