Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

relay account and tests #651

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
22 changes: 22 additions & 0 deletions xcm-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use xcm_executor::traits::{FilterAssetLocation, MatchesFungible};
use orml_traits::location::Reserve;

pub use currency_adapter::MultiCurrencyAdapter;
use frame_support::pallet_prelude::Get;

mod currency_adapter;

Expand Down Expand Up @@ -75,3 +76,24 @@ impl UnknownAsset for () {
Err(DispatchError::Other(NO_UNKNOWN_ASSET_IMPL))
}
}

/// Extracts the `AccountId32` from the passed `location` if the network matches.
pub struct RelaychainAccountId32Aliases<Network, AccountId>(PhantomData<(Network, AccountId)>);
zqhxuyuan marked this conversation as resolved.
Show resolved Hide resolved
impl<Network: Get<NetworkId>, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone>
xcm_executor::traits::Convert<MultiLocation, AccountId> for RelaychainAccountId32Aliases<Network, AccountId>
{
fn convert(location: MultiLocation) -> Result<AccountId, MultiLocation> {
let id = match location {
zqhxuyuan marked this conversation as resolved.
Show resolved Hide resolved
MultiLocation {
parents: 1,
interior: X1(AccountId32 { id, network: NetworkId::Any }),
} => id,
_ => return Err(location),
};
Ok(id.into())
}

fn reverse(who: AccountId) -> Result<MultiLocation, AccountId> {
Ok(AccountId32 { id: who.into(), network: Network::get() }.into())
}
}
38 changes: 34 additions & 4 deletions xtokens/src/mock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,40 @@ use sp_io::TestExternalities;
use sp_runtime::AccountId32;

use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain};
use cumulus_primitives_core::ParaId;
use polkadot_parachain::primitives::{AccountIdConversion, Sibling};

pub mod para;
pub mod relay;
pub mod tests;

pub const ALICE: AccountId32 = AccountId32::new([0u8; 32]);
pub const BOB: AccountId32 = AccountId32::new([1u8; 32]);
pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]);
pub const BOB: AccountId32 = AccountId32::new([2u8; 32]);
pub const GOD: AccountId32 = AccountId32::new([0u8; 32]);
pub const INITIAL_BALANCE: u128 = 1_000;

pub fn para_a_account() -> AccountId32 {
ParaId::from(1).into_account()
}

pub fn para_b_account() -> AccountId32 {
ParaId::from(2).into_account()
}

pub fn sibling_a_account() -> AccountId32 {
use sp_runtime::traits::AccountIdConversion;
Sibling::from(1).into_account()
}

pub fn sibling_b_account() -> AccountId32 {
use sp_runtime::traits::AccountIdConversion;
Sibling::from(2).into_account()
}

pub fn sibling_c_account() -> AccountId32 {
use sp_runtime::traits::AccountIdConversion;
Sibling::from(3).into_account()
}

#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, RuntimeDebug, PartialOrd, Ord, TypeInfo)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
Expand Down Expand Up @@ -118,6 +146,8 @@ decl_test_network! {
}

pub type RelayBalances = pallet_balances::Pallet<relay::Runtime>;
pub type ParaBalances = pallet_balances::Pallet<para::Runtime>;

pub type ParaTokens = orml_tokens::Pallet<para::Runtime>;
pub type ParaXTokens = orml_xtokens::Pallet<para::Runtime>;

