diff --git a/Cargo.lock b/Cargo.lock index 078271880..dd692ac80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10370,6 +10370,7 @@ dependencies = [ name = "runtime-common" version = "0.1.0" dependencies = [ + "cumulus-primitives-core", "dia-oracle", "frame-benchmarking", "frame-support", @@ -10403,6 +10404,7 @@ dependencies = [ "frame-support", "frame-system", "kusama-runtime", + "orml-asset-registry", "orml-tokens 0.4.1-dev (git+https://github.com/open-web3-stack/open-runtime-module-library.git?branch=polkadot-v0.9.42)", "orml-traits", "orml-xcm", diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 3761542df..5745b41cb 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -539,6 +539,7 @@ fn foucoco_genesis( .iter() .flat_map(|k| vec![(k.0.clone(), XCM(0), u128::pow(10, 18))]) .collect(); + let stakers: Vec<_> = invulnerables .iter() diff --git a/node/src/constants/foucoco.rs b/node/src/constants/foucoco.rs index e349b20ac..7ff9041fc 100644 --- a/node/src/constants/foucoco.rs +++ b/node/src/constants/foucoco.rs @@ -10,6 +10,7 @@ pub const COLLATOR_ADDITIONAL: Balance = 10 * UNIT; pub const OFF_CHAIN_WORKER_ADDRESS: &str = "6m69vWMouLarYCbJGJisVaDDpfNGETkD5hsDWf2T7osW4Cn1"; + pub const TOKEN_DECIMALS: u32 = 12; pub const INITIAL_SUDO_SIGNATORIES: [&str; 5] = [ diff --git a/runtime/amplitude/src/xcm_config.rs b/runtime/amplitude/src/xcm_config.rs index 7301dbdfd..34634f112 100644 --- a/runtime/amplitude/src/xcm_config.rs +++ b/runtime/amplitude/src/xcm_config.rs @@ -1,12 +1,10 @@ use core::marker::PhantomData; use frame_support::{ - log, match_types, - pallet_prelude::DispatchError, - parameter_types, - traits::{tokens::fungibles, ContainsPair, Everything, Nothing, ProcessMessageError}, - weights::{Weight, WeightToFee as WeightToFeeTrait}, + log, match_types, parameter_types, + traits::{ContainsPair, Everything, Nothing, ProcessMessageError}, }; +use orml_asset_registry::{AssetRegistryTrader, FixedRateAssetRegistryTrader}; use orml_traits::{ location::{RelativeReserveProvider, Reserve}, parameter_type_with_key, @@ -18,35 +16,22 @@ use sp_runtime::traits::Convert; use xcm::latest::{prelude::*, Weight as XCMWeight}; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, - FixedWeightBounds, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, -}; -use xcm_executor::{ - traits::{JustTry, ShouldExecute}, - XcmExecutor, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, }; +use xcm_executor::{traits::ShouldExecute, XcmExecutor}; -use runtime_common::{parachains::kusama::asset_hub, RelativeValue}; +use runtime_common::{asset_registry::{FixedConversionRateProvider}, CurrencyIdConvert}; -use cumulus_primitives_utility::{ - ChargeWeightInFungibles, TakeFirstAssetTrader, XcmFeesTo32ByteAccount, -}; -use sp_runtime::traits::Zero; +use cumulus_primitives_utility::XcmFeesTo32ByteAccount; -use crate::{ - assets::{ - native_locations::{native_location_external_pov, native_location_local_pov}, - xcm_assets, - }, - ConstU32, -}; +use crate::ConstU32; use super::{ - AccountId, AmplitudeTreasuryAccount, Balance, Balances, Currencies, CurrencyId, ParachainInfo, - ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, - WeightToFee, XcmpQueue, + AccountId, AmplitudeTreasuryAccount, AssetRegistry, Balance, Balances, Currencies, CurrencyId, + ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + XcmpQueue, }; use frame_system::EnsureRoot; @@ -72,77 +57,6 @@ pub type LocationToAccountId = ( AccountId32Aliases, ); -/// CurrencyIdConvert -/// This type implements conversions from our `CurrencyId` type into `MultiLocation` and vice-versa. -/// A currency locally is identified with a `CurrencyId` variant but in the network it is identified -/// in the form of a `MultiLocation`, in this case a pCfg (Para-Id, Currency-Id). -pub struct CurrencyIdConvert; - -impl Convert> for CurrencyIdConvert { - fn convert(id: CurrencyId) -> Option { - match id { - CurrencyId::XCM(index) => match index { - xcm_assets::RELAY_KSM => Some(MultiLocation::parent()), - xcm_assets::ASSETHUB_USDT => Some(asset_hub::USDT_location()), - _ => None, - }, - CurrencyId::Native => Some(native_location_external_pov()), - _ => None, - } - } -} - -impl Convert> for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Option { - match location { - loc if loc == MultiLocation::parent() => Some(xcm_assets::RELAY_KSM_id()), - loc if loc == asset_hub::USDT_location() => Some(xcm_assets::ASSETHUB_USDT_id()), - // Our native currency location without re-anchoring - loc if loc == native_location_external_pov() => Some(CurrencyId::Native), - // Our native currency location with re-anchoring - // The XCM pallet will try to re-anchor the location before it reaches here - loc if loc == native_location_local_pov() => Some(CurrencyId::Native), - _ => None, - } - } -} - -impl Convert> for CurrencyIdConvert { - fn convert(a: MultiAsset) -> Option { - if let MultiAsset { id: AssetId::Concrete(id), fun: _ } = a { - Self::convert(id) - } else { - None - } - } -} - -type RelativeValueOf = RelativeValue; - -pub struct RelayRelativeValue; -impl RelayRelativeValue { - fn get_relative_value(id: CurrencyId) -> Option { - match id { - CurrencyId::XCM(index) => match index { - xcm_assets::RELAY_KSM => Some(RelativeValueOf { num: 100, denominator: 1 }), - xcm_assets::ASSETHUB_USDT => Some(RelativeValueOf { num: 20, denominator: 4 }), - _ => None, - }, - CurrencyId::Native => Some(RelativeValueOf { num: 1, denominator: 1 }), - _ => Some(RelativeValueOf { num: 1, denominator: 1 }), - } - } -} - -/// Convert an incoming `MultiLocation` into a `CurrencyId` if possible. -/// Here we need to know the canonical representation of all the tokens we handle in order to -/// correctly convert their `MultiLocation` representation into our internal `CurrencyId` type. -impl xcm_executor::traits::Convert for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Result { - >>::convert(location) - .ok_or(location) - } -} /// A `FilterAssetLocation` implementation. Filters multi native assets whose /// reserve is same with `origin`. @@ -166,11 +80,11 @@ pub type LocalAssetTransactor = MultiCurrencyAdapter< // Use this fungibles implementation Currencies, (), // We don't handle unknown assets. - IsNativeConcrete, + IsNativeConcrete>, AccountId, LocationToAccountId, CurrencyId, - CurrencyIdConvert, + CurrencyIdConvert, DepositToAlternative, >; @@ -199,18 +113,11 @@ parameter_types! { // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. pub UnitWeightCost: XCMWeight = XCMWeight::from_parts(1_000_000_000,0); pub const MaxInstructions: u32 = 100; - pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::parachain_id().into()))); + pub SelfLocation: MultiLocation = MultiLocation::here(); pub const BaseXcmWeight: XCMWeight = XCMWeight::from_parts(150_000_000,0); pub const MaxAssetsForTransfer: usize = 2; } -match_types! { - pub type ParentOrParentsExecutivePlurality: impl Contains = { - MultiLocation { parents: 1, interior: Here } | - MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } - }; -} - //TODO: move DenyThenTry to polkadot's xcm module. /// Deny executing the xcm message if it matches any of the Deny filter regardless of anything else. /// If it passes the Deny, and matches one of the Allow cases then it is let through. @@ -292,112 +199,10 @@ pub type Barrier = ( AllowSubscriptionsFrom, ); -pub struct ChargeWeightInFungiblesImplementation; -impl ChargeWeightInFungibles for ChargeWeightInFungiblesImplementation { - fn charge_weight_in_fungibles( - asset_id: CurrencyId, - weight: Weight, - ) -> Result { - let amount = ::weight_to_fee(&weight); - - if let Some(relative_value) = RelayRelativeValue::get_relative_value(asset_id) { - let adjusted_amount = - RelativeValue::::divide_by_relative_value(amount, relative_value); - log::info!("amount to be charged: {:?} in asset: {:?}", adjusted_amount, asset_id); - return Ok(adjusted_amount) - } else { - log::info!("amount to be charged: {:?} in asset: {:?}", amount, asset_id); - return Ok(amount) - } - } -} - -// Workarround for TakeFirstAssetTrader -use frame_support::traits::tokens::{ - DepositConsequence, Fortitude, Preservation, Provenance, WithdrawConsequence, -}; - -pub struct ConcreteAssets; -impl fungibles::Mutate for ConcreteAssets {} -impl fungibles::Balanced for ConcreteAssets { - type OnDropCredit = fungibles::DecreaseIssuance; - type OnDropDebt = fungibles::IncreaseIssuance; -} -// We only use minimum_balance of these implementations -impl fungibles::Inspect for ConcreteAssets { - type AssetId = >::AssetId; - type Balance = >::Balance; - - fn minimum_balance(id: Self::AssetId) -> Self::Balance { - Tokens::minimum_balance(id) - } - - fn total_issuance(asset_id: Self::AssetId) -> Self::Balance { - Tokens::total_issuance(asset_id) - } - - fn balance(asset_id: Self::AssetId, account_id: &AccountId) -> Self::Balance { - Tokens::balance(asset_id, account_id) - } - - fn total_balance(asset_id: Self::AssetId, account_id: &AccountId) -> Self::Balance { - Tokens::balance(asset_id, account_id) - } - - fn reducible_balance( - _: Self::AssetId, - _: &AccountId, - _: Preservation, - _: Fortitude, - ) -> Self::Balance { - Self::Balance::zero() - } - - fn can_deposit( - _: Self::AssetId, - _: &AccountId, - _: Self::Balance, - _: Provenance, - ) -> DepositConsequence { - DepositConsequence::UnknownAsset - } - - fn can_withdraw( - _: Self::AssetId, - _: &AccountId, - _: Self::Balance, - ) -> WithdrawConsequence { - WithdrawConsequence::UnknownAsset - } - - fn asset_exists(_: Self::AssetId) -> bool { - false - } -} - -// Not used -impl fungibles::Unbalanced for ConcreteAssets { - fn handle_dust(_: fungibles::Dust) {} - fn write_balance( - _: Self::AssetId, - _: &AccountId, - _: Self::Balance, - ) -> Result, DispatchError> { - core::prelude::v1::Err(DispatchError::CannotLookup) - } - - fn set_total_issuance(_: Self::AssetId, _: Self::Balance) {} -} - -pub type Traders = ( - TakeFirstAssetTrader< - AccountId, - ChargeWeightInFungiblesImplementation, - ConvertedConcreteId, - ConcreteAssets, - XcmFeesTo32ByteAccount, - >, -); +pub type Traders = AssetRegistryTrader< + FixedRateAssetRegistryTrader>, + XcmFeesTo32ByteAccount, +>; pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { @@ -485,7 +290,7 @@ impl orml_xtokens::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; type XcmExecutor = XcmExecutor; diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index db9deed3f..27535c158 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -22,6 +22,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", default-features sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus.git", default-features = false, branch = "polkadot-v0.9.42" } xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } @@ -58,6 +59,7 @@ std = [ "orml-xcm-support/std", "zenlink-protocol/std", "spacewalk-primitives/std", + "cumulus-primitives-core/std", ] runtime-benchmarks = [ diff --git a/runtime/common/src/asset_registry.rs b/runtime/common/src/asset_registry.rs index 7f61f7efd..f1e9caa79 100644 --- a/runtime/common/src/asset_registry.rs +++ b/runtime/common/src/asset_registry.rs @@ -1,13 +1,15 @@ use crate::*; use frame_support::traits::AsEnsureOriginWithArg; use frame_system::EnsureRoot; -use orml_traits::asset_registry::{AssetMetadata, AssetProcessor}; +use orml_traits::{FixedConversionRateProvider as FixedConversionRateProviderTrait, + asset_registry::{AssetMetadata, AssetProcessor, Inspect}}; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use sp_core::Get; -use sp_runtime::{BoundedVec, DispatchError}; +use sp_runtime::{BoundedVec, DispatchError, traits::PhantomData}; use sp_std::fmt::Debug; use spacewalk_primitives::CurrencyId; +use xcm::opaque::v3::{MultiLocation}; #[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Encode, Decode, TypeInfo, MaxEncodedLen)] pub struct StringLimit; @@ -54,3 +56,18 @@ impl AssetProcessor> for Cust } pub type AssetAuthority = AsEnsureOriginWithArg>; +pub struct FixedConversionRateProvider(PhantomData); + +impl< + OrmlAssetRegistry: Inspect< + AssetId = CurrencyId, + Balance = Balance, + CustomMetadata = asset_registry::CustomMetadata, + >, + > FixedConversionRateProviderTrait for FixedConversionRateProvider +{ + fn get_fee_per_second(location: &MultiLocation) -> Option { + let metadata = OrmlAssetRegistry::metadata_by_location(&location)?; + Some(metadata.additional.fee_per_second) + } +} \ No newline at end of file diff --git a/runtime/common/src/benchmarking/orml_asset_registry.rs b/runtime/common/src/benchmarking/orml_asset_registry.rs index d872742e5..a1d956132 100644 --- a/runtime/common/src/benchmarking/orml_asset_registry.rs +++ b/runtime/common/src/benchmarking/orml_asset_registry.rs @@ -1,7 +1,9 @@ +use crate::asset_registry::{CustomMetadata, DiaKeys}; use frame_benchmarking::v2::benchmarks; use frame_support::assert_ok; use frame_system::RawOrigin; use orml_asset_registry::AssetMetadata; +use sp_runtime::BoundedVec; use sp_std::{vec, vec::Vec}; use spacewalk_primitives::CurrencyId; use xcm::{ diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 82a186083..323070fd2 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -2,9 +2,13 @@ #![allow(non_snake_case)] use sp_runtime::{ - traits::{CheckedDiv, IdentifyAccount, Saturating, Verify}, + traits::{IdentifyAccount, Verify,Convert}, DispatchError, MultiSignature, }; +use spacewalk_primitives::CurrencyId; +use xcm::v3::{MultiAsset, AssetId, MultiLocation}; +use orml_traits::asset_registry::Inspect; +use asset_registry::CustomMetadata; pub mod asset_registry; pub mod chain_ext; @@ -53,6 +57,8 @@ pub type Index = u32; /// A hash of some data used by the chain. pub type Hash = sp_core::H256; + + /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades @@ -70,29 +76,6 @@ pub mod opaque { pub type BlockId = generic::BlockId; } -pub struct RelativeValue { - pub num: Amount, - pub denominator: Amount, -} - -impl + Saturating + Clone> RelativeValue { - pub fn divide_by_relative_value( - amount: Amount, - relative_value: RelativeValue, - ) -> Amount { - // Calculate the adjusted amount - if let Some(adjusted_amount) = amount - .clone() - .saturating_mul(relative_value.denominator) - .checked_div(&relative_value.num) - { - return adjusted_amount - } - // We should never specify a numerator of 0, but just to be safe - return amount - } -} - #[macro_use] pub mod parachains { @@ -243,6 +226,48 @@ pub mod parachains { } } +/// CurrencyIdConvert +/// This type implements conversions from our `CurrencyId` type into `MultiLocation` and vice-versa. +/// A currency locally is identified with a `CurrencyId` variant but in the network it is identified +/// in the form of a `MultiLocation`, in this case a pCfg (Para-Id, Currency-Id). +pub struct CurrencyIdConvert(sp_std::marker::PhantomData); + +impl> Convert> for CurrencyIdConvert { + fn convert(id: CurrencyId) -> Option { + ::metadata(&id) + .filter(|m| m.location.is_some()) + .and_then(|m| m.location) + .and_then(|l| l.try_into().ok()) + } +} + +impl> Convert> for CurrencyIdConvert { + fn convert(location: MultiLocation) -> Option { + ::asset_id(&location) + } +} + +impl> Convert> for CurrencyIdConvert { + fn convert(a: MultiAsset) -> Option { + if let MultiAsset { id: AssetId::Concrete(id), fun: _ } = a { + >>::convert(id) + } else { + None + } + } +} + +/// Convert an incoming `MultiLocation` into a `CurrencyId` if possible. +/// Here we need to know the canonical representation of all the tokens we handle in order to +/// correctly convert their `MultiLocation` representation into our internal `CurrencyId` type. +impl> xcm_executor::traits::Convert for CurrencyIdConvert { + fn convert(location: MultiLocation) -> Result { + as Convert>>::convert(location) + .ok_or(location) + } +} + + #[cfg(test)] mod tests { use super::parachains::polkadot::*; diff --git a/runtime/foucoco/src/xcm_config.rs b/runtime/foucoco/src/xcm_config.rs index c666b6b68..393eff381 100644 --- a/runtime/foucoco/src/xcm_config.rs +++ b/runtime/foucoco/src/xcm_config.rs @@ -4,6 +4,7 @@ use frame_support::{ log, match_types, parameter_types, traits::{ConstU32, ContainsPair, Everything, Nothing, ProcessMessageError}, }; +use orml_asset_registry::{AssetRegistryTrader, FixedRateAssetRegistryTrader, AssetMetadata}; use orml_traits::{ location::{RelativeReserveProvider, Reserve}, parameter_type_with_key, @@ -11,26 +12,26 @@ use orml_traits::{ use orml_xcm_support::{DepositToAlternative, IsNativeConcrete, MultiCurrencyAdapter}; use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; -use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Convert; use xcm::latest::{prelude::*, Weight as XCMWeight}; use xcm_builder::{ - AccountId32Aliases, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, + AccountId32Aliases, AllowUnpaidExecutionFrom, AllowSubscriptionsFrom,AllowTopLevelPaidExecutionFrom, AllowKnownQueryResponses, EnsureXcmOrigin, FixedWeightBounds, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, UsingComponents, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, }; use xcm_executor::{traits::ShouldExecute, XcmExecutor}; +use cumulus_primitives_utility::XcmFeesTo32ByteAccount; -use runtime_common::parachains::moonbase_alpha_relay::moonbase_alpha; +use runtime_common::{asset_registry::FixedConversionRateProvider, CurrencyIdConvert, + asset_registry::CustomMetadata}; use crate::assets::{ native_locations::{native_location_external_pov, native_location_local_pov}, - xcm_assets, }; use super::{ - AccountId, Balance, Balances, Currencies, CurrencyId, FoucocoTreasuryAccount, ParachainInfo, - ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, + AccountId, AssetRegistry, Balance, Balances, Currencies, CurrencyId, FoucocoTreasuryAccount, ParachainInfo, + ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmpQueue, }; use frame_system::EnsureRoot; @@ -56,59 +57,6 @@ pub type LocationToAccountId = ( AccountId32Aliases, ); -/// CurrencyIdConvert -/// This type implements conversions from our `CurrencyId` type into `MultiLocation` and vice-versa. -/// A currency locally is identified with a `CurrencyId` variant but in the network it is identified -/// in the form of a `MultiLocation`, in this case a pCfg (Para-Id, Currency-Id). -pub struct CurrencyIdConvert; - -impl Convert> for CurrencyIdConvert { - fn convert(id: CurrencyId) -> Option { - match id { - CurrencyId::XCM(xcm_assets::RELAY) => Some(MultiLocation::parent()), - // Moonbase testnet native token - CurrencyId::XCM(xcm_assets::MOONBASE_DEV) => Some(moonbase_alpha::DEV_location()), - CurrencyId::Native => Some(native_location_external_pov()), - _ => None, - } - } -} - -impl Convert> for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Option { - match location { - loc if loc == MultiLocation::parent() => Some(xcm_assets::RELAY_id()), - // Our native currency location without re-anchoring - loc if loc == native_location_external_pov() => Some(CurrencyId::Native), - // Our native currency location with re-anchoring - // The XCM pallet will try to re-anchor the location before it reaches here - loc if loc == native_location_local_pov() => Some(CurrencyId::Native), - // Moonbase testnet native token - loc if loc == moonbase_alpha::DEV_location() => Some(xcm_assets::MOONBASE_DEV_id()), - _ => None, - } - } -} - -impl Convert> for CurrencyIdConvert { - fn convert(a: MultiAsset) -> Option { - if let MultiAsset { id: AssetId::Concrete(id), fun: _ } = a { - Self::convert(id) - } else { - None - } - } -} - -/// Convert an incoming `MultiLocation` into a `CurrencyId` if possible. -/// Here we need to know the canonical representation of all the tokens we handle in order to -/// correctly convert their `MultiLocation` representation into our internal `CurrencyId` type. -impl xcm_executor::traits::Convert for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Result { - >>::convert(location) - .ok_or(location) - } -} /// A `FilterAssetLocation` implementation. Filters multi native assets whose /// reserve is same with `origin`. @@ -132,11 +80,11 @@ pub type LocalAssetTransactor = MultiCurrencyAdapter< // Use this fungibles implementation Currencies, (), // We don't handle unknown assets. - IsNativeConcrete, + IsNativeConcrete>, AccountId, LocationToAccountId, CurrencyId, - CurrencyIdConvert, + CurrencyIdConvert, DepositToAlternative, >; @@ -165,18 +113,11 @@ parameter_types! { // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. pub UnitWeightCost: XCMWeight = XCMWeight::from_parts(1_000_000_000,0); pub const MaxInstructions: u32 = 100; - pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::parachain_id().into()))); + pub SelfLocation: MultiLocation = MultiLocation::here(); pub const BaseXcmWeight: XCMWeight = XCMWeight::from_parts(150_000_000, 0); pub const MaxAssetsForTransfer: usize = 2; } -match_types! { - pub type ParentOrParentsExecutivePlurality: impl Contains = { - MultiLocation { parents: 1, interior: Here } | - MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } - }; -} - //TODO: move DenyThenTry to polkadot's xcm module. /// Deny executing the xcm message if it matches any of the Deny filter regardless of anything else. /// If it passes the Deny, and matches one of the Allow cases then it is let through. @@ -240,7 +181,28 @@ impl ShouldExecute for DenyReserveTransferToRelayChain { } } -pub type Barrier = AllowUnpaidExecutionFrom; +match_types! { + pub type ParentOrParentsPlurality: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(Plurality { .. }) } + }; +} + +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + // Parent and its plurality get free execution + AllowUnpaidExecutionFrom, + // Expected responses are OK. + AllowKnownQueryResponses, + // Subscriptions for version tracking are OK. + AllowSubscriptionsFrom, +); + +pub type Traders = AssetRegistryTrader< + FixedRateAssetRegistryTrader>, + XcmFeesTo32ByteAccount, +>; pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { @@ -255,8 +217,7 @@ impl xcm_executor::Config for XcmConfig { type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = - UsingComponents>; + type Trader = Traders; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; type AssetLocker = (); @@ -330,7 +291,7 @@ impl orml_xtokens::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; type XcmExecutor = XcmExecutor; diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index ec73898f0..1be4874f5 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -48,11 +48,12 @@ parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polk statemint-runtime = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } statemine-runtime = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -orml-xcm = {git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.42" } -orml-xcm-support = {git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.42" } -orml-traits = {git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.42" } -orml-tokens = {git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.42" } -orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.42" } +orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.42" } +orml-xcm = { git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.42" } +orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.42" } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.42" } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library.git", branch = "polkadot-v0.9.42" } +orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.42" } # Local runtime-common = { path = "../common", default-features = false } diff --git a/runtime/integration-tests/src/amplitude_tests.rs b/runtime/integration-tests/src/amplitude_tests.rs index 972eeb290..67c2341c8 100644 --- a/runtime/integration-tests/src/amplitude_tests.rs +++ b/runtime/integration-tests/src/amplitude_tests.rs @@ -16,9 +16,10 @@ use statemine_runtime as kusama_asset_hub_runtime; use xcm::latest::NetworkId; use xcm_emulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; -const KSM_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 32000000; -const USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 640000000; -const NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 3200000000; +// Native fee expected for each token according to the `fee_per_second` values defined in the mock +const NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 4000000000; +const KSM_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN / 20; +const USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN / 10; decl_test_relay_chain! { pub struct KusamaRelay { diff --git a/runtime/integration-tests/src/mock.rs b/runtime/integration-tests/src/mock.rs index 0182e3f22..47adf9ce9 100644 --- a/runtime/integration-tests/src/mock.rs +++ b/runtime/integration-tests/src/mock.rs @@ -1,4 +1,5 @@ use crate::{sibling, AMPLITUDE_ID, ASSETHUB_ID, PENDULUM_ID, SIBLING_ID}; +use amplitude_runtime::CurrencyId as AmplitudeCurrencyId; use frame_support::traits::GenesisBuild; use pendulum_runtime::CurrencyId as PendulumCurrencyId; use polkadot_core_primitives::{AccountId, Balance, BlockNumber}; @@ -10,7 +11,18 @@ use sp_io::TestExternalities; use sp_runtime::traits::AccountIdConversion; use xcm_emulator::Weight; -use runtime_common::parachains::polkadot::moonbeam::PARA_ID as MOONBEAM_PARA_ID; +use codec::Encode; +use frame_support::BoundedVec; +use runtime_common::asset_registry::{CustomMetadata, DiaKeys, StringLimit}; + +use xcm::{ + v3::{MultiLocation}, + VersionedMultiLocation, +}; + +use runtime_common::parachains::polkadot::{ + asset_hub, moonbeam, moonbeam::PARA_ID as MOONBEAM_PARA_ID, +}; use statemine_runtime as kusama_asset_hub_runtime; use statemint_runtime as polkadot_asset_hub_runtime; @@ -84,6 +96,36 @@ macro_rules! build_parachain_with_orml { }}; } +macro_rules! build_parachain_with_orml_and_asset_registry { + ($self:ident, $runtime:ty, $system:tt, $balance:tt, $orml_balance:tt, $currency_id_type:ty, $registry_assets:tt) => {{ + let mut t = frame_system::GenesisConfig::default().build_storage::<$runtime>().unwrap(); + pallet_balances::GenesisConfig::<$runtime> { + balances: vec![(AccountId::from(ALICE), $balance), (AccountId::from(BOB), $balance)], + } + .assimilate_storage(&mut t) + .unwrap(); + + type CurrencyId = $currency_id_type; + orml_tokens::GenesisConfig::<$runtime> { + balances: vec![ + (AccountId::from(BOB), CurrencyId::XCM(0), units($orml_balance)), + (AccountId::from(ALICE), CurrencyId::XCM(0), units($orml_balance)), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + orml_asset_registry::GenesisConfig::<$runtime> { + assets: $registry_assets, + last_asset_id: CurrencyId::Native, + } + .assimilate_storage(&mut t) + .unwrap(); + + build_parachain!($self, $runtime, $system, t) + }}; +} + macro_rules! build_parachain { ($self:ident, $runtime:ty, $system:tt) => {{ let mut t = frame_system::GenesisConfig::default().build_storage::<$runtime>().unwrap(); @@ -180,6 +222,152 @@ fn default_parachains_host_configuration() -> HostConfiguration { ..Default::default() } } +fn assets_metadata_for_registry_pendulum() -> Vec<(PendulumCurrencyId, Vec)> { + vec![ + ( + PendulumCurrencyId::Native, + orml_asset_registry::AssetMetadata { + decimals: 12u32, + name: "Pendulum".as_bytes().to_vec(), + symbol: "PEN".as_bytes().to_vec(), + existential_deposit: 1_000u128, + location: Some(VersionedMultiLocation::V3(MultiLocation::new( + 0u8, + xcm::latest::Junctions::X1( + xcm::latest::Junction::PalletInstance(10), + ), + ))), + additional: CustomMetadata { + dia_keys: DiaKeys:: { + blockchain: BoundedVec::truncate_from(vec![1, 2, 3]), + symbol: BoundedVec::truncate_from(vec![1, 2, 3]), + }, + fee_per_second: UNIT, + }, + } + .encode(), + ), + + ( + PendulumCurrencyId::XCM(1), + orml_asset_registry::AssetMetadata { + decimals: 12u32, + name: "USDT Assethub".as_bytes().to_vec(), + symbol: "USDT".as_bytes().to_vec(), + existential_deposit: 1_000u128, + location: Some(VersionedMultiLocation::V3(asset_hub::USDT_location())), + additional: CustomMetadata { + dia_keys: DiaKeys:: { + blockchain: BoundedVec::truncate_from(vec![1, 2, 3]), + symbol: BoundedVec::truncate_from(vec![1, 2, 3]), + }, + fee_per_second: UNIT/2, + }, + } + .encode(), + ), + ( + PendulumCurrencyId::XCM(0), + orml_asset_registry::AssetMetadata { + decimals: 12u32, + name: "Polkadot".as_bytes().to_vec(), + symbol: "DOT".as_bytes().to_vec(), + existential_deposit: 1_000u128, + location: Some(VersionedMultiLocation::V3(MultiLocation::parent())), + additional: CustomMetadata { + dia_keys: DiaKeys:: { + blockchain: BoundedVec::truncate_from(vec![1, 2, 3]), + symbol: BoundedVec::truncate_from(vec![1, 2, 3]), + }, + fee_per_second: UNIT/4, + }, + } + .encode(), + ), + ( + PendulumCurrencyId::XCM(6), + orml_asset_registry::AssetMetadata { + decimals: 12u32, + name: "Moonbeam BRZ".as_bytes().to_vec(), + symbol: "BRZ".as_bytes().to_vec(), + existential_deposit: 1_000u128, + location: Some(xcm::VersionedMultiLocation::V3(moonbeam::BRZ_location())), + additional: CustomMetadata { + dia_keys: DiaKeys:: { + blockchain: BoundedVec::truncate_from(vec![1, 2, 3]), + symbol: BoundedVec::truncate_from(vec![1, 2, 3]), + }, + fee_per_second: 2*UNIT, + }, + } + .encode(), + ), + ] +} + +fn assets_metadata_for_registry_amplitude() -> Vec<(AmplitudeCurrencyId, Vec)> { + vec![ + ( + AmplitudeCurrencyId::Native, + orml_asset_registry::AssetMetadata { + decimals: 12u32, + name: "Amplitude".as_bytes().to_vec(), + symbol: "AMPE".as_bytes().to_vec(), + existential_deposit: 1_000u128, + location: Some(VersionedMultiLocation::V3(MultiLocation::new( + 0u8, + xcm::latest::Junctions::X1( + xcm::latest::Junction::PalletInstance(10), + ), + ))), + additional: CustomMetadata { + dia_keys: DiaKeys:: { + blockchain: BoundedVec::truncate_from(vec![1, 2, 3]), + symbol: BoundedVec::truncate_from(vec![1, 2, 3]), + }, + fee_per_second: UNIT, + }, + } + .encode(), + ), + ( + AmplitudeCurrencyId::XCM(1), + orml_asset_registry::AssetMetadata { + decimals: 12u32, + name: "USDT Assethub".as_bytes().to_vec(), + symbol: "USDT".as_bytes().to_vec(), + existential_deposit: 1_000u128, + location: Some(VersionedMultiLocation::V3(asset_hub::USDT_location())), + additional: CustomMetadata { + dia_keys: DiaKeys:: { + blockchain: BoundedVec::truncate_from(vec![1, 2, 3]), + symbol: BoundedVec::truncate_from(vec![1, 2, 3]), + }, + fee_per_second: UNIT/10, + }, + } + .encode(), + ), + ( + AmplitudeCurrencyId::XCM(0), + orml_asset_registry::AssetMetadata { + decimals: 12u32, + name: "Kusama".as_bytes().to_vec(), + symbol: "KSM".as_bytes().to_vec(), + existential_deposit: 1_000u128, + location: Some(VersionedMultiLocation::V3(MultiLocation::parent())), + additional: CustomMetadata { + dia_keys: DiaKeys:: { + blockchain: BoundedVec::truncate_from(vec![1, 2, 3]), + symbol: BoundedVec::truncate_from(vec![1, 2, 3]), + }, + fee_per_second: UNIT/20, + }, + } + .encode(), + ), + ] +} pub fn para_ext(chain: ParachainType) -> sp_io::TestExternalities { match chain { @@ -226,27 +414,31 @@ impl Builder for ExtBuilderParachain { } fn build(self) -> TestExternalities { + let assets_metadata_pendulum = assets_metadata_for_registry_pendulum(); + let assets_metadata_amplitude = assets_metadata_for_registry_amplitude(); match self.chain { ParachainType::Pendulum => { use pendulum_runtime::{Runtime, System}; - build_parachain_with_orml!( + build_parachain_with_orml_and_asset_registry!( self, Runtime, System, NATIVE_INITIAL_BALANCE, ORML_INITIAL_BALANCE, - PendulumCurrencyId + PendulumCurrencyId, + assets_metadata_pendulum ) }, ParachainType::Amplitude => { use amplitude_runtime::{Runtime, System}; - build_parachain_with_orml!( + build_parachain_with_orml_and_asset_registry!( self, Runtime, System, NATIVE_INITIAL_BALANCE, ORML_INITIAL_BALANCE, - PendulumCurrencyId + AmplitudeCurrencyId, + assets_metadata_amplitude ) }, _ => panic!("cannot use this chain to build"), diff --git a/runtime/integration-tests/src/pendulum_tests.rs b/runtime/integration-tests/src/pendulum_tests.rs index 9e317eb35..80df82ece 100644 --- a/runtime/integration-tests/src/pendulum_tests.rs +++ b/runtime/integration-tests/src/pendulum_tests.rs @@ -18,10 +18,11 @@ use statemint_runtime as polkadot_asset_hub_runtime; use xcm::latest::NetworkId; use xcm_emulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt}; -const DOT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 32653061; //The fees that relay chain will charge when transfer DOT to parachain. sovereign account of some parachain will receive transfer_amount - DOT_FEE -const MOONBEAM_BRZ_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 1391304347; //Fees that we will charge in incoming Moonbeam's BRZ. Depends on the RelativeValue struct implementation. -const USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 266666666; -const NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 3200000000; +// Native fee expected for each token according to the `fee_per_second` values defined in the mock +const NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 4000000000; +const DOT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN /4; +const MOONBEAM_BRZ_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 2*NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN; +const USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN /2; decl_test_relay_chain! { pub struct PolkadotRelay { diff --git a/runtime/integration-tests/src/sibling.rs b/runtime/integration-tests/src/sibling.rs index 3a6cdc708..4b5cebd91 100644 --- a/runtime/integration-tests/src/sibling.rs +++ b/runtime/integration-tests/src/sibling.rs @@ -142,6 +142,7 @@ impl Convert> for CurrencyIdConvert { } impl Convert> for CurrencyIdConvert { + fn convert(location: MultiLocation) -> Option { match location { MultiLocation { diff --git a/runtime/integration-tests/src/test_macros.rs b/runtime/integration-tests/src/test_macros.rs index 1eed61c4c..68e0298eb 100644 --- a/runtime/integration-tests/src/test_macros.rs +++ b/runtime/integration-tests/src/test_macros.rs @@ -236,12 +236,13 @@ macro_rules! parachain1_transfer_incorrect_asset_to_parachain2_should_fail { $parachain2::execute_with(|| { use $para2_runtime::{RuntimeEvent, System}; - //most likely this is not emitid because buy execution fails + //since the asset registry trader cannot find the fee per second for the asset, + //it will return TooExpensive error. assert!(System::events().iter().any(|r| matches!( r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Fail { message_hash: _, - error: xcm::v3::Error::AssetNotFound, + error: xcm::v3::Error::TooExpensive, weight: _ }) ))); @@ -484,7 +485,7 @@ macro_rules! transfer_native_token_from_parachain1_to_parachain2_and_back { use frame_support::traits::fungibles::Inspect; use polkadot_core_primitives::Balance; use xcm::latest::{ - Junction, Junction::AccountId32, Junctions::X2, MultiLocation, WeightLimit, + Junction, Junction::AccountId32, Junctions::{X2, X1}, MultiLocation, WeightLimit, }; use orml_traits::MultiCurrency; use $parachain1_runtime::CurrencyId as Parachain1CurrencyId; @@ -493,6 +494,10 @@ macro_rules! transfer_native_token_from_parachain1_to_parachain2_and_back { $mocknet::reset(); let transfer_amount: Balance = UNIT; + let asset_location_local_pov = MultiLocation::new( + 0, + X1(Junction::PalletInstance(10)), + ); let asset_location = MultiLocation::new( 1, X2(Junction::Parachain($parachain1_id), Junction::PalletInstance(10)), @@ -524,7 +529,7 @@ macro_rules! transfer_native_token_from_parachain1_to_parachain2_and_back { // Transfer using multilocation assert_ok!(XTokens::transfer_multiasset( $parachain1_runtime::RuntimeOrigin::signed(ALICE.into()), - Box::new((asset_location.clone(), transfer_amount).into()), + Box::new((asset_location_local_pov.clone(), transfer_amount).into()), Box::new( MultiLocation { parents: 1, @@ -538,6 +543,24 @@ macro_rules! transfer_native_token_from_parachain1_to_parachain2_and_back { WeightLimit::Unlimited )); + // Alternatively, we should be able to use + // assert_ok!(XTokens::transfer( + // $parachain1_runtime::RuntimeOrigin::signed(ALICE.into()), + // Parachain1CurrencyId::Native, + // transfer_amount, + // Box::new( + // MultiLocation { + // parents: 1, + // interior: X2( + // Junction::Parachain($parachain2_id), + // AccountId32 { network: None, id: BOB } + // ) + // } + // .into() + // ), + // WeightLimit::Unlimited + // )); + assert!(System::events().iter().any(|r| matches!( r.event, RuntimeEvent::XTokens(orml_xtokens::Event::TransferredMultiAssets { .. }) @@ -641,6 +664,7 @@ macro_rules! moonbeam_transfers_token_and_handle_automation { use pendulum_runtime::assets::xcm_assets; use orml_traits::MultiCurrency; + use $parachain1_runtime::CurrencyId as Parachain1CurrencyId; use $parachain2_runtime::CurrencyId as Parachain2CurrencyId; $mocknet::reset(); @@ -686,14 +710,15 @@ macro_rules! moonbeam_transfers_token_and_handle_automation { $parachain1::execute_with(|| { use $parachain1_runtime::{RuntimeEvent, System, Treasury}; // given the configuration in pendulum's xcm_config, we expect the callback (in this case a Remark) - // to be executed + // to be executed and the treasury to be rewarded with the expected fee assert!(System::events().iter().any(|r| matches!( r.event, RuntimeEvent::System(frame_system::Event::Remarked { .. }) ))); + // For parachain 1 (Pendulum) BRZ token is located at index 6 assert_eq!( - $parachain1_runtime::Currencies::free_balance(xcm_assets::MOONBEAM_BRZ_id(), &Treasury::account_id()), + $parachain1_runtime::Currencies::free_balance(Parachain1CurrencyId::XCM(6), &Treasury::account_id()), $expected_fee ); diff --git a/runtime/pendulum/src/xcm_config.rs b/runtime/pendulum/src/xcm_config.rs index ae328345f..9c82d63b2 100644 --- a/runtime/pendulum/src/xcm_config.rs +++ b/runtime/pendulum/src/xcm_config.rs @@ -1,15 +1,11 @@ use core::marker::PhantomData; -use cumulus_primitives_utility::{ - ChargeWeightInFungibles, TakeFirstAssetTrader, XcmFeesTo32ByteAccount, -}; +use cumulus_primitives_utility::XcmFeesTo32ByteAccount; use frame_support::{ - log, match_types, - pallet_prelude::DispatchError, - parameter_types, - traits::{tokens::fungibles, ContainsPair, Everything, Nothing, ProcessMessageError}, - weights::{Weight, WeightToFee as WeightToFeeTrait}, + log, match_types, parameter_types, + traits::{ContainsPair, Everything, Nothing, ProcessMessageError}, }; +use orml_asset_registry::{AssetRegistryTrader, FixedRateAssetRegistryTrader}; use orml_traits::{ location::{RelativeReserveProvider, Reserve}, parameter_type_with_key, @@ -22,40 +18,25 @@ use sp_runtime::traits::Convert; use xcm::latest::{prelude::*, Weight as XCMWeight}; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin, - FixedWeightBounds, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, -}; -use xcm_executor::{ - traits::{JustTry, ShouldExecute}, - XcmExecutor, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, }; +use xcm_executor::{traits::ShouldExecute, XcmExecutor}; use runtime_common::{ custom_transactor::{AssetData, AutomationPalletConfig, CustomTransactorInterceptor}, - parachains::polkadot::{asset_hub, equilibrium, moonbeam, polkadex}, - RelativeValue, + parachains::polkadot::{moonbeam}, + asset_registry::{ FixedConversionRateProvider}, + CurrencyIdConvert, }; -use sp_runtime::traits::Zero; - -use crate::{ - assets::{ - self, - native_locations::{ - native_location_external_pov, native_location_local_pov, EURC_location_external_pov, - EURC_location_local_pov, - }, - xcm_assets, - }, - ConstU32, -}; +use crate::ConstU32; use super::{ - AccountId, Balance, Balances, Currencies, CurrencyId, ParachainInfo, ParachainSystem, - PendulumTreasuryAccount, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, - System, Tokens, WeightToFee, XcmpQueue, + AccountId, AssetRegistry, Balance, Balances, Currencies, CurrencyId, ParachainInfo, + ParachainSystem, PendulumTreasuryAccount, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, + RuntimeOrigin, System, XcmpQueue, }; use frame_system::EnsureRoot; @@ -80,103 +61,6 @@ pub type LocationToAccountId = ( AccountId32Aliases, ); -/// CurrencyIdConvert -/// This type implements conversions from our `CurrencyId` type into `MultiLocation` and vice-versa. -/// A currency locally is identified with a `CurrencyId` variant but in the network it is identified -/// in the form of a `MultiLocation`, in this case a pCfg (Para-Id, Currency-Id). -pub struct CurrencyIdConvert; - -impl Convert> for CurrencyIdConvert { - fn convert(id: CurrencyId) -> Option { - match id { - CurrencyId::XCM(f) => match f { - xcm_assets::RELAY_DOT => Some(MultiLocation::parent()), - xcm_assets::ASSETHUB_USDT => Some(asset_hub::USDT_location()), - xcm_assets::ASSETHUB_USDC => Some(asset_hub::USDC_location()), - xcm_assets::EQUILIBRIUM_EQD => Some(equilibrium::EQD_location()), - xcm_assets::MOONBEAM_BRZ => Some(moonbeam::BRZ_location()), - xcm_assets::POLKADEX_PDEX => Some(polkadex::PDEX_location()), - xcm_assets::MOONBEAM_GLMR => Some(moonbeam::GLMR_location()), - xcm_assets::ASSETHUB_PINK => Some(asset_hub::PINK_location()), - _ => None, - }, - - CurrencyId::Native => Some(native_location_external_pov()), - assets::tokens::EURC_ID => Some(EURC_location_external_pov()), - _ => None, - } - } -} - -type RelativeValueOf = RelativeValue; - -pub struct RelayRelativeValue; -impl RelayRelativeValue { - fn get_relative_value(id: CurrencyId) -> Option { - match id { - CurrencyId::XCM(f) => match f { - xcm_assets::RELAY_DOT => Some(RelativeValueOf { num: 98, denominator: 1 }), - xcm_assets::ASSETHUB_USDT => Some(RelativeValueOf { num: 12, denominator: 1 }), - xcm_assets::ASSETHUB_USDC => Some(RelativeValueOf { num: 12, denominator: 1 }), - xcm_assets::EQUILIBRIUM_EQD => Some(RelativeValueOf { num: 12, denominator: 1 }), - xcm_assets::MOONBEAM_BRZ => Some(RelativeValueOf { num: 23, denominator: 10 }), - xcm_assets::POLKADEX_PDEX => Some(RelativeValueOf { num: 14, denominator: 1 }), - xcm_assets::MOONBEAM_GLMR => Some(RelativeValueOf { num: 55, denominator: 10 }), - _ => None, - }, - - CurrencyId::Native => Some(RelativeValueOf { num: 1, denominator: 1 }), - assets::tokens::EURC_ID => Some(RelativeValueOf { num: 13, denominator: 1 }), - _ => Some(RelativeValueOf { num: 10, denominator: 1 }), - } - } -} - -impl Convert> for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Option { - match location { - loc if loc == MultiLocation::parent() => Some(xcm_assets::RELAY_DOT_id()), - - loc if loc == asset_hub::USDT_location() => Some(xcm_assets::ASSETHUB_USDT_id()), - loc if loc == asset_hub::USDC_location() => Some(xcm_assets::ASSETHUB_USDC_id()), - loc if loc == equilibrium::EQD_location() => Some(xcm_assets::EQUILIBRIUM_EQD_id()), - loc if loc == moonbeam::BRZ_location() => Some(xcm_assets::MOONBEAM_BRZ_id()), - loc if loc == polkadex::PDEX_location() => Some(xcm_assets::POLKADEX_PDEX_id()), - loc if loc == moonbeam::GLMR_location() => Some(xcm_assets::MOONBEAM_GLMR_id()), - loc if loc == asset_hub::PINK_location() => Some(xcm_assets::ASSETHUB_PINK_id()), - - // Our native currency location without re-anchoring - loc if loc == native_location_external_pov() => Some(CurrencyId::Native), - // Our native currency location with re-anchoring - // The XCM pallet will try to re-anchor the location before it reaches here - loc if loc == native_location_local_pov() => Some(CurrencyId::Native), - loc if loc == EURC_location_external_pov() => Some(assets::tokens::EURC_ID), - loc if loc == EURC_location_local_pov() => Some(assets::tokens::EURC_ID), - _ => None, - } - } -} - -impl Convert> for CurrencyIdConvert { - fn convert(a: MultiAsset) -> Option { - if let MultiAsset { id: AssetId::Concrete(id), fun: _ } = a { - Self::convert(id) - } else { - None - } - } -} - -/// Convert an incoming `MultiLocation` into a `CurrencyId` if possible. -/// Here we need to know the canonical representation of all the tokens we handle in order to -/// correctly convert their `MultiLocation` representation into our internal `CurrencyId` type. -impl xcm_executor::traits::Convert for CurrencyIdConvert { - fn convert(location: MultiLocation) -> Result { - >>::convert(location) - .ok_or(location) - } -} - /// A `FilterAssetLocation` implementation. Filters multi native assets whose /// reserve is same with `origin`. pub struct MultiNativeAsset(PhantomData); @@ -219,18 +103,11 @@ parameter_types! { // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. pub UnitWeightCost: XCMWeight = XCMWeight::from_parts(1_000_000_000, 0); pub const MaxInstructions: u32 = 100; - pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::parachain_id().into()))); + pub SelfLocation: MultiLocation = MultiLocation::here(); pub const BaseXcmWeight: XCMWeight = XCMWeight::from_parts(150_000_000, 0); pub const MaxAssetsForTransfer: usize = 2; } -match_types! { - pub type ParentOrParentsExecutivePlurality: impl Contains = { - MultiLocation { parents: 1, interior: Here } | - MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } - }; -} - //TODO: move DenyThenTry to polkadot's xcm module. /// Deny executing the xcm message if it matches any of the Deny filter regardless of anything else. /// If it passes the Deny, and matches one of the Allow cases then it is let through. @@ -312,129 +189,23 @@ pub type Barrier = ( AllowSubscriptionsFrom, ); -pub struct ChargeWeightInFungiblesImplementation; -impl ChargeWeightInFungibles for ChargeWeightInFungiblesImplementation { - fn charge_weight_in_fungibles( - asset_id: CurrencyId, - weight: Weight, - ) -> Result { - let amount = ::weight_to_fee(&weight); - - // since this is calibrated (in theory) for the native of the relay - // we should just have a multiplier for relative "value" of that token - // and adjust the amount inversily proportional to the value - if let Some(relative_value) = RelayRelativeValue::get_relative_value(asset_id) { - let adjusted_amount = - RelativeValue::::divide_by_relative_value(amount, relative_value); - log::info!("amount to be charged: {:?} in asset: {:?}", adjusted_amount, asset_id); - return Ok(adjusted_amount) - } else { - log::info!("amount to be charged: {:?} in asset: {:?}", amount, asset_id); - return Ok(amount) - } - } -} +pub type Traders = AssetRegistryTrader< + FixedRateAssetRegistryTrader>, + XcmFeesTo32ByteAccount, +>; /// Means for transacting the currencies of this parachain type Transactor = MultiCurrencyAdapter< Currencies, (), // We don't handle unknown assets. - IsNativeConcrete, + IsNativeConcrete>, AccountId, LocationToAccountId, CurrencyId, - CurrencyIdConvert, + CurrencyIdConvert, DepositToAlternative, >; -// Workarround for TakeFirstAssetTrader -use frame_support::traits::tokens::{ - DepositConsequence, Fortitude, Preservation, Provenance, WithdrawConsequence, -}; - -pub struct ConcreteAssets; -impl fungibles::Mutate for ConcreteAssets {} -impl fungibles::Balanced for ConcreteAssets { - type OnDropCredit = fungibles::DecreaseIssuance; - type OnDropDebt = fungibles::IncreaseIssuance; -} - -// We only use minimum_balance of these implementations -impl fungibles::Inspect for ConcreteAssets { - type AssetId = >::AssetId; - type Balance = >::Balance; - - fn minimum_balance(id: Self::AssetId) -> Self::Balance { - Tokens::minimum_balance(id) - } - - fn total_issuance(asset_id: Self::AssetId) -> Self::Balance { - Tokens::total_issuance(asset_id) - } - - fn balance(asset_id: Self::AssetId, account_id: &AccountId) -> Self::Balance { - Tokens::balance(asset_id, account_id) - } - - fn total_balance(asset_id: Self::AssetId, account_id: &AccountId) -> Self::Balance { - Tokens::balance(asset_id, account_id) - } - - fn reducible_balance( - _: Self::AssetId, - _: &AccountId, - _: Preservation, - _: Fortitude, - ) -> Self::Balance { - Self::Balance::zero() - } - - fn can_deposit( - _: Self::AssetId, - _: &AccountId, - _: Self::Balance, - _: Provenance, - ) -> DepositConsequence { - DepositConsequence::UnknownAsset - } - - fn can_withdraw( - _: Self::AssetId, - _: &AccountId, - _: Self::Balance, - ) -> WithdrawConsequence { - WithdrawConsequence::UnknownAsset - } - - fn asset_exists(_: Self::AssetId) -> bool { - false - } -} - -// Not used -impl fungibles::Unbalanced for ConcreteAssets { - fn handle_dust(_: fungibles::Dust) {} - fn write_balance( - _: Self::AssetId, - _: &AccountId, - _: Self::Balance, - ) -> Result, DispatchError> { - core::prelude::v1::Err(DispatchError::CannotLookup) - } - - fn set_total_issuance(_: Self::AssetId, _: Self::Balance) {} -} - -pub type Traders = ( - TakeFirstAssetTrader< - AccountId, - ChargeWeightInFungiblesImplementation, - ConvertedConcreteId, - ConcreteAssets, - XcmFeesTo32ByteAccount, - >, -); - // We will allow for BRZ location from moonbeam pub struct AutomationPalletConfigPendulum; @@ -564,7 +335,7 @@ impl orml_xtokens::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type CurrencyId = CurrencyId; - type CurrencyIdConvert = CurrencyIdConvert; + type CurrencyIdConvert = CurrencyIdConvert; type AccountIdToMultiLocation = AccountIdToMultiLocation; type SelfLocation = SelfLocation; type XcmExecutor = XcmExecutor;