From e7024c897e93adce67e2e120f75df8313ba7abf7 Mon Sep 17 00:00:00 2001 From: "B. Yap" <2826165+b-yap@users.noreply.github.com> Date: Tue, 21 Nov 2023 22:20:01 +0800 Subject: [PATCH] 296 Enable XCM assets on Pendulum (#339) * first iteration * add moonbeam; also move macro to `common` * added PDEX https://github.com/pendulum-chain/pendulum/issues/296#issuecomment-1807870891 * segregate assets/tokens added EURC * https://github.com/pendulum-chain/pendulum/pull/339#discussion_r1397479229, https://github.com/pendulum-chain/pendulum/pull/339#discussion_r1397483894, https://github.com/pendulum-chain/pendulum/pull/339#discussion_r1397537722 * https://github.com/pendulum-chain/pendulum/actions/runs/6926668943/job/18839202556?pr=339#step:8:2029 * https://github.com/pendulum-chain/pendulum/pull/339#discussion_r1398928528 * cargo fmt --- Cargo.lock | 4 + runtime/amplitude/Cargo.toml | 1 + runtime/amplitude/src/assets.rs | 39 ++++++ runtime/amplitude/src/lib.rs | 3 +- runtime/amplitude/src/xcm_config.rs | 47 ++----- runtime/common/Cargo.toml | 1 + runtime/common/src/lib.rs | 161 +++++++++++++++++++++-- runtime/common/src/zenlink.rs | 6 +- runtime/foucoco/Cargo.toml | 1 + runtime/foucoco/src/assets.rs | 37 ++++++ runtime/foucoco/src/lib.rs | 1 + runtime/foucoco/src/xcm_config.rs | 22 ++-- runtime/integration-tests/src/sibling.rs | 20 +-- runtime/pendulum/Cargo.toml | 1 + runtime/pendulum/src/assets.rs | 84 ++++++++++++ runtime/pendulum/src/lib.rs | 2 + runtime/pendulum/src/xcm_config.rs | 69 +++++----- 17 files changed, 388 insertions(+), 111 deletions(-) create mode 100644 runtime/amplitude/src/assets.rs create mode 100644 runtime/foucoco/src/assets.rs create mode 100644 runtime/pendulum/src/assets.rs diff --git a/Cargo.lock b/Cargo.lock index 5d907a149..a68205c5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -253,6 +253,7 @@ dependencies = [ "parachain-info", "parachain-staking", "parity-scale-codec", + "paste", "polkadot-parachain", "polkadot-runtime-common", "pooled-rewards", @@ -3068,6 +3069,7 @@ dependencies = [ "parachain-info", "parachain-staking", "parity-scale-codec", + "paste", "polkadot-parachain", "polkadot-runtime-common", "pooled-rewards", @@ -7754,6 +7756,7 @@ dependencies = [ "parachain-info", "parachain-staking", "parity-scale-codec", + "paste", "polkadot-parachain", "polkadot-runtime-common", "runtime-common", @@ -10008,6 +10011,7 @@ dependencies = [ "orml-asset-registry", "orml-traits", "parity-scale-codec", + "paste", "scale-info", "sp-consensus-aura", "sp-core", diff --git a/runtime/amplitude/Cargo.toml b/runtime/amplitude/Cargo.toml index d908b2d95..aade36dbb 100644 --- a/runtime/amplitude/Cargo.toml +++ b/runtime/amplitude/Cargo.toml @@ -18,6 +18,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex-literal = { version = "0.3.4", optional = true } log = { version = "0.4.17", default-features = false } +paste = "1.0.14" scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.144", optional = true, features = ["derive"] } smallvec = "1.9.0" diff --git a/runtime/amplitude/src/assets.rs b/runtime/amplitude/src/assets.rs new file mode 100644 index 000000000..38654694e --- /dev/null +++ b/runtime/amplitude/src/assets.rs @@ -0,0 +1,39 @@ +#![allow(non_snake_case)] + +pub mod xcm_assets { + use runtime_common::create_xcm_id; + + create_xcm_id!(RELAY_KSM, 0); + create_xcm_id!(ASSETHUB_USDT, 1); +} + +/// Locations for native currency and all natively issued tokens +pub mod native_locations { + use crate::ParachainInfo; + use frame_support::traits::PalletInfoAccess; + use xcm::latest::{ + Junction::{PalletInstance, Parachain}, + Junctions::{X1, X2}, + MultiLocation, + }; + + fn balances_pallet_id() -> u8 { + crate::Balances::index() as u8 + } + + /// location of the native currency from the point of view of Pendulum parachain + pub fn native_location_local_pov() -> MultiLocation { + MultiLocation { parents: 0, interior: X1(PalletInstance(balances_pallet_id())) } + } + + /// location of the native currency from the point of view of other parachains(external) + pub fn native_location_external_pov() -> MultiLocation { + MultiLocation { + parents: 1, + interior: X2( + Parachain(ParachainInfo::parachain_id().into()), + PalletInstance(balances_pallet_id()), + ), + } + } +} diff --git a/runtime/amplitude/src/lib.rs b/runtime/amplitude/src/lib.rs index 19fe8b572..dc9887728 100644 --- a/runtime/amplitude/src/lib.rs +++ b/runtime/amplitude/src/lib.rs @@ -6,6 +6,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +mod assets; mod weights; pub mod xcm_config; pub mod zenlink; @@ -1889,4 +1890,4 @@ cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, CheckInherents = CheckInherents, -} \ No newline at end of file +} diff --git a/runtime/amplitude/src/xcm_config.rs b/runtime/amplitude/src/xcm_config.rs index cf66826cb..978db033b 100644 --- a/runtime/amplitude/src/xcm_config.rs +++ b/runtime/amplitude/src/xcm_config.rs @@ -2,7 +2,13 @@ use super::{ AccountId, Balance, Balances, CurrencyId, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, WeightToFee, XcmpQueue, }; -use crate::ConstU32; +use crate::{ + assets::{ + native_locations::{native_location_external_pov, native_location_local_pov}, + xcm_assets, + }, + ConstU32, +}; use core::marker::PhantomData; use frame_support::{ log, match_types, parameter_types, @@ -29,9 +35,6 @@ use xcm_executor::{ XcmExecutor, }; -const XCM_ASSET_RELAY_KSM: u8 = 0; -const XCM_ASSET_ASSETHUB_USDT: u8 = 1; - parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = NetworkId::Kusama; @@ -64,21 +67,11 @@ impl Convert> for CurrencyIdConvert { fn convert(id: CurrencyId) -> Option { match id { CurrencyId::XCM(index) => match index { - XCM_ASSET_RELAY_KSM => Some(MultiLocation::parent()), - XCM_ASSET_ASSETHUB_USDT => Some(MultiLocation::new( - 1, - X3( - Parachain(asset_hub::PARA_ID), - PalletInstance(asset_hub::ASSET_PALLET_ID), - GeneralIndex(asset_hub::USDT_ASSET_ID), - ), - )), + xcm_assets::RELAY_KSM => Some(MultiLocation::parent()), + xcm_assets::ASSETHUB_USDT => Some(asset_hub::USDT_location()), _ => None, }, - CurrencyId::Native => Some(MultiLocation::new( - 1, - X2(Parachain(ParachainInfo::parachain_id().into()), PalletInstance(10)), - )), + CurrencyId::Native => Some(native_location_external_pov()), _ => None, } } @@ -87,25 +80,13 @@ impl Convert> for CurrencyIdConvert { impl Convert> for CurrencyIdConvert { fn convert(location: MultiLocation) -> Option { match location { - MultiLocation { parents: 1, interior: Here } => - Some(CurrencyId::XCM(XCM_ASSET_RELAY_KSM)), - MultiLocation { - parents: 1, - interior: - X3( - Parachain(asset_hub::PARA_ID), - PalletInstance(asset_hub::ASSET_PALLET_ID), - GeneralIndex(asset_hub::USDT_ASSET_ID), - ), - } => Some(CurrencyId::XCM(XCM_ASSET_ASSETHUB_USDT)), + 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 - MultiLocation { parents: 1, interior: X2(Parachain(id), PalletInstance(10)) } - if id == u32::from(ParachainInfo::parachain_id()) => - Some(CurrencyId::Native), + 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 - MultiLocation { parents: 0, interior: X1(PalletInstance(10)) } => - Some(CurrencyId::Native), + loc if loc == native_location_local_pov() => Some(CurrencyId::Native), _ => None, } } diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 28a5e9687..ff0d48d7b 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -11,6 +11,7 @@ edition = "2021" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +paste = "1.0.14" parity-scale-codec = { version = "3.1.5", default-features = false, features = ["derive"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 1f166a17e..c322e62da 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(not(feature = "std"), no_std)] +#![allow(non_snake_case)] use sp_runtime::{ traits::{IdentifyAccount, Verify}, @@ -68,24 +69,168 @@ pub mod opaque { pub type BlockId = generic::BlockId; } +#[macro_use] pub mod parachains { + + /// Creates a function and a const u8 representation of the value. + /// # Examples + /// `create_xcm_id!(PARACHAIN_ASSET,100);` + /// + /// will look like: + /// ``` + /// use spacewalk_primitives::CurrencyId; + /// + /// pub const PARACHAIN_ASSET : u8 = 100; + /// pub fn PARACHAIN_ASSET_id() -> CurrencyId { + /// CurrencyId::XCM(PARACHAIN_ASSET) + /// } + /// ``` + #[macro_export] + macro_rules! create_xcm_id { + ($asset_name:ident, $u8_repr:literal) => { + paste::item! { + pub const $asset_name :u8 = $u8_repr; + + pub fn [< $asset_name _id >]() -> crate::CurrencyId { + spacewalk_primitives::CurrencyId::XCM($asset_name) + } + } + }; + } + + /// Creates a location for the given asset in this format: `fn _location() -> MultiLocation` + macro_rules! parachain_asset_location { + // Also declares a constant variable _ASSET_ID with . + // This assumes that the following constant variables exist: + // * `PARA_ID` - the parachain id + // * `ASSET_PALLET_INDEX` - the index of the Assets Pallet + ($asset_name:ident, $asset_index: literal) => { + paste::item! { + pub const [< $asset_name _ASSET_ID >] : u128 = $asset_index; + + pub fn [< $asset_name _location >] () -> xcm::latest::MultiLocation { + xcm::latest::MultiLocation { + parents: 1, + interior: xcm::latest::Junctions::X3( + xcm::latest::Junction::Parachain(PARA_ID), + xcm::latest::Junction::PalletInstance(ASSET_PALLET_INDEX), + xcm::latest::Junction::GeneralIndex($asset_index) + ), + } + } + } + }; + + // Accepts the asset name AND the interior of the location + // mostly for locations that do not use a `GeneralIndex` + ($asset_name:ident, $interiors: expr) => { + paste::item! { + pub fn [< $asset_name _location >] () -> xcm::latest::MultiLocation { + xcm::latest::MultiLocation { + parents: 1, + interior: $interiors + } + } + + } + }; + } + pub mod polkadot { pub mod asset_hub { pub const PARA_ID: u32 = 1000; - pub const ASSET_PALLET_ID: u8 = 50; + pub const ASSET_PALLET_INDEX: u8 = 50; + + parachain_asset_location!(USDC, 1337); + parachain_asset_location!(USDT, 1984); + } + + pub mod equilibrium { + pub const PARA_ID: u32 = 2011; + pub const ASSET_PALLET_INDEX: u8 = 11; + + parachain_asset_location!(EQ, 25_969); + parachain_asset_location!(EQD, 6_648_164); + } + + pub mod moonbeam { + use xcm::latest::{ + Junction::{AccountKey20, PalletInstance, Parachain}, + Junctions::X3, + }; + + pub const PARA_ID: u32 = 2004; + pub const ASSET_PALLET_INDEX: u8 = 110; + // 0xD65A1872f2E2E26092A443CB86bb5d8572027E6E + // extracted using `H160::from_str("...")` then `as_bytes()` + pub const BRZ_ASSET_ACCOUNT_IN_BYTES: [u8; 20] = [ + 214, 90, 24, 114, 242, 226, 226, 96, 146, 164, 67, 203, 134, 187, 93, 133, 114, 2, + 126, 110, + ]; + + parachain_asset_location!( + BRZ, + X3( + Parachain(PARA_ID), + PalletInstance(ASSET_PALLET_INDEX), + AccountKey20 { network: None, key: BRZ_ASSET_ACCOUNT_IN_BYTES } + ) + ); + } - pub const USDC_ASSET_ID: u128 = 1337; - pub const USDT_ASSET_ID: u128 = 1984; + pub mod polkadex { + use xcm::latest::{Junction::Parachain, Junctions::X1}; + + pub const PARA_ID: u32 = 2040; + + parachain_asset_location!(PDEX, X1(Parachain(PARA_ID))); } } pub mod kusama { + /// values of kusama asset_hub is similar to polkadot's asset_hub pub mod asset_hub { - pub const PARA_ID: u32 = 1000; - pub const ASSET_PALLET_ID: u8 = 50; - - pub const USDC_ASSET_ID: u128 = 1337; - pub const USDT_ASSET_ID: u128 = 1984; + pub use super::super::polkadot::asset_hub::*; } } } + +#[cfg(test)] +mod tests { + use super::parachains::polkadot::*; + use xcm::{ + latest::prelude::{AccountKey20, PalletInstance, Parachain}, + prelude::GeneralIndex, + }; + + #[test] + fn test_BRZ() { + let brz_loc = moonbeam::BRZ_location(); + let mut junctions = brz_loc.interior().clone().into_iter(); + + assert_eq!(junctions.next(), Some(Parachain(moonbeam::PARA_ID))); + assert_eq!(junctions.next(), Some(PalletInstance(moonbeam::ASSET_PALLET_INDEX))); + assert_eq!( + junctions.next(), + Some(AccountKey20 { network: None, key: moonbeam::BRZ_ASSET_ACCOUNT_IN_BYTES }) + ); + assert_eq!(junctions.next(), None); + } + + #[test] + fn test_constants() { + let expected_EQ_value = 25_969; + assert_eq!(equilibrium::EQ_ASSET_ID, expected_EQ_value); + + let eq_interior = equilibrium::EQ_location().interior; + let mut junctions = eq_interior.clone().into_iter(); + + assert_eq!(junctions.next(), Some(Parachain(equilibrium::PARA_ID))); + assert_eq!(junctions.next(), Some(PalletInstance(equilibrium::ASSET_PALLET_INDEX))); + assert_eq!(junctions.next(), Some(GeneralIndex(equilibrium::EQ_ASSET_ID))); + assert_eq!(junctions.next(), None); + + let expected_USDT_value = 1984; + assert_eq!(asset_hub::USDT_ASSET_ID, expected_USDT_value); + } +} diff --git a/runtime/common/src/zenlink.rs b/runtime/common/src/zenlink.rs index 128c57ca1..d4ef33fd3 100644 --- a/runtime/common/src/zenlink.rs +++ b/runtime/common/src/zenlink.rs @@ -9,7 +9,7 @@ fn discriminant(currency: &CurrencyId) -> u8 { CurrencyId::XCM(_) => 1, CurrencyId::Stellar(_) => 2, CurrencyId::ZenlinkLPToken(_, _, _, _) => 3, - _=>0 + _ => 0, } } @@ -98,7 +98,7 @@ pub fn currency_id_to_zenlink_id( ((token2_type as u64) << 40); Ok(ZenlinkAssetId { chain_id: parachain_id, asset_type: LOCAL, asset_index: index }) }, - CurrencyId::Token(_)=> Err(()), + CurrencyId::Token(_) => Err(()), } } @@ -235,7 +235,7 @@ mod zenlink_tests { let currency: Result = zenlink_id_to_currency_id(fake_zenlink_asset, 1000u32); let expected_currency: CurrencyId = CurrencyId::ZenlinkLPToken(0, 2, 1, 2); - assert_eq!(currency, Ok(expected_currency)); + assert_eq!(currency, Ok(expected_currency)); } #[test] diff --git a/runtime/foucoco/Cargo.toml b/runtime/foucoco/Cargo.toml index ec638c8f9..68924072b 100644 --- a/runtime/foucoco/Cargo.toml +++ b/runtime/foucoco/Cargo.toml @@ -18,6 +18,7 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex-literal = { version = "0.3.4", optional = true } log = { version = "0.4.17", default-features = false } +paste = "1.0.14" scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.144", optional = true, features = ["derive"] } smallvec = "1.9.0" diff --git a/runtime/foucoco/src/assets.rs b/runtime/foucoco/src/assets.rs new file mode 100644 index 000000000..a29bb7e48 --- /dev/null +++ b/runtime/foucoco/src/assets.rs @@ -0,0 +1,37 @@ +#![allow(non_snake_case)] + +pub mod xcm_assets { + use runtime_common::create_xcm_id; + create_xcm_id!(RELAY, 0); +} + +/// Locations for native currency and all natively issued tokens +pub mod native_locations { + use crate::ParachainInfo; + use frame_support::traits::PalletInfoAccess; + use xcm::latest::{ + Junction::{PalletInstance, Parachain}, + Junctions::{X1, X2}, + MultiLocation, + }; + + fn balances_pallet_id() -> u8 { + crate::Balances::index() as u8 + } + + /// location of the native currency from the point of view of Pendulum parachain + pub fn native_location_local_pov() -> MultiLocation { + MultiLocation { parents: 0, interior: X1(PalletInstance(balances_pallet_id())) } + } + + /// location of the native currency from the point of view of other parachains(external) + pub fn native_location_external_pov() -> MultiLocation { + MultiLocation { + parents: 1, + interior: X2( + Parachain(ParachainInfo::parachain_id().into()), + PalletInstance(balances_pallet_id()), + ), + } + } +} diff --git a/runtime/foucoco/src/lib.rs b/runtime/foucoco/src/lib.rs index b848f4526..1154589e5 100644 --- a/runtime/foucoco/src/lib.rs +++ b/runtime/foucoco/src/lib.rs @@ -6,6 +6,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +mod assets; mod weights; pub mod xcm_config; pub mod zenlink; diff --git a/runtime/foucoco/src/xcm_config.rs b/runtime/foucoco/src/xcm_config.rs index 047a9666f..d04394974 100644 --- a/runtime/foucoco/src/xcm_config.rs +++ b/runtime/foucoco/src/xcm_config.rs @@ -2,6 +2,10 @@ use super::{ AccountId, Balance, Balances, CurrencyId, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, WeightToFee, XcmpQueue, }; +use crate::assets::{ + native_locations::{native_location_external_pov, native_location_local_pov}, + xcm_assets, +}; use core::marker::PhantomData; use frame_support::{ log, match_types, parameter_types, @@ -26,7 +30,6 @@ use xcm_executor::{ traits::{JustTry, ShouldExecute}, XcmExecutor, }; - parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = NetworkId::Rococo; @@ -58,15 +61,11 @@ pub struct CurrencyIdConvert; impl Convert> for CurrencyIdConvert { fn convert(id: CurrencyId) -> Option { match id { - // CurrencyId::KSM => Some(MultiLocation::parent()), CurrencyId::XCM(f) => match f { - 0 => Some(MultiLocation::parent()), + xcm_assets::RELAY => Some(MultiLocation::parent()), _ => None, }, - CurrencyId::Native => Some(MultiLocation::new( - 1, - X2(Parachain(ParachainInfo::parachain_id().into()), PalletInstance(10)), - )), + CurrencyId::Native => Some(native_location_external_pov()), _ => None, } } @@ -75,15 +74,12 @@ impl Convert> for CurrencyIdConvert { impl Convert> for CurrencyIdConvert { fn convert(location: MultiLocation) -> Option { match location { - MultiLocation { parents: 1, interior: Here } => Some(CurrencyId::XCM(0)), + loc if loc == MultiLocation::parent() => Some(xcm_assets::RELAY_id()), // Our native currency location without re-anchoring - MultiLocation { parents: 1, interior: X2(Parachain(id), PalletInstance(10)) } - if id == u32::from(ParachainInfo::parachain_id()) => - Some(CurrencyId::Native), + 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 - MultiLocation { parents: 0, interior: X1(PalletInstance(10)) } => - Some(CurrencyId::Native), + loc if loc == native_location_local_pov() => Some(CurrencyId::Native), _ => None, } } diff --git a/runtime/integration-tests/src/sibling.rs b/runtime/integration-tests/src/sibling.rs index fcca7bdca..2d2f07266 100644 --- a/runtime/integration-tests/src/sibling.rs +++ b/runtime/integration-tests/src/sibling.rs @@ -129,14 +129,7 @@ impl Convert> for CurrencyIdConvert { CurrencyId::XCM(f) => match f { XCM_ASSET_RELAY_DOT => Some(MultiLocation::parent()), // Handles both Kusama and Polkadot asset hub - XCM_ASSET_ASSETHUB_USDT => Some(MultiLocation::new( - 1, - X3( - Parachain(asset_hub::PARA_ID), - PalletInstance(asset_hub::ASSET_PALLET_ID), - GeneralIndex(asset_hub::USDT_ASSET_ID), - ), - )), + XCM_ASSET_ASSETHUB_USDT => Some(asset_hub::USDT_location()), _ => None, }, } @@ -157,15 +150,8 @@ impl Convert> for CurrencyIdConvert { MultiLocation { parents: 0, interior: X1(PalletInstance(10)) } => Some(CurrencyId::Native), // Handles both Kusama and Polkadot asset hub - MultiLocation { - parents: 1, - interior: - X3( - Parachain(asset_hub::PARA_ID), - PalletInstance(asset_hub::ASSET_PALLET_ID), - GeneralIndex(asset_hub::USDT_ASSET_ID), - ), - } => Some(CurrencyId::XCM(XCM_ASSET_ASSETHUB_USDT)), + loc if loc == asset_hub::USDT_location() => + Some(CurrencyId::XCM(XCM_ASSET_ASSETHUB_USDT)), MultiLocation { parents: 1, interior: Here } => Some(CurrencyId::XCM(XCM_ASSET_RELAY_DOT)), _ => None, diff --git a/runtime/pendulum/Cargo.toml b/runtime/pendulum/Cargo.toml index af0f17fc2..c9d28c673 100644 --- a/runtime/pendulum/Cargo.toml +++ b/runtime/pendulum/Cargo.toml @@ -18,6 +18,7 @@ substrate-wasm-builder = {git = "https://github.com/paritytech/substrate", branc codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex-literal = { version = "0.3.4", optional = true } log = { version = "0.4.17", default-features = false } +paste = "1.0.14" scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } serde = { version = "1.0.144", optional = true, features = ["derive"] } smallvec = "1.9.0" diff --git a/runtime/pendulum/src/assets.rs b/runtime/pendulum/src/assets.rs new file mode 100644 index 000000000..a27139983 --- /dev/null +++ b/runtime/pendulum/src/assets.rs @@ -0,0 +1,84 @@ +#![allow(non_snake_case)] + +pub mod xcm_assets { + use runtime_common::create_xcm_id; + + create_xcm_id!(RELAY_DOT, 0); + create_xcm_id!(ASSETHUB_USDT, 1); + create_xcm_id!(ASSETHUB_USDC, 2); + create_xcm_id!(EQUILIBRIUM_EQD, 3); + create_xcm_id!(MOONBEAM_BRZ, 4); + create_xcm_id!(POLKADEX_PDEX, 5); +} + +/// Locations for native currency and all natively issued tokens +pub mod native_locations { + use crate::ParachainInfo; + use frame_support::traits::PalletInfoAccess; + use xcm::latest::{ + Junction::{GeneralIndex, PalletInstance, Parachain}, + Junctions::{X1, X2, X3, X4}, + MultiLocation, + }; + + const TOKEN_IN_CURRENCY_ID: u128 = 4; + + fn tokens_pallet_id() -> u8 { + crate::Tokens::index() as u8 + } + + fn balances_pallet_id() -> u8 { + crate::Balances::index() as u8 + } + + /// location of the native currency from the point of view of Pendulum parachain + pub fn native_location_local_pov() -> MultiLocation { + MultiLocation { parents: 0, interior: X1(PalletInstance(balances_pallet_id())) } + } + + /// location of the native currency from the point of view of other parachains(external) + pub fn native_location_external_pov() -> MultiLocation { + MultiLocation { + parents: 1, + interior: X2( + Parachain(ParachainInfo::parachain_id().into()), + PalletInstance(balances_pallet_id()), + ), + } + } + + /// EURC location from the point of view of Pendulum parachain + pub fn EURC_location_local_pov() -> MultiLocation { + MultiLocation { + parents: 0, + interior: X3( + PalletInstance(tokens_pallet_id()), + GeneralIndex(TOKEN_IN_CURRENCY_ID), // index of the Token variant of CurrencyId enum + GeneralIndex(super::tokens::EURC_TOKEN_INDEX as u128), + ), + } + } + + /// EURC location from the point of view of other parachains(external) + pub fn EURC_location_external_pov() -> MultiLocation { + MultiLocation { + parents: 1, + interior: X4( + Parachain(ParachainInfo::parachain_id().into()), + PalletInstance(tokens_pallet_id()), + GeneralIndex(TOKEN_IN_CURRENCY_ID), + GeneralIndex(super::tokens::EURC_TOKEN_INDEX as u128), + ), + } + } +} + +/// Tokens issued by Pendulum +pub mod tokens { + use spacewalk_primitives::CurrencyId; + + // The index of EURC in the token variant of CurrencyId + pub const EURC_TOKEN_INDEX: u64 = 0; + + pub const EURC_ID: CurrencyId = CurrencyId::Token(EURC_TOKEN_INDEX); +} diff --git a/runtime/pendulum/src/lib.rs b/runtime/pendulum/src/lib.rs index 2b86a70f1..08686ab63 100644 --- a/runtime/pendulum/src/lib.rs +++ b/runtime/pendulum/src/lib.rs @@ -6,9 +6,11 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +mod assets; mod weights; pub mod xcm_config; pub mod zenlink; + use crate::zenlink::*; use xcm::v3::MultiLocation; use zenlink_protocol::{AssetBalance, MultiAssetsHandler, PairInfo}; diff --git a/runtime/pendulum/src/xcm_config.rs b/runtime/pendulum/src/xcm_config.rs index 03c1ede01..fbaa589fb 100644 --- a/runtime/pendulum/src/xcm_config.rs +++ b/runtime/pendulum/src/xcm_config.rs @@ -2,7 +2,17 @@ use super::{ AccountId, Balance, Balances, CurrencyId, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens, WeightToFee, XcmpQueue, }; -use crate::ConstU32; +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 core::marker::PhantomData; use frame_support::{ log, match_types, parameter_types, @@ -15,7 +25,7 @@ use orml_traits::{ use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; -use runtime_common::parachains::polkadot::asset_hub; +use runtime_common::parachains::polkadot::{asset_hub, equilibrium, moonbeam, polkadex}; use sp_runtime::traits::Convert; use xcm::latest::{prelude::*, Weight as XCMWeight}; use xcm_builder::{ @@ -29,9 +39,6 @@ use xcm_executor::{ XcmExecutor, }; -const XCM_ASSET_RELAY_DOT: u8 = 0; -const XCM_ASSET_ASSETHUB_USDT: u8 = 1; - parameter_types! { pub const RelayLocation: MultiLocation = MultiLocation::parent(); pub const RelayNetwork: NetworkId = NetworkId::Polkadot; @@ -39,7 +46,6 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); pub UniversalLocation: InteriorMultiLocation = X2(GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())); - } /// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used @@ -63,23 +69,18 @@ pub struct CurrencyIdConvert; impl Convert> for CurrencyIdConvert { fn convert(id: CurrencyId) -> Option { match id { - // CurrencyId::KSM => Some(MultiLocation::parent()), CurrencyId::XCM(f) => match f { - XCM_ASSET_RELAY_DOT => Some(MultiLocation::parent()), - XCM_ASSET_ASSETHUB_USDT => Some(MultiLocation::new( - 1, - X3( - Parachain(asset_hub::PARA_ID), - PalletInstance(asset_hub::ASSET_PALLET_ID), - GeneralIndex(asset_hub::USDT_ASSET_ID), - ), - )), + 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()), _ => None, }, - CurrencyId::Native => Some(MultiLocation::new( - 1, - X2(Parachain(ParachainInfo::parachain_id().into()), PalletInstance(10)), - )), + + CurrencyId::Native => Some(native_location_external_pov()), + assets::tokens::EURC_ID => Some(EURC_location_external_pov()), _ => None, } } @@ -88,25 +89,21 @@ impl Convert> for CurrencyIdConvert { impl Convert> for CurrencyIdConvert { fn convert(location: MultiLocation) -> Option { match location { - MultiLocation { parents: 1, interior: Here } => - Some(CurrencyId::XCM(XCM_ASSET_RELAY_DOT)), - MultiLocation { - parents: 1, - interior: - X3( - Parachain(asset_hub::PARA_ID), - PalletInstance(asset_hub::ASSET_PALLET_ID), - GeneralIndex(asset_hub::USDT_ASSET_ID), - ), - } => Some(CurrencyId::XCM(XCM_ASSET_ASSETHUB_USDT)), + 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()), + // Our native currency location without re-anchoring - MultiLocation { parents: 1, interior: X2(Parachain(id), PalletInstance(10)) } - if id == u32::from(ParachainInfo::parachain_id()) => - Some(CurrencyId::Native), + 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 - MultiLocation { parents: 0, interior: X1(PalletInstance(10)) } => - Some(CurrencyId::Native), + 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, } }