Expand All @@ -135,7 +165,7 @@ pub fn para_ext(para_id: u32) -> TestExternalities {
.unwrap();

orml_tokens::GenesisConfig::<Runtime> {
balances: vec![(ALICE, CurrencyId::R, 1_000)],
balances: vec![(ALICE, CurrencyId::R, INITIAL_BALANCE)],
}
.assimilate_storage(&mut t)
.unwrap();
Expand All @@ -153,7 +183,7 @@ pub fn relay_ext() -> sp_io::TestExternalities {
.unwrap();

pallet_balances::GenesisConfig::<Runtime> {
balances: vec![(ALICE, 1_000)],
balances: vec![(ALICE, INITIAL_BALANCE)],
}
.assimilate_storage(&mut t)
.unwrap();
Expand Down
3 changes: 2 additions & 1 deletion xtokens/src/mock/para.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use xcm_builder::{
use xcm_executor::{traits::WeightTrader, Assets, Config, XcmExecutor};

use orml_traits::parameter_type_with_key;
use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset};
use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, RelaychainAccountId32Aliases};

pub type AccountId = AccountId32;

Expand Down Expand Up @@ -114,6 +114,7 @@ pub type LocationToAccountId = (
ParentIsDefault<AccountId>,
SiblingParachainConvertsVia<Sibling, AccountId>,
AccountId32Aliases<RelayNetwork, AccountId>,
RelaychainAccountId32Aliases<RelayNetwork, AccountId>,
);

pub type XcmOriginToCallOrigin = (
Expand Down
204 changes: 204 additions & 0 deletions xtokens/src/mock/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#![cfg(test)]
zqhxuyuan marked this conversation as resolved.
Show resolved Hide resolved

use super::*;
use super::para::AccountIdToMultiLocation;
use orml_traits::{MultiCurrency};
use xcm_simulator::TestExt;
use xcm_builder::{IsConcrete};
use crate::mock::relay::KsmLocation;
use xcm_executor::traits::MatchesFungible;
use crate::mock::para::RelayLocation;

#[test]
fn test_init_balance() {
Relay::execute_with(|| {
assert_eq!(RelayBalances::free_balance(&ALICE), INITIAL_BALANCE);
assert_eq!(RelayBalances::free_balance(&BOB), 0);
assert_eq!(RelayBalances::free_balance(&para_a_account()), 0);
assert_eq!(RelayBalances::free_balance(&para_b_account()), 0);
});

ParaA::execute_with(|| {
assert_eq!(ParaTokens::free_balance(CurrencyId::R, &ALICE), INITIAL_BALANCE);
assert_eq!(ParaTokens::free_balance(CurrencyId::R, &BOB), 0);

assert_eq!(ParaTokens::free_balance(CurrencyId::A, &ALICE), 0);
assert_eq!(ParaTokens::free_balance(CurrencyId::B, &ALICE), 0);

assert_eq!(ParaBalances::free_balance(&ALICE), 0);
assert_eq!(ParaBalances::free_balance(&BOB), 0);
assert_eq!(ParaBalances::free_balance(&sibling_b_account()), 0);
assert_eq!(ParaBalances::free_balance(&sibling_c_account()), 0);
});

ParaB::execute_with(|| {
assert_eq!(ParaTokens::free_balance(CurrencyId::R, &ALICE), INITIAL_BALANCE);
assert_eq!(ParaTokens::free_balance(CurrencyId::R, &BOB), 0);
});
}

#[test]
fn test_asset_matches_fungible() {
// use raw way: VersionedMultiAssets -> MultiAssets -> Vec<MultiAsset>
// `KsmLocation` in `relay.rs` is `Here`
let assets: VersionedMultiAssets = (Here, 100u128).into();
let assets: MultiAssets = assets.try_into().unwrap();
let assets: Vec<MultiAsset> = assets.drain();
for asset in assets {
let assets: u128 = IsConcrete::<KsmLocation>::matches_fungible(&asset.clone()).unwrap_or_default();
assert_eq!(assets, 100u128);
}

// use convenient way, `KsmLocation` in `relay.rs` is `Here`
let asset: MultiAsset = (Here, 100u128).into();
let amount: u128 = IsConcrete::<KsmLocation>::matches_fungible(&asset.clone()).unwrap_or_default();
assert_eq!(amount, 100u128);

// the first parameter is not equal to `Here`, which not match `KsmLocation`, so asset match result is `0`
let asset: MultiAsset = (X1(Parachain(1)), 100u128).into();
let assets: u128 = IsConcrete::<KsmLocation>::matches_fungible(&asset.clone()).unwrap_or_default();
assert_eq!(assets, 0);

// `RelayLocation` in `para.rs` is `Parent`
let asset: MultiAsset = (Parent, 100u128).into();
let assets: u128 = IsConcrete::<RelayLocation>::matches_fungible(&asset.clone()).unwrap_or_default();
assert_eq!(assets, 100);
}

#[test]
fn test_account_location_convert() {
let account = Junction::AccountId32 {
network: NetworkId::Any,
id: ALICE.into()
};

let origin_location = AccountIdToMultiLocation::convert(ALICE);
let junction: Junctions = origin_location.try_into().unwrap();
assert_eq!(junction, X1(account.clone()));

let parent: MultiLocation = Parent.into();
assert_eq!(parent.parents, 1);
assert_eq!(parent.interior, Here);
assert_eq!(parent.contains_parents_only(1), true);

let destination: MultiLocation = MultiLocation::new(
1,
X2(
Parachain(2),
account.clone(),
)
).into();
assert_eq!(destination.parents, 1);
assert_eq!(destination.interior, X2(Parachain(2), account.clone()));

let destination: MultiLocation = (
Parent,
Parachain(2),
account.clone(),
).into();
assert_eq!(destination.parents, 1);
assert_eq!(destination.interior, X2(Parachain(2), account.clone()));

let destination: MultiLocation = (
Parent,
account.clone()
).into();
assert_eq!(destination.parents, 1);
assert_eq!(destination.interior, X1(account.clone()));

let destination: MultiLocation = (
Parachain(2),
account.clone()
).into();
assert_eq!(destination.parents, 0);
assert_eq!(destination.interior, X2(Parachain(2), account.clone()));

let junction = X1(account.clone());
let mut destination: MultiLocation = Parent.into();
destination.append_with(junction).unwrap();
assert_eq!(destination.parents, 1);
assert_eq!(destination.interior, X1(account.clone()));
}

#[test]
fn test_parachain_convert_location_to_account() {
use xcm_executor::traits::Convert;

// ParentIsDefault
let parent: MultiLocation = Parent.into();
let account = para::LocationToAccountId::convert(parent);
assert_eq!(account, Ok(GOD));

// SiblingParachainConvertsVia
let destination: MultiLocation = (
Parent,
Parachain(1),
).into();
let account = para::LocationToAccountId::convert(destination);
assert_eq!(account, Ok(sibling_a_account()));

let alice = Junction::AccountId32 {
network: NetworkId::Any,
id: ALICE.into()
};

// AccountId32Aliases
let destination: MultiLocation = (
alice.clone()
).into();
let account = para::LocationToAccountId::convert(destination);
assert_eq!(account, Ok(ALICE));

// RelaychainAccountId32Aliases
let destination: MultiLocation = (
Parent,
alice.clone()
).into();
let account = para::LocationToAccountId::convert(destination);
assert_eq!(account, Ok(ALICE));

// Error case
let destination: MultiLocation = (
Parent,
Parachain(1),
alice.clone()
).into();
let account = para::LocationToAccountId::convert(destination.clone());
assert_eq!(account, Err(destination));
}

#[test]
fn test_relaychain_convert_location_to_account() {
use xcm_executor::traits::Convert;

// ChildParachainConvertsVia
let destination: MultiLocation = (
Parachain(1),
).into();
let account = relay::SovereignAccountOf::convert(destination);
assert_eq!(account, Ok(para_a_account()));

let alice = Junction::AccountId32 {
network: NetworkId::Any,
id: ALICE.into()
};

let alice_unknown_network = Junction::AccountId32 {
network: NetworkId::Polkadot,
id: ALICE.into()
};

// AccountId32Aliases
let destination: MultiLocation = (
alice.clone()
).into();
let account = relay::SovereignAccountOf::convert(destination);
assert_eq!(account, Ok(ALICE));

// AccountId32Aliases with unknown-network location
let destination: MultiLocation = (
alice_unknown_network.clone()
).into();
let account = relay::SovereignAccountOf::convert(destination.clone());
assert_eq!(account, Err(destination));
}
27 changes: 0 additions & 27 deletions xtokens/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,11 @@
#![cfg(test)]

use super::*;
use codec::Encode;
use cumulus_primitives_core::ParaId;
use frame_support::{assert_err, assert_noop, assert_ok, traits::Currency};
use mock::*;
use orml_traits::{ConcreteFungibleAsset, MultiCurrency};
use polkadot_parachain::primitives::{AccountIdConversion, Sibling};
use sp_runtime::AccountId32;
use xcm_simulator::TestExt;

fn para_a_account() -> AccountId32 {
ParaId::from(1).into_account()
}

fn para_b_account() -> AccountId32 {
ParaId::from(2).into_account()
}

fn sibling_a_account() -> AccountId32 {
use sp_runtime::traits::AccountIdConversion;
Sibling::from(1).into_account()
}

fn sibling_b_account() -> AccountId32 {
use sp_runtime::traits::AccountIdConversion;
Sibling::from(2).into_account()
}

fn sibling_c_account() -> AccountId32 {
use sp_runtime::traits::AccountIdConversion;
Sibling::from(3).into_account()
}

// Not used in any unit tests, but it's super helpful for debugging. Let's
// keep it here.
#[allow(dead_code)]
Expand Down