From 7421f97b0078b894e1f983b8050a16643f731002 Mon Sep 17 00:00:00 2001 From: zqh Date: Wed, 10 Nov 2021 17:20:44 +0800 Subject: [PATCH 01/16] relay account and tests --- xcm-support/src/lib.rs | 22 ++++ xtokens/src/mock/mod.rs | 38 ++++++- xtokens/src/mock/para.rs | 3 +- xtokens/src/mock/tests.rs | 204 ++++++++++++++++++++++++++++++++++++++ xtokens/src/tests.rs | 27 ----- 5 files changed, 262 insertions(+), 32 deletions(-) create mode 100644 xtokens/src/mock/tests.rs diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 2a68197e5..a39d1365e 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -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; @@ -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(PhantomData<(Network, AccountId)>); +impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone> +xcm_executor::traits::Convert for RelaychainAccountId32Aliases +{ + fn convert(location: MultiLocation) -> Result { + let id = match location { + MultiLocation { + parents: 1, + interior: X1(AccountId32 { id, network: NetworkId::Any }), + } => id, + _ => return Err(location), + }; + Ok(id.into()) + } + + fn reverse(who: AccountId) -> Result { + Ok(AccountId32 { id: who.into(), network: Network::get() }.into()) + } +} \ No newline at end of file diff --git a/xtokens/src/mock/mod.rs b/xtokens/src/mock/mod.rs index 35291882f..00aa7490c 100644 --- a/xtokens/src/mock/mod.rs +++ b/xtokens/src/mock/mod.rs @@ -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))] @@ -118,6 +146,8 @@ decl_test_network! { } pub type RelayBalances = pallet_balances::Pallet; +pub type ParaBalances = pallet_balances::Pallet; + pub type ParaTokens = orml_tokens::Pallet; pub type ParaXTokens = orml_xtokens::Pallet; @@ -135,7 +165,7 @@ pub fn para_ext(para_id: u32) -> TestExternalities { .unwrap(); orml_tokens::GenesisConfig:: { - balances: vec![(ALICE, CurrencyId::R, 1_000)], + balances: vec![(ALICE, CurrencyId::R, INITIAL_BALANCE)], } .assimilate_storage(&mut t) .unwrap(); @@ -153,7 +183,7 @@ pub fn relay_ext() -> sp_io::TestExternalities { .unwrap(); pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, 1_000)], + balances: vec![(ALICE, INITIAL_BALANCE)], } .assimilate_storage(&mut t) .unwrap(); diff --git a/xtokens/src/mock/para.rs b/xtokens/src/mock/para.rs index 0c67e974a..3934a403d 100644 --- a/xtokens/src/mock/para.rs +++ b/xtokens/src/mock/para.rs @@ -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; @@ -114,6 +114,7 @@ pub type LocationToAccountId = ( ParentIsDefault, SiblingParachainConvertsVia, AccountId32Aliases, + RelaychainAccountId32Aliases, ); pub type XcmOriginToCallOrigin = ( diff --git a/xtokens/src/mock/tests.rs b/xtokens/src/mock/tests.rs new file mode 100644 index 000000000..6995b7e98 --- /dev/null +++ b/xtokens/src/mock/tests.rs @@ -0,0 +1,204 @@ +#![cfg(test)] + +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(¶_a_account()), 0); + assert_eq!(RelayBalances::free_balance(¶_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 + // `KsmLocation` in `relay.rs` is `Here` + let assets: VersionedMultiAssets = (Here, 100u128).into(); + let assets: MultiAssets = assets.try_into().unwrap(); + let assets: Vec = assets.drain(); + for asset in assets { + let assets: u128 = IsConcrete::::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::::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::::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::::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)); +} diff --git a/xtokens/src/tests.rs b/xtokens/src/tests.rs index ba2540dfd..be2c8ca78 100644 --- a/xtokens/src/tests.rs +++ b/xtokens/src/tests.rs @@ -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)] From 514566b329be2d87adf2091416a4d18146e41d6d Mon Sep 17 00:00:00 2001 From: zqh Date: Thu, 11 Nov 2021 08:20:29 +0800 Subject: [PATCH 02/16] convert origin unit test --- xtokens/src/mock/tests.rs | 94 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/xtokens/src/mock/tests.rs b/xtokens/src/mock/tests.rs index 6995b7e98..0d8dd46b1 100644 --- a/xtokens/src/mock/tests.rs +++ b/xtokens/src/mock/tests.rs @@ -5,8 +5,9 @@ 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::relay::KsmLocation; use crate::mock::para::RelayLocation; #[test] @@ -54,7 +55,7 @@ fn test_asset_matches_fungible() { let amount: u128 = IsConcrete::::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` + // `KsmLocation` in `relay.rs` is `Here` let asset: MultiAsset = (X1(Parachain(1)), 100u128).into(); let assets: u128 = IsConcrete::::matches_fungible(&asset.clone()).unwrap_or_default(); assert_eq!(assets, 0); @@ -157,7 +158,7 @@ fn test_parachain_convert_location_to_account() { let account = para::LocationToAccountId::convert(destination); assert_eq!(account, Ok(ALICE)); - // Error case + // Error case 1: ../Parachain/Account let destination: MultiLocation = ( Parent, Parachain(1), @@ -165,6 +166,13 @@ fn test_parachain_convert_location_to_account() { ).into(); let account = para::LocationToAccountId::convert(destination.clone()); assert_eq!(account, Err(destination)); + + // Error case 2: ./Parachain + let destination: MultiLocation = ( + Parachain(1), + ).into(); + let account = para::LocationToAccountId::convert(destination.clone()); + assert_eq!(account, Err(destination)); } #[test] @@ -202,3 +210,83 @@ fn test_relaychain_convert_location_to_account() { let account = relay::SovereignAccountOf::convert(destination.clone()); assert_eq!(account, Err(destination)); } + +#[test] +fn test_parachain_convert_origin() { + use xcm_executor::traits::ConvertOrigin; + + let alice = Junction::AccountId32 { + network: NetworkId::Any, + id: ALICE.into() + }; + + // SovereignSignedViaLocation + let destination: MultiLocation = Parent.into(); + let origin = para::XcmOriginToCallOrigin::convert_origin( + destination.clone(), OriginKind::SovereignAccount); + assert!(origin.is_ok()); + + // SovereignSignedViaLocation + let destination: MultiLocation = ( + Parent, + Parachain(1), + ).into(); + let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::SovereignAccount); + assert!(origin.is_ok()); + + // SovereignSignedViaLocation + let destination: MultiLocation = ( + alice.clone() + ).into(); + let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::SovereignAccount); + assert!(origin.is_ok()); + + // SovereignSignedViaLocation + let destination: MultiLocation = ( + Parent, + alice.clone() + ).into(); + let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::SovereignAccount); + assert!(origin.is_ok()); + + // SovereignSignedViaLocation Error case + let destination: MultiLocation = ( + Parent, + Parachain(1), + alice.clone() + ).into(); + let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::SovereignAccount); + assert!(origin.is_err()); + + // RelayChainAsNative + let destination: MultiLocation = Parent.into(); + let origin = para::XcmOriginToCallOrigin::convert_origin( + destination.clone(), OriginKind::Native); + assert!(origin.is_ok()); + + // SiblingParachainAsNative + let destination: MultiLocation = ( + Parent, + Parachain(1), + ).into(); + let origin = para::XcmOriginToCallOrigin::convert_origin( + destination.clone(), OriginKind::Native); + assert!(origin.is_ok()); + + // SignedAccountId32AsNative + let destination: MultiLocation = ( + alice.clone() + ).into(); + let origin = para::XcmOriginToCallOrigin::convert_origin( + destination.clone(), OriginKind::Native); + assert!(origin.is_ok()); + + // XcmPassthrough + let destination: MultiLocation = ( + Parent, + alice.clone() + ).into(); + let origin = para::XcmOriginToCallOrigin::convert_origin( + destination.clone(), OriginKind::Xcm); + assert!(origin.is_ok()); +} \ No newline at end of file From 1f7d92a8f75329fd057cfe8399413f8cded4ed5b Mon Sep 17 00:00:00 2001 From: zqh Date: Thu, 11 Nov 2021 18:42:53 +0800 Subject: [PATCH 03/16] add AllowDescendOrigin and integration test --- xcm-support/src/lib.rs | 65 +++++- xtokens/Cargo.toml | 2 + xtokens/src/mock/mod.rs | 7 +- xtokens/src/mock/para.rs | 10 +- xtokens/src/mock/tests.rs | 481 +++++++++++++++++--------------------- xtokens/src/tests.rs | 123 ++++++++++ 6 files changed, 415 insertions(+), 273 deletions(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index a39d1365e..418c4fa01 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -10,11 +10,13 @@ #![allow(clippy::unused_unit)] use frame_support::dispatch::{DispatchError, DispatchResult}; +use frame_support::{ensure, traits::Contains, weights::Weight}; + use sp_runtime::traits::{CheckedConversion, Convert}; use sp_std::{convert::TryFrom, marker::PhantomData, prelude::*}; use xcm::latest::prelude::*; -use xcm_executor::traits::{FilterAssetLocation, MatchesFungible}; +use xcm_executor::traits::{FilterAssetLocation, MatchesFungible, ShouldExecute}; use orml_traits::location::Reserve; @@ -77,16 +79,20 @@ impl UnknownAsset for () { } } -/// Extracts the `AccountId32` from the passed `location` if the network matches. +/// Extracts the `AccountId32` from the passed `location` if the network +/// matches. pub struct RelaychainAccountId32Aliases(PhantomData<(Network, AccountId)>); impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone> -xcm_executor::traits::Convert for RelaychainAccountId32Aliases + xcm_executor::traits::Convert for RelaychainAccountId32Aliases { fn convert(location: MultiLocation) -> Result { let id = match location { MultiLocation { parents: 1, - interior: X1(AccountId32 { id, network: NetworkId::Any }), + interior: X1(AccountId32 { + id, + network: NetworkId::Any, + }), } => id, _ => return Err(location), }; @@ -94,6 +100,53 @@ xcm_executor::traits::Convert for RelaychainAccountId3 } fn reverse(who: AccountId) -> Result { - Ok(AccountId32 { id: who.into(), network: Network::get() }.into()) + Ok(AccountId32 { + id: who.into(), + network: Network::get(), + } + .into()) + } +} + +pub struct AllowDescendOrigin(PhantomData); +impl> ShouldExecute for AllowDescendOrigin { + fn should_execute( + origin: &MultiLocation, + message: &mut Xcm, + max_weight: Weight, + _weight_credit: &mut Weight, + ) -> Result<(), ()> { + ensure!(T::contains(origin), ()); + let mut iter = message.0.iter_mut(); + let i = iter.next().ok_or(())?; + match i { + DescendOrigin(..) => (), + _ => return Err(()), + } + let i = iter.next().ok_or(())?; + match i { + ReceiveTeleportedAsset(..) | WithdrawAsset(..) | ReserveAssetDeposited(..) | ClaimAsset { .. } => (), + _ => return Err(()), + } + let mut i = iter.next().ok_or(())?; + while let ClearOrigin = i { + i = iter.next().ok_or(())?; + } + match i { + BuyExecution { + weight_limit: Limited(ref mut weight), + .. + } if *weight >= max_weight => { + *weight = max_weight; + Ok(()) + } + BuyExecution { + ref mut weight_limit, .. + } if weight_limit == &Unlimited => { + *weight_limit = Limited(max_weight); + Ok(()) + } + _ => Err(()), + } } -} \ No newline at end of file +} diff --git a/xtokens/Cargo.toml b/xtokens/Cargo.toml index f93ad8cf6..b61b7f83d 100644 --- a/xtokens/Cargo.toml +++ b/xtokens/Cargo.toml @@ -49,6 +49,8 @@ xcm-simulator = { git = "https://github.com/paritytech/polkadot", branch = "rele orml-tokens = { path = "../tokens" } orml-xcm = { path = "../xcm" } +env_logger = "0.8.3" + [features] default = ["std"] std = [ diff --git a/xtokens/src/mock/mod.rs b/xtokens/src/mock/mod.rs index 00aa7490c..bf84ccde3 100644 --- a/xtokens/src/mock/mod.rs +++ b/xtokens/src/mock/mod.rs @@ -8,9 +8,9 @@ use serde::{Deserialize, Serialize}; 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}; +use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain}; pub mod para; pub mod relay; @@ -18,7 +18,7 @@ pub mod tests; 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 DEFAULT: AccountId32 = AccountId32::new([0u8; 32]); pub const INITIAL_BALANCE: u128 = 1_000; pub fn para_a_account() -> AccountId32 { @@ -151,6 +151,9 @@ pub type ParaBalances = pallet_balances::Pallet; pub type ParaTokens = orml_tokens::Pallet; pub type ParaXTokens = orml_xtokens::Pallet; +pub type RelayChainPalletXcm = pallet_xcm::Pallet; +pub type ParachainPalletXcm = pallet_xcm::Pallet; + pub fn para_ext(para_id: u32) -> TestExternalities { use para::{Runtime, System}; diff --git a/xtokens/src/mock/para.rs b/xtokens/src/mock/para.rs index 3934a403d..016fab07e 100644 --- a/xtokens/src/mock/para.rs +++ b/xtokens/src/mock/para.rs @@ -26,7 +26,9 @@ 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, RelaychainAccountId32Aliases}; +use orml_xcm_support::{ + AllowDescendOrigin, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, RelaychainAccountId32Aliases, +}; pub type AccountId = AccountId32; @@ -141,7 +143,11 @@ pub type LocalAssetTransactor = MultiCurrencyAdapter< >; pub type XcmRouter = ParachainXcmRouter; -pub type Barrier = (TakeWeightCredit, AllowTopLevelPaidExecutionFrom); +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + AllowDescendOrigin, +); /// A trader who believes all tokens are created equal to "weight" of any chain, /// which is not true, but good enough to mock the fee payment of XCM execution. diff --git a/xtokens/src/mock/tests.rs b/xtokens/src/mock/tests.rs index 0d8dd46b1..f07cd57d6 100644 --- a/xtokens/src/mock/tests.rs +++ b/xtokens/src/mock/tests.rs @@ -1,292 +1,247 @@ #![cfg(test)] -use super::*; use super::para::AccountIdToMultiLocation; -use orml_traits::{MultiCurrency}; -use xcm_simulator::TestExt; -use xcm_builder::{IsConcrete}; +use super::*; +use orml_traits::MultiCurrency; +use xcm_builder::IsConcrete; use xcm_executor::traits::MatchesFungible; +use xcm_simulator::TestExt; -use crate::mock::relay::KsmLocation; use crate::mock::para::RelayLocation; +use crate::mock::relay::KsmLocation; #[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(¶_a_account()), 0); - assert_eq!(RelayBalances::free_balance(¶_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); - }); + Relay::execute_with(|| { + assert_eq!(RelayBalances::free_balance(&ALICE), INITIAL_BALANCE); + assert_eq!(RelayBalances::free_balance(&BOB), 0); + assert_eq!(RelayBalances::free_balance(¶_a_account()), 0); + assert_eq!(RelayBalances::free_balance(¶_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 - // `KsmLocation` in `relay.rs` is `Here` - let assets: VersionedMultiAssets = (Here, 100u128).into(); - let assets: MultiAssets = assets.try_into().unwrap(); - let assets: Vec = assets.drain(); - for asset in assets { - let assets: u128 = IsConcrete::::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::::matches_fungible(&asset.clone()).unwrap_or_default(); - assert_eq!(amount, 100u128); - - // `KsmLocation` in `relay.rs` is `Here` - let asset: MultiAsset = (X1(Parachain(1)), 100u128).into(); - let assets: u128 = IsConcrete::::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::::matches_fungible(&asset.clone()).unwrap_or_default(); - assert_eq!(assets, 100); + // use raw way: VersionedMultiAssets -> MultiAssets -> Vec + // `KsmLocation` in `relay.rs` is `Here` + let assets: VersionedMultiAssets = (Here, 100u128).into(); + let assets: MultiAssets = assets.try_into().unwrap(); + let assets: Vec = assets.drain(); + for asset in assets { + let assets: u128 = IsConcrete::::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::::matches_fungible(&asset.clone()).unwrap_or_default(); + assert_eq!(amount, 100u128); + + // `KsmLocation` in `relay.rs` is `Here` + let asset: MultiAsset = (X1(Parachain(1)), 100u128).into(); + let assets: u128 = IsConcrete::::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::::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())); + 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 1: ../Parachain/Account - let destination: MultiLocation = ( - Parent, - Parachain(1), - alice.clone() - ).into(); - let account = para::LocationToAccountId::convert(destination.clone()); - assert_eq!(account, Err(destination)); - - // Error case 2: ./Parachain - let destination: MultiLocation = ( - Parachain(1), - ).into(); - let account = para::LocationToAccountId::convert(destination.clone()); - assert_eq!(account, Err(destination)); + use xcm_executor::traits::Convert; + + // ParentIsDefault + let parent: MultiLocation = Parent.into(); + let account = para::LocationToAccountId::convert(parent); + assert_eq!(account, Ok(DEFAULT)); + + // 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 1: ../Parachain/Account + let destination: MultiLocation = (Parent, Parachain(1), alice.clone()).into(); + let account = para::LocationToAccountId::convert(destination.clone()); + assert_eq!(account, Err(destination)); + + // Error case 2: ./Parachain + let destination: MultiLocation = (Parachain(1),).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)); + 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_on_dot = 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_on_dot.clone()).into(); + let account = relay::SovereignAccountOf::convert(destination.clone()); + assert_eq!(account, Err(destination)); } #[test] fn test_parachain_convert_origin() { - use xcm_executor::traits::ConvertOrigin; - - let alice = Junction::AccountId32 { - network: NetworkId::Any, - id: ALICE.into() - }; - - // SovereignSignedViaLocation - let destination: MultiLocation = Parent.into(); - let origin = para::XcmOriginToCallOrigin::convert_origin( - destination.clone(), OriginKind::SovereignAccount); - assert!(origin.is_ok()); - - // SovereignSignedViaLocation - let destination: MultiLocation = ( - Parent, - Parachain(1), - ).into(); - let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::SovereignAccount); - assert!(origin.is_ok()); - - // SovereignSignedViaLocation - let destination: MultiLocation = ( - alice.clone() - ).into(); - let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::SovereignAccount); - assert!(origin.is_ok()); - - // SovereignSignedViaLocation - let destination: MultiLocation = ( - Parent, - alice.clone() - ).into(); - let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::SovereignAccount); - assert!(origin.is_ok()); - - // SovereignSignedViaLocation Error case - let destination: MultiLocation = ( - Parent, - Parachain(1), - alice.clone() - ).into(); - let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::SovereignAccount); - assert!(origin.is_err()); - - // RelayChainAsNative - let destination: MultiLocation = Parent.into(); - let origin = para::XcmOriginToCallOrigin::convert_origin( - destination.clone(), OriginKind::Native); - assert!(origin.is_ok()); - - // SiblingParachainAsNative - let destination: MultiLocation = ( - Parent, - Parachain(1), - ).into(); - let origin = para::XcmOriginToCallOrigin::convert_origin( - destination.clone(), OriginKind::Native); - assert!(origin.is_ok()); - - // SignedAccountId32AsNative - let destination: MultiLocation = ( - alice.clone() - ).into(); - let origin = para::XcmOriginToCallOrigin::convert_origin( - destination.clone(), OriginKind::Native); - assert!(origin.is_ok()); - - // XcmPassthrough - let destination: MultiLocation = ( - Parent, - alice.clone() - ).into(); - let origin = para::XcmOriginToCallOrigin::convert_origin( - destination.clone(), OriginKind::Xcm); - assert!(origin.is_ok()); -} \ No newline at end of file + use xcm_executor::traits::ConvertOrigin; + + let alice = Junction::AccountId32 { + network: NetworkId::Any, + id: ALICE.into(), + }; + let alice_on_dot = Junction::AccountId32 { + network: NetworkId::Polkadot, + id: ALICE.into(), + }; + + // supported destination convert with OriginKind::SovereignAccount + let supported_sovereign_account_destination: Vec = vec![ + // ParentIsDefault: parent default account can be kind of sovereign account + Parent.into(), + // SiblingParachainConvertsVia: sibling parachain can be kind of sovereign account + (Parent, Parachain(1)).into(), + // AccountId32Aliases: current chain's account can be kind of sovereign account + (alice.clone()).into(), + // RelaychainAccountId32Aliases: relaychain's account can be kind of sovereign account(xcm-support feature) + (Parent, alice.clone()).into(), + ]; + + // unsupported destination convert with OriginKind::SovereignAccount + let unsupported_sovereign_account_destination: Vec = vec![ + // sibling parachain's account can't be kind of sovereign account + (Parent, Parachain(1), alice.clone()).into(), + // relaychain's account with unmatched network can't be kind of sovereign account + (Parent, alice_on_dot.clone()).into(), + ]; + + for destination in supported_sovereign_account_destination { + let origin = para::XcmOriginToCallOrigin::convert_origin(destination, OriginKind::SovereignAccount); + assert!(origin.is_ok()); + } + for destination in unsupported_sovereign_account_destination { + let origin = para::XcmOriginToCallOrigin::convert_origin(destination, OriginKind::SovereignAccount); + assert!(origin.is_err()); + } + + let supported_native_destination: Vec = vec![ + // RelayChainAsNative + Parent.into(), + // SiblingParachainAsNative + (Parent, Parachain(1)).into(), + // SignedAccountId32AsNative + (alice.clone()).into(), + ]; + + let unsupported_native_destination: Vec = vec![ + (Parent, Parachain(1), alice.clone()).into(), + (Parent, alice.clone()).into(), + ]; + + for destination in supported_native_destination { + let origin = para::XcmOriginToCallOrigin::convert_origin(destination, OriginKind::Native); + assert!(origin.is_ok()); + } + for destination in unsupported_native_destination { + let origin = para::XcmOriginToCallOrigin::convert_origin(destination, OriginKind::Native); + assert!(origin.is_err()); + } + + // XcmPassthrough + let destination: MultiLocation = (Parent, Parachain(1), alice.clone()).into(); + let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::Xcm); + assert!(origin.is_ok()); +} diff --git a/xtokens/src/tests.rs b/xtokens/src/tests.rs index be2c8ca78..d96249d89 100644 --- a/xtokens/src/tests.rs +++ b/xtokens/src/tests.rs @@ -404,6 +404,129 @@ fn send_as_sovereign_fails_if_bad_origin() { }); } +#[test] +fn para_transact_sovereign_account() { + TestNet::reset(); + + Relay::execute_with(|| { + let _ = RelayBalances::deposit_creating(¶_a_account(), 1_000_000_000_000); + }); + + ParaA::execute_with(|| { + let call = + relay::Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); + let assets: MultiAsset = (Here, 1_000_000_000_000).into(); + assert_ok!(ParachainPalletXcm::send_xcm( + Here, + Parent, + Xcm(vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(2_000_000_000) + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 1_000_000_000 as u64, + call: call.encode().into(), + }, + ]), + )); + }); + + Relay::execute_with(|| { + use relay::{Event, System}; + assert!(System::events() + .iter() + .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); + }); +} + +#[test] +fn relay_transact_default_sovereign_account() { + TestNet::reset(); + + ParaA::execute_with(|| { + assert_ok!(ParaTokens::deposit(CurrencyId::R, &DEFAULT, 10_000_000_000_000)); + }); + + relaychain_transact_to_parachain(Here, 1_000_000_000_000); + + ParaA::execute_with(|| { + use para::{Event, System}; + assert!(System::events() + .iter() + .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); + }); +} + +#[test] +fn relay_transact_normal_account() { + TestNet::reset(); + + ParaA::execute_with(|| { + assert_ok!(ParaTokens::deposit(CurrencyId::R, &ALICE, 1_000_000_000_000)); + assert_eq!(1_000_000_001_000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + }); + + let alice = Junctions::X1(Junction::AccountId32 { + network: NetworkId::Any, + id: ALICE.into(), + }); + relaychain_transact_to_parachain(alice.clone(), 1_000_000_000_000); + + ParaA::execute_with(|| { + assert_eq!(1000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + use para::{Event, System}; + assert!(System::events() + .iter() + .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); + }); + + relaychain_transact_to_parachain(alice.clone(), 100); + + ParaA::execute_with(|| { + assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + use para::{Event, System}; + assert!(System::events() + .iter() + .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); + }); + + relaychain_transact_to_parachain(alice, 1000); + + ParaA::execute_with(|| { + assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + use para::{Event, System}; + assert!(System::events() + .iter() + .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); + }); +} + +fn relaychain_transact_to_parachain(junctions: Junctions, amount: u128) { + Relay::execute_with(|| { + let call = para::Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); + let assets: MultiAsset = (Parent, amount).into(); + assert_ok!(RelayChainPalletXcm::send_xcm( + junctions, + Parachain(1).into(), + Xcm(vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(2_000_000_000) + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 1_000_000_000 as u64, + call: call.encode().into(), + }, + ]), + )); + }); +} + #[test] fn call_size_limit() { // Ensures Call enum doesn't allocate more than 200 bytes in runtime From d132663ff161ca112b5f124411c75ee7f8bb4b1a Mon Sep 17 00:00:00 2001 From: zqh Date: Thu, 11 Nov 2021 23:42:25 +0800 Subject: [PATCH 04/16] sibling parachain test --- xtokens/src/tests.rs | 73 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/xtokens/src/tests.rs b/xtokens/src/tests.rs index d96249d89..3f750138a 100644 --- a/xtokens/src/tests.rs +++ b/xtokens/src/tests.rs @@ -405,9 +405,7 @@ fn send_as_sovereign_fails_if_bad_origin() { } #[test] -fn para_transact_sovereign_account() { - TestNet::reset(); - +fn para_transact_to_relay_use_sovereign_account() { Relay::execute_with(|| { let _ = RelayBalances::deposit_creating(¶_a_account(), 1_000_000_000_000); }); @@ -443,9 +441,7 @@ fn para_transact_sovereign_account() { } #[test] -fn relay_transact_default_sovereign_account() { - TestNet::reset(); - +fn relay_transact_to_para_use_default_sovereign_account() { ParaA::execute_with(|| { assert_ok!(ParaTokens::deposit(CurrencyId::R, &DEFAULT, 10_000_000_000_000)); }); @@ -461,9 +457,7 @@ fn relay_transact_default_sovereign_account() { } #[test] -fn relay_transact_normal_account() { - TestNet::reset(); - +fn relay_transact_to_para_use_normal_account() { ParaA::execute_with(|| { assert_ok!(ParaTokens::deposit(CurrencyId::R, &ALICE, 1_000_000_000_000)); assert_eq!(1_000_000_001_000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); @@ -476,8 +470,8 @@ fn relay_transact_normal_account() { relaychain_transact_to_parachain(alice.clone(), 1_000_000_000_000); ParaA::execute_with(|| { - assert_eq!(1000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); use para::{Event, System}; + assert_eq!(1000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); assert!(System::events() .iter() .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); @@ -486,8 +480,8 @@ fn relay_transact_normal_account() { relaychain_transact_to_parachain(alice.clone(), 100); ParaA::execute_with(|| { - assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); use para::{Event, System}; + assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); assert!(System::events() .iter() .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); @@ -496,14 +490,48 @@ fn relay_transact_normal_account() { relaychain_transact_to_parachain(alice, 1000); ParaA::execute_with(|| { + use para::{Event, System}; assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + assert!(System::events() + .iter() + .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); + }); +} + +#[test] +fn para_transact_to_sibling_use_sovereign_account() { + ParaB::execute_with(|| { + assert_ok!(ParaTokens::deposit( + CurrencyId::R, + &sibling_a_account(), + 1_000_000_000_000 + )); + }); + + parachain_transact_to_sibling(Here, 1_000_000_000_000); + + ParaB::execute_with(|| { use para::{Event, System}; + assert_eq!(0, ParaTokens::free_balance(CurrencyId::R, &sibling_a_account())); assert!(System::events() .iter() .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); }); } +#[test] +fn para_transact_to_sibling_use_account_failed() { + let alice = Junctions::X1(Junction::AccountId32 { + network: NetworkId::Any, + id: ALICE.into(), + }); + + // the origin of WithdrawAsset in the context of destination parachain is + // (Parent, Parachain(1), Alice) and it get error when convert + // LocationToAccountId + parachain_transact_to_sibling(alice, 1_000_000_000_000); +} + fn relaychain_transact_to_parachain(junctions: Junctions, amount: u128) { Relay::execute_with(|| { let call = para::Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); @@ -527,6 +555,29 @@ fn relaychain_transact_to_parachain(junctions: Junctions, amount: u128) { }); } +fn parachain_transact_to_sibling(junctions: Junctions, amount: u128) { + ParaA::execute_with(|| { + let call = para::Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); + let assets: MultiAsset = (Parent, amount).into(); + assert_ok!(ParachainPalletXcm::send_xcm( + junctions, + (Parent, Parachain(2)), + Xcm(vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(2_000_000_000) + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 1_000_000_000 as u64, + call: call.encode().into(), + }, + ]) + )); + }); +} + #[test] fn call_size_limit() { // Ensures Call enum doesn't allocate more than 200 bytes in runtime From f4162e30e05ef6d3f89b78e8816b6beb96c7dce8 Mon Sep 17 00:00:00 2001 From: zqh Date: Fri, 12 Nov 2021 08:15:50 +0800 Subject: [PATCH 05/16] add doc --- xcm-support/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 418c4fa01..7bebd5a00 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -108,6 +108,11 @@ impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone } } +/// when Relay an XCM message from a given `interior` location, if the given +/// `interior` is not `Here`, the destination will receive a xcm message +/// beginning with `DescendOrigin` as the first instruction. the implementation +/// of `AllowDescendOrigin` is first allow `DescendOrigin` pass through, and +/// then the remaining process is same as `AllowTopLevelPaidExecutionFrom`. pub struct AllowDescendOrigin(PhantomData); impl> ShouldExecute for AllowDescendOrigin { fn should_execute( From ced4d674a907a571c8cad46a3e6420150504ebcb Mon Sep 17 00:00:00 2001 From: zqh Date: Fri, 12 Nov 2021 18:00:41 +0800 Subject: [PATCH 06/16] add transfer test and change to AllowEquivalentAccountsFrom --- xcm-support/src/lib.rs | 35 +++-- xtokens/src/mock/para.rs | 4 +- xtokens/src/mock/tests.rs | 68 +++++++++ xtokens/src/tests.rs | 287 ++++++++++++++++++++++++++++---------- 4 files changed, 298 insertions(+), 96 deletions(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 7bebd5a00..56c9a7b74 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -110,11 +110,11 @@ impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone /// when Relay an XCM message from a given `interior` location, if the given /// `interior` is not `Here`, the destination will receive a xcm message -/// beginning with `DescendOrigin` as the first instruction. the implementation -/// of `AllowDescendOrigin` is first allow `DescendOrigin` pass through, and -/// then the remaining process is same as `AllowTopLevelPaidExecutionFrom`. -pub struct AllowDescendOrigin(PhantomData); -impl> ShouldExecute for AllowDescendOrigin { +/// beginning with `DescendOrigin` as the first instruction. so the xcm message +/// format must match this order: +/// `DescendOrigin`,`WithdrawAsset`,`BuyExecution`,`Transact`. +pub struct AllowEquivalentAccountsFrom(PhantomData); +impl> ShouldExecute for AllowEquivalentAccountsFrom { fn should_execute( origin: &MultiLocation, message: &mut Xcm, @@ -130,28 +130,27 @@ impl> ShouldExecute for AllowDescendOrigin { } let i = iter.next().ok_or(())?; match i { - ReceiveTeleportedAsset(..) | WithdrawAsset(..) | ReserveAssetDeposited(..) | ClaimAsset { .. } => (), + WithdrawAsset(..) => (), _ => return Err(()), } - let mut i = iter.next().ok_or(())?; - while let ClearOrigin = i { - i = iter.next().ok_or(())?; - } + let i = iter.next().ok_or(())?; match i { BuyExecution { weight_limit: Limited(ref mut weight), .. } if *weight >= max_weight => { *weight = max_weight; - Ok(()) + () } - BuyExecution { - ref mut weight_limit, .. - } if weight_limit == &Unlimited => { - *weight_limit = Limited(max_weight); - Ok(()) - } - _ => Err(()), + _ => return Err(()), + } + let i = iter.next().ok_or(())?; + match i { + Transact { + origin_type: OriginKind::SovereignAccount, + .. + } => Ok(()), + _ => return Err(()), } } } diff --git a/xtokens/src/mock/para.rs b/xtokens/src/mock/para.rs index 016fab07e..ee38c7536 100644 --- a/xtokens/src/mock/para.rs +++ b/xtokens/src/mock/para.rs @@ -27,7 +27,7 @@ use xcm_executor::{traits::WeightTrader, Assets, Config, XcmExecutor}; use orml_traits::parameter_type_with_key; use orml_xcm_support::{ - AllowDescendOrigin, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, RelaychainAccountId32Aliases, + AllowEquivalentAccountsFrom, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, RelaychainAccountId32Aliases, }; pub type AccountId = AccountId32; @@ -146,7 +146,7 @@ pub type XcmRouter = ParachainXcmRouter; pub type Barrier = ( TakeWeightCredit, AllowTopLevelPaidExecutionFrom, - AllowDescendOrigin, + AllowEquivalentAccountsFrom, ); /// A trader who believes all tokens are created equal to "weight" of any chain, diff --git a/xtokens/src/mock/tests.rs b/xtokens/src/mock/tests.rs index f07cd57d6..b62a5934c 100644 --- a/xtokens/src/mock/tests.rs +++ b/xtokens/src/mock/tests.rs @@ -245,3 +245,71 @@ fn test_parachain_convert_origin() { let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::Xcm); assert!(origin.is_ok()); } + +#[test] +fn test_call_weight_info() { + use frame_support::weights::GetDispatchInfo; + use para::{Call, Runtime}; + + let expect_weight: u64 = 6000; + let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); + + let weight = call.get_dispatch_info().weight; + assert_eq!(weight, expect_weight); + + let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); + let weight = call.get_dispatch_info().weight; + assert_eq!(weight, expect_weight); + + let call = Call::Balances(pallet_balances::Call::::transfer { dest: BOB, value: 100 }); + let weight = call.get_dispatch_info().weight; + assert_eq!(weight, 195952000); +} + +#[test] +fn test_parachain_weigher_calculate() { + use frame_support::weights::GetDispatchInfo; + use para::{Call, Runtime, XcmConfig}; + + let expect_weight: u64 = 195952000; + let call = Call::Balances(pallet_balances::Call::::transfer { dest: BOB, value: 100 }); + + let weight = call.get_dispatch_info().weight; + assert_eq!(weight, expect_weight); + + let assets: MultiAsset = (Parent, 1).into(); + + let instructions = vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets.clone(), + weight_limit: Limited(1), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: expect_weight, + call: call.encode().into(), + }, + ]; + let xcm_weight = ::Weigher::weight(&mut Xcm(instructions)); + assert_eq!(xcm_weight.unwrap(), expect_weight + 30); + + let instructions = vec![ + DescendOrigin(Junctions::X1(Junction::AccountId32 { + network: NetworkId::Any, + id: [0; 32], + })), + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(1), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: expect_weight, + call: call.encode().into(), + }, + ]; + let xcm_weight = ::Weigher::weight(&mut Xcm(instructions)); + assert_eq!(xcm_weight.unwrap(), expect_weight + 40); +} diff --git a/xtokens/src/tests.rs b/xtokens/src/tests.rs index 3f750138a..ea8d368a6 100644 --- a/xtokens/src/tests.rs +++ b/xtokens/src/tests.rs @@ -405,31 +405,13 @@ fn send_as_sovereign_fails_if_bad_origin() { } #[test] -fn para_transact_to_relay_use_sovereign_account() { +fn para_transact_to_relay_remark_use_sovereign_account() { Relay::execute_with(|| { - let _ = RelayBalances::deposit_creating(¶_a_account(), 1_000_000_000_000); + let _ = RelayBalances::deposit_creating(¶_a_account(), 6030); }); ParaA::execute_with(|| { - let call = - relay::Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); - let assets: MultiAsset = (Here, 1_000_000_000_000).into(); - assert_ok!(ParachainPalletXcm::send_xcm( - Here, - Parent, - Xcm(vec![ - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets, - weight_limit: Limited(2_000_000_000) - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 1_000_000_000 as u64, - call: call.encode().into(), - }, - ]), - )); + parachain_transact_to_relaychian_remark(); }); Relay::execute_with(|| { @@ -441,12 +423,12 @@ fn para_transact_to_relay_use_sovereign_account() { } #[test] -fn relay_transact_to_para_use_default_sovereign_account() { +fn relay_transact_to_para_remark_use_default_sovereign_account() { ParaA::execute_with(|| { - assert_ok!(ParaTokens::deposit(CurrencyId::R, &DEFAULT, 10_000_000_000_000)); + assert_ok!(ParaTokens::deposit(CurrencyId::R, &DEFAULT, 6030)); }); - relaychain_transact_to_parachain(Here, 1_000_000_000_000); + relaychain_transact_to_parachain_remark(Here, 6030); ParaA::execute_with(|| { use para::{Event, System}; @@ -457,17 +439,17 @@ fn relay_transact_to_para_use_default_sovereign_account() { } #[test] -fn relay_transact_to_para_use_normal_account() { +fn relay_transact_to_para_remark_use_normal_account() { ParaA::execute_with(|| { - assert_ok!(ParaTokens::deposit(CurrencyId::R, &ALICE, 1_000_000_000_000)); - assert_eq!(1_000_000_001_000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + assert_ok!(ParaTokens::deposit(CurrencyId::R, &ALICE, 6040)); + assert_eq!(7040, ParaTokens::free_balance(CurrencyId::R, &ALICE)); }); let alice = Junctions::X1(Junction::AccountId32 { network: NetworkId::Any, id: ALICE.into(), }); - relaychain_transact_to_parachain(alice.clone(), 1_000_000_000_000); + relaychain_transact_to_parachain_remark(alice.clone(), 6040); ParaA::execute_with(|| { use para::{Event, System}; @@ -477,7 +459,7 @@ fn relay_transact_to_para_use_normal_account() { .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); }); - relaychain_transact_to_parachain(alice.clone(), 100); + relaychain_transact_to_parachain_remark(alice.clone(), 100); ParaA::execute_with(|| { use para::{Event, System}; @@ -487,7 +469,7 @@ fn relay_transact_to_para_use_normal_account() { .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); }); - relaychain_transact_to_parachain(alice, 1000); + relaychain_transact_to_parachain_remark(alice, 1000); ParaA::execute_with(|| { use para::{Event, System}; @@ -499,16 +481,56 @@ fn relay_transact_to_para_use_normal_account() { } #[test] -fn para_transact_to_sibling_use_sovereign_account() { +fn relay_transact_to_para_transfer_use_normal_account() { + ParaA::execute_with(|| { + assert_ok!(ParaTokens::deposit(CurrencyId::R, &ALICE, 195952040)); + assert_eq!(195953040, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + let _ = ParaBalances::deposit_creating(&ALICE, 1_000); + assert_eq!(1000, ParaBalances::free_balance(&ALICE)); + }); + + let alice = Junctions::X1(Junction::AccountId32 { + network: NetworkId::Any, + id: ALICE.into(), + }); + relaychain_transact_to_parachain_transfer(alice.clone(), 195952040); + + ParaA::execute_with(|| { + use para::{Event, System}; + assert_eq!(1000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + assert!(System::events() + .iter() + .any(|r| matches!(r.event, Event::Balances(pallet_balances::Event::Transfer(_, _, _))))); + }); + + relaychain_transact_to_parachain_transfer(alice.clone(), 100); + + ParaA::execute_with(|| { + use para::{Event, System}; + assert_eq!(900, ParaBalances::free_balance(&ALICE)); + assert!(System::events() + .iter() + .any(|r| matches!(r.event, Event::Balances(pallet_balances::Event::Transfer(_, _, _))))); + }); + + relaychain_transact_to_parachain_transfer(alice, 1000); + + ParaA::execute_with(|| { + use para::{Event, System}; + assert_eq!(900, ParaBalances::free_balance(&ALICE)); + assert!(System::events() + .iter() + .any(|r| matches!(r.event, Event::Balances(pallet_balances::Event::Transfer(_, _, _))))); + }); +} + +#[test] +fn para_transact_to_sibling_remark_use_sovereign_account() { ParaB::execute_with(|| { - assert_ok!(ParaTokens::deposit( - CurrencyId::R, - &sibling_a_account(), - 1_000_000_000_000 - )); + assert_ok!(ParaTokens::deposit(CurrencyId::R, &sibling_a_account(), 6030)); }); - parachain_transact_to_sibling(Here, 1_000_000_000_000); + parachain_transact_to_sibling_remark(Here, 6030); ParaB::execute_with(|| { use para::{Event, System}; @@ -520,60 +542,173 @@ fn para_transact_to_sibling_use_sovereign_account() { } #[test] -fn para_transact_to_sibling_use_account_failed() { +fn para_transact_to_sibling_remark_use_account_failed() { + let alice = Junctions::X1(Junction::AccountId32 { + network: NetworkId::Any, + id: ALICE.into(), + }); + + // the origin of `WithdrawAsset` in the context of destination parachain is + // `(Parent, Parachain(1), Alice)` and it get error when convert by + // `LocationToAccountId`. + parachain_transact_to_sibling_remark(alice, 6040); + + ParaB::execute_with(|| { + use para::{Event, System}; + assert_eq!( + System::events() + .iter() + .find(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _)))), + None + ); + }); +} + +#[test] +fn relay_transact_to_para_use_wrong_kind() { + ParaA::execute_with(|| { + assert_ok!(ParaTokens::deposit(CurrencyId::R, &DEFAULT, 6040)); + }); + + use para::{Call, Runtime}; + let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); + let assets: MultiAsset = (Parent, 6040).into(); let alice = Junctions::X1(Junction::AccountId32 { network: NetworkId::Any, id: ALICE.into(), }); - // the origin of WithdrawAsset in the context of destination parachain is - // (Parent, Parachain(1), Alice) and it get error when convert - // LocationToAccountId - parachain_transact_to_sibling(alice, 1_000_000_000_000); + Relay::execute_with(|| { + let xcm = vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(6040), + }, + Transact { + origin_type: OriginKind::Native, + require_weight_at_most: 6000 as u64, + call: call.encode().into(), + }, + ]; + assert_ok!(RelayChainPalletXcm::send_xcm(alice, Parachain(1).into(), Xcm(xcm),)); + }); + + ParaA::execute_with(|| { + use para::{Event, System}; + assert_eq!( + System::events() + .iter() + .find(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _)))), + None + ); + }); } -fn relaychain_transact_to_parachain(junctions: Junctions, amount: u128) { +fn relaychain_transact_to_parachain_remark(junctions: Junctions, amount: u128) { + use para::{Call, Runtime}; + let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); + let assets: MultiAsset = (Parent, amount).into(); + + let limit: u64 = match junctions { + Here => 6030, + _ => 6040, + }; + Relay::execute_with(|| { - let call = para::Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); - let assets: MultiAsset = (Parent, amount).into(); - assert_ok!(RelayChainPalletXcm::send_xcm( - junctions, - Parachain(1).into(), - Xcm(vec![ - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets, - weight_limit: Limited(2_000_000_000) - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 1_000_000_000 as u64, - call: call.encode().into(), - }, - ]), - )); + let xcm = vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(limit), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 6000 as u64, + call: call.encode().into(), + }, + ]; + assert_ok!(RelayChainPalletXcm::send_xcm(junctions, Parachain(1).into(), Xcm(xcm),)); + }); +} + +fn relaychain_transact_to_parachain_transfer(junctions: Junctions, amount: u128) { + use para::{Call, Runtime}; + let call = Call::Balances(pallet_balances::Call::::transfer { dest: BOB, value: 100 }); + let assets: MultiAsset = (Parent, amount).into(); + + let limit: u64 = match junctions { + Here => 195952000 + 30, + _ => 195952000 + 40, + }; + + Relay::execute_with(|| { + let xcm = vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(limit), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 195952000 as u64, + call: call.encode().into(), + }, + ]; + assert_ok!(RelayChainPalletXcm::send_xcm(junctions, Parachain(1).into(), Xcm(xcm),)); }); } -fn parachain_transact_to_sibling(junctions: Junctions, amount: u128) { +fn parachain_transact_to_relaychian_remark() { + use relay::{Call, Runtime}; + let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); + let assets: MultiAsset = (Here, 6030).into(); + + assert_ok!(ParachainPalletXcm::send_xcm( + Here, + Parent, + Xcm(vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(6030) + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 6000 as u64, + call: call.encode().into(), + }, + ]), + )); +} + +fn parachain_transact_to_sibling_remark(junctions: Junctions, amount: u128) { + use relay::{Call, Runtime}; + let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); + let assets: MultiAsset = (Parent, amount).into(); + let limit: u64 = match junctions { + Here => 6030, + _ => 6040, + }; + ParaA::execute_with(|| { - let call = para::Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); - let assets: MultiAsset = (Parent, amount).into(); + let xcm = vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(limit), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 6000 as u64, + call: call.encode().into(), + }, + ]; + assert_ok!(ParachainPalletXcm::send_xcm( junctions, (Parent, Parachain(2)), - Xcm(vec![ - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets, - weight_limit: Limited(2_000_000_000) - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 1_000_000_000 as u64, - call: call.encode().into(), - }, - ]) + Xcm(xcm) )); }); } From cbb494466732b612b92982bf6e858f0c9a9f2e49 Mon Sep 17 00:00:00 2001 From: zqh Date: Fri, 12 Nov 2021 19:35:48 +0800 Subject: [PATCH 07/16] clippy --- xcm-support/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 56c9a7b74..0173bb157 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -150,7 +150,7 @@ impl> ShouldExecute for AllowEquivalentAccountsFrom Ok(()), - _ => return Err(()), + _ => Err(()), } } } From c3b4d7d586d04eb62f9b15d3cdced6d1328e20c1 Mon Sep 17 00:00:00 2001 From: zqh Date: Sat, 13 Nov 2021 22:57:04 +0800 Subject: [PATCH 08/16] fix test --- xcm-support/src/lib.rs | 20 ++++++------ xtokens/src/mock/tests.rs | 49 ++++++++++++++++++++++++++++-- xtokens/src/tests.rs | 64 ++++++++++++++++++--------------------- 3 files changed, 86 insertions(+), 47 deletions(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 0173bb157..4f6cbd984 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -89,22 +89,22 @@ impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone let id = match location { MultiLocation { parents: 1, - interior: X1(AccountId32 { - id, - network: NetworkId::Any, - }), - } => id, + interior: X1(AccountId32 { id, network }), + } if network == Network::get() => id, _ => return Err(location), }; Ok(id.into()) } fn reverse(who: AccountId) -> Result { - Ok(AccountId32 { - id: who.into(), - network: Network::get(), - } - .into()) + Ok(( + 1, + AccountId32 { + id: who.into(), + network: Network::get(), + }, + ) + .into()) } } diff --git a/xtokens/src/mock/tests.rs b/xtokens/src/mock/tests.rs index b62a5934c..a2d00fd23 100644 --- a/xtokens/src/mock/tests.rs +++ b/xtokens/src/mock/tests.rs @@ -4,11 +4,12 @@ use super::para::AccountIdToMultiLocation; use super::*; use orml_traits::MultiCurrency; use xcm_builder::IsConcrete; -use xcm_executor::traits::MatchesFungible; +use xcm_executor::traits::{MatchesFungible, WeightTrader}; use xcm_simulator::TestExt; use crate::mock::para::RelayLocation; use crate::mock::relay::KsmLocation; +use xcm_executor::Assets; #[test] fn test_init_balance() { @@ -120,7 +121,7 @@ fn test_parachain_convert_location_to_account() { assert_eq!(account, Ok(sibling_a_account())); let alice = Junction::AccountId32 { - network: NetworkId::Any, + network: NetworkId::Kusama, id: ALICE.into(), }; @@ -180,6 +181,10 @@ fn test_parachain_convert_origin() { use xcm_executor::traits::ConvertOrigin; let alice = Junction::AccountId32 { + network: NetworkId::Kusama, + id: ALICE.into(), + }; + let alice_any = Junction::AccountId32 { network: NetworkId::Any, id: ALICE.into(), }; @@ -202,6 +207,8 @@ fn test_parachain_convert_origin() { // unsupported destination convert with OriginKind::SovereignAccount let unsupported_sovereign_account_destination: Vec = vec![ + // network not matched can't be kind of sovereign account + (Parent, alice_any.clone()).into(), // sibling parachain's account can't be kind of sovereign account (Parent, Parachain(1), alice.clone()).into(), // relaychain's account with unmatched network can't be kind of sovereign account @@ -264,6 +271,18 @@ fn test_call_weight_info() { let call = Call::Balances(pallet_balances::Call::::transfer { dest: BOB, value: 100 }); let weight = call.get_dispatch_info().weight; assert_eq!(weight, 195952000); + + let call_para = Call::Balances(pallet_balances::Call::::transfer { dest: BOB, value: 100 }); + let call_relay = relay::Call::XcmPallet(pallet_xcm::Call::::send { + dest: Box::new(VersionedMultiLocation::V1(Parachain(2).into())), + message: Box::new(VersionedXcm::from(Xcm(vec![Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 1000, + call: call_para.encode().into(), + }]))), + }); + let weight = call_relay.get_dispatch_info().weight; + assert_eq!(weight, 100000000); } #[test] @@ -313,3 +332,29 @@ fn test_parachain_weigher_calculate() { let xcm_weight = ::Weigher::weight(&mut Xcm(instructions)); assert_eq!(xcm_weight.unwrap(), expect_weight + 40); } + +#[test] +fn test_trader() { + use para::XcmConfig; + + let asset: MultiAsset = (Parent, 1000).into(); + + let mut holding = Assets::new(); + holding.subsume(asset.clone()); + + let backup = holding.clone(); + + let fees: MultiAsset = (Parent, 1000).into(); + let max_fee = holding.try_take(fees.into()).unwrap(); + + assert_eq!(holding.is_empty(), true); + assert_eq!(max_fee, backup); + + let mut trader = para::AllTokensAreCreatedEqualToWeight::new(); + let result = ::Trader::buy_weight(&mut trader, 1000, max_fee.clone()); + assert_eq!(result.is_ok(), true); + assert_eq!(result.unwrap().is_empty(), true); + + let result = ::Trader::buy_weight(&mut trader, 2000, max_fee); + assert_eq!(result.is_err(), true); +} diff --git a/xtokens/src/tests.rs b/xtokens/src/tests.rs index ea8d368a6..3a495ad4e 100644 --- a/xtokens/src/tests.rs +++ b/xtokens/src/tests.rs @@ -446,7 +446,7 @@ fn relay_transact_to_para_remark_use_normal_account() { }); let alice = Junctions::X1(Junction::AccountId32 { - network: NetworkId::Any, + network: NetworkId::Kusama, id: ALICE.into(), }); relaychain_transact_to_parachain_remark(alice.clone(), 6040); @@ -457,26 +457,19 @@ fn relay_transact_to_para_remark_use_normal_account() { assert!(System::events() .iter() .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); + System::reset_events(); }); - relaychain_transact_to_parachain_remark(alice.clone(), 100); ParaA::execute_with(|| { use para::{Event, System}; assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); - }); - - relaychain_transact_to_parachain_remark(alice, 1000); - - ParaA::execute_with(|| { - use para::{Event, System}; - assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); + assert_eq!( + System::events() + .iter() + .find(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _)))), + None + ); }); } @@ -490,37 +483,35 @@ fn relay_transact_to_para_transfer_use_normal_account() { }); let alice = Junctions::X1(Junction::AccountId32 { - network: NetworkId::Any, + network: NetworkId::Kusama, id: ALICE.into(), }); - relaychain_transact_to_parachain_transfer(alice.clone(), 195952040); + relaychain_transact_to_parachain_transfer(alice.clone(), 195952040, 500); ParaA::execute_with(|| { use para::{Event, System}; assert_eq!(1000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + assert_eq!(500, ParaBalances::free_balance(&ALICE)); + assert_eq!(500, ParaBalances::free_balance(&BOB)); assert!(System::events() .iter() .any(|r| matches!(r.event, Event::Balances(pallet_balances::Event::Transfer(_, _, _))))); + System::reset_events(); }); - relaychain_transact_to_parachain_transfer(alice.clone(), 100); - - ParaA::execute_with(|| { - use para::{Event, System}; - assert_eq!(900, ParaBalances::free_balance(&ALICE)); - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::Balances(pallet_balances::Event::Transfer(_, _, _))))); - }); - - relaychain_transact_to_parachain_transfer(alice, 1000); + relaychain_transact_to_parachain_transfer(alice.clone(), 100, 100); ParaA::execute_with(|| { use para::{Event, System}; - assert_eq!(900, ParaBalances::free_balance(&ALICE)); - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::Balances(pallet_balances::Event::Transfer(_, _, _))))); + assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); + assert_eq!(500, ParaBalances::free_balance(&ALICE)); + assert_eq!(500, ParaBalances::free_balance(&BOB)); + assert_eq!( + System::events() + .iter() + .find(|r| matches!(r.event, Event::Balances(pallet_balances::Event::Transfer(_, _, _)))), + None + ); }); } @@ -565,7 +556,7 @@ fn para_transact_to_sibling_remark_use_account_failed() { } #[test] -fn relay_transact_to_para_use_wrong_kind() { +fn relay_transact_to_para_unsupport_kind_failed() { ParaA::execute_with(|| { assert_ok!(ParaTokens::deposit(CurrencyId::R, &DEFAULT, 6040)); }); @@ -632,9 +623,12 @@ fn relaychain_transact_to_parachain_remark(junctions: Junctions, amount: u128) { }); } -fn relaychain_transact_to_parachain_transfer(junctions: Junctions, amount: u128) { +fn relaychain_transact_to_parachain_transfer(junctions: Junctions, amount: u128, transfer_amount: u128) { use para::{Call, Runtime}; - let call = Call::Balances(pallet_balances::Call::::transfer { dest: BOB, value: 100 }); + let call = Call::Balances(pallet_balances::Call::::transfer { + dest: BOB, + value: transfer_amount, + }); let assets: MultiAsset = (Parent, amount).into(); let limit: u64 = match junctions { From 61d40f5bdac0900c0654413e42ed185edc0648bf Mon Sep 17 00:00:00 2001 From: zqh Date: Sun, 14 Nov 2021 23:38:39 +0800 Subject: [PATCH 09/16] allow network any --- xcm-support/src/lib.rs | 7 +++++++ xtokens/src/mock/tests.rs | 3 +-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 4f6cbd984..82d282656 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -87,6 +87,13 @@ impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone { fn convert(location: MultiLocation) -> Result { let id = match location { + MultiLocation { + parents: 1, + interior: X1(AccountId32 { + id, + network: NetworkId::Any, + }), + } => id, MultiLocation { parents: 1, interior: X1(AccountId32 { id, network }), diff --git a/xtokens/src/mock/tests.rs b/xtokens/src/mock/tests.rs index a2d00fd23..094f4ad49 100644 --- a/xtokens/src/mock/tests.rs +++ b/xtokens/src/mock/tests.rs @@ -203,12 +203,11 @@ fn test_parachain_convert_origin() { (alice.clone()).into(), // RelaychainAccountId32Aliases: relaychain's account can be kind of sovereign account(xcm-support feature) (Parent, alice.clone()).into(), + (Parent, alice_any.clone()).into(), ]; // unsupported destination convert with OriginKind::SovereignAccount let unsupported_sovereign_account_destination: Vec = vec![ - // network not matched can't be kind of sovereign account - (Parent, alice_any.clone()).into(), // sibling parachain's account can't be kind of sovereign account (Parent, Parachain(1), alice.clone()).into(), // relaychain's account with unmatched network can't be kind of sovereign account From 1cb1abfb98818e5a802a86b3d7a72cae35bfb85d Mon Sep 17 00:00:00 2001 From: zqh Date: Tue, 16 Nov 2021 10:34:33 +0800 Subject: [PATCH 10/16] add IsParent --- xcm-support/src/lib.rs | 19 ++++++++++++++++--- xtokens/src/mock/para.rs | 5 +++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 82d282656..057e47b18 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -115,13 +115,22 @@ impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone } } +pub struct IsParent; +impl Contains for IsParent { + fn contains(l: &MultiLocation) -> bool { + l.contains_parents_only(1) + } +} + /// when Relay an XCM message from a given `interior` location, if the given /// `interior` is not `Here`, the destination will receive a xcm message /// beginning with `DescendOrigin` as the first instruction. so the xcm message /// format must match this order: /// `DescendOrigin`,`WithdrawAsset`,`BuyExecution`,`Transact`. -pub struct AllowEquivalentAccountsFrom(PhantomData); -impl> ShouldExecute for AllowEquivalentAccountsFrom { +pub struct AllowEquivalentParentAccountsFrom(PhantomData<(T, Network)>); +impl, Network: Get> ShouldExecute + for AllowEquivalentParentAccountsFrom +{ fn should_execute( origin: &MultiLocation, message: &mut Xcm, @@ -132,7 +141,11 @@ impl> ShouldExecute for AllowEquivalentAccountsFrom (), + DescendOrigin(X1(Junction::AccountId32 { + network: NetworkId::Any, + .. + })) => (), + DescendOrigin(X1(Junction::AccountId32 { network, .. })) if network == &Network::get() => (), _ => return Err(()), } let i = iter.next().ok_or(())?; diff --git a/xtokens/src/mock/para.rs b/xtokens/src/mock/para.rs index ee38c7536..0eea55c02 100644 --- a/xtokens/src/mock/para.rs +++ b/xtokens/src/mock/para.rs @@ -27,7 +27,8 @@ use xcm_executor::{traits::WeightTrader, Assets, Config, XcmExecutor}; use orml_traits::parameter_type_with_key; use orml_xcm_support::{ - AllowEquivalentAccountsFrom, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, RelaychainAccountId32Aliases, + AllowEquivalentParentAccountsFrom, IsNativeConcrete, IsParent, MultiCurrencyAdapter, MultiNativeAsset, + RelaychainAccountId32Aliases, }; pub type AccountId = AccountId32; @@ -146,7 +147,7 @@ pub type XcmRouter = ParachainXcmRouter; pub type Barrier = ( TakeWeightCredit, AllowTopLevelPaidExecutionFrom, - AllowEquivalentAccountsFrom, + AllowEquivalentParentAccountsFrom, ); /// A trader who believes all tokens are created equal to "weight" of any chain, From 23e1a9f6fce5e6c20611d98b46a20e3b1fc23538 Mon Sep 17 00:00:00 2001 From: zqh Date: Tue, 16 Nov 2021 13:38:10 +0800 Subject: [PATCH 11/16] clean test --- xcm-support/src/lib.rs | 65 +++---- xcm-support/src/tests.rs | 48 +++++ xtokens/Cargo.toml | 2 - xtokens/src/mock/mod.rs | 7 - xtokens/src/mock/para.rs | 8 +- xtokens/src/mock/tests.rs | 359 -------------------------------------- xtokens/src/tests.rs | 303 -------------------------------- 7 files changed, 77 insertions(+), 715 deletions(-) delete mode 100644 xtokens/src/mock/tests.rs diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 057e47b18..81e62f68b 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -10,7 +10,7 @@ #![allow(clippy::unused_unit)] use frame_support::dispatch::{DispatchError, DispatchResult}; -use frame_support::{ensure, traits::Contains, weights::Weight}; +use frame_support::{ensure, weights::Weight}; use sp_runtime::traits::{CheckedConversion, Convert}; use sp_std::{convert::TryFrom, marker::PhantomData, prelude::*}; @@ -80,27 +80,22 @@ impl UnknownAsset for () { } /// Extracts the `AccountId32` from the passed `location` if the network -/// matches. -pub struct RelaychainAccountId32Aliases(PhantomData<(Network, AccountId)>); +/// matches or is `NetworkId::Any`. +pub struct RelayChainAccountId32Aliases(PhantomData<(Network, AccountId)>); impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone> - xcm_executor::traits::Convert for RelaychainAccountId32Aliases + xcm_executor::traits::Convert for RelayChainAccountId32Aliases { fn convert(location: MultiLocation) -> Result { - let id = match location { - MultiLocation { - parents: 1, - interior: X1(AccountId32 { - id, - network: NetworkId::Any, - }), - } => id, - MultiLocation { - parents: 1, - interior: X1(AccountId32 { id, network }), - } if network == Network::get() => id, - _ => return Err(location), + if let MultiLocation { + parents: 1, + interior: X1(AccountId32 { id, network }), + } = location.clone() + { + if network == NetworkId::Any || network == Network::get() { + return Ok(id.into()); + } }; - Ok(id.into()) + return Err(location); } fn reverse(who: AccountId) -> Result { @@ -115,37 +110,27 @@ impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone } } -pub struct IsParent; -impl Contains for IsParent { - fn contains(l: &MultiLocation) -> bool { - l.contains_parents_only(1) - } -} - -/// when Relay an XCM message from a given `interior` location, if the given -/// `interior` is not `Here`, the destination will receive a xcm message -/// beginning with `DescendOrigin` as the first instruction. so the xcm message -/// format must match this order: -/// `DescendOrigin`,`WithdrawAsset`,`BuyExecution`,`Transact`. -pub struct AllowEquivalentParentAccountsFrom(PhantomData<(T, Network)>); -impl, Network: Get> ShouldExecute - for AllowEquivalentParentAccountsFrom -{ +/// Allows execution from `origin` if it is `Parent`. +/// +/// Only allows exactly alike the order of xcm: `DescendOrigin`, +/// `WithdrawAsset`, `BuyExecution` and `Transact`. +pub struct AllowRelayedPaidExecutionFrom(PhantomData); +impl> ShouldExecute for AllowRelayedPaidExecutionFrom { fn should_execute( origin: &MultiLocation, message: &mut Xcm, max_weight: Weight, _weight_credit: &mut Weight, ) -> Result<(), ()> { - ensure!(T::contains(origin), ()); + ensure!(origin.contains_parents_only(1), ()); let mut iter = message.0.iter_mut(); let i = iter.next().ok_or(())?; match i { - DescendOrigin(X1(Junction::AccountId32 { - network: NetworkId::Any, - .. - })) => (), - DescendOrigin(X1(Junction::AccountId32 { network, .. })) if network == &Network::get() => (), + DescendOrigin(X1(Junction::AccountId32 { network, .. })) + if network == &NetworkId::Any || network == &Network::get() => + { + () + } _ => return Err(()), } let i = iter.next().ok_or(())?; diff --git a/xcm-support/src/tests.rs b/xcm-support/src/tests.rs index c47469c41..86a9de808 100644 --- a/xcm-support/src/tests.rs +++ b/xcm-support/src/tests.rs @@ -4,7 +4,9 @@ use super::*; +use frame_support::{pallet_prelude::Encode, parameter_types}; use orml_traits::{location::RelativeLocations, ConcreteFungibleAsset}; +use sp_runtime::AccountId32; #[derive(Debug, PartialEq, Eq)] pub enum TestCurrencyId { @@ -98,3 +100,49 @@ fn multi_native_asset() { &MultiLocation::parent(), )); } + +#[test] +fn relay_account_convert() { + use xcm_executor::traits::Convert; + + parameter_types! { + const RelayNetwork: NetworkId = NetworkId::Any; + } + let destination: MultiLocation = ( + Parent, + Junction::AccountId32 { + network: NetworkId::Any, + id: [0; 32], + }, + ) + .into(); + let account: Result = + RelayChainAccountId32Aliases::::convert(destination); + assert_eq!(account, Ok(AccountId32::new([0; 32]))); +} + +#[test] +fn allow_relayed_paid_execution_works() { + parameter_types! { + const RelayNetwork: NetworkId = NetworkId::Any; + } + let assets: MultiAsset = (Parent, 1000).into(); + let mut xcm = Xcm::<()>(vec![ + DescendOrigin(X1(Junction::AccountId32 { + network: NetworkId::Any, + id: [0; 32], + })), + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(1000), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: 1000 as u64, + call: Encode::encode(&100).into(), + }, + ]); + let r = AllowRelayedPaidExecutionFrom::::should_execute(&(Parent.into()), &mut xcm, 100, &mut 100); + assert_eq!(r, Ok(())); +} diff --git a/xtokens/Cargo.toml b/xtokens/Cargo.toml index b61b7f83d..f93ad8cf6 100644 --- a/xtokens/Cargo.toml +++ b/xtokens/Cargo.toml @@ -49,8 +49,6 @@ xcm-simulator = { git = "https://github.com/paritytech/polkadot", branch = "rele orml-tokens = { path = "../tokens" } orml-xcm = { path = "../xcm" } -env_logger = "0.8.3" - [features] default = ["std"] std = [ diff --git a/xtokens/src/mock/mod.rs b/xtokens/src/mock/mod.rs index bf84ccde3..81fcb56f2 100644 --- a/xtokens/src/mock/mod.rs +++ b/xtokens/src/mock/mod.rs @@ -14,11 +14,9 @@ use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chai pub mod para; pub mod relay; -pub mod tests; pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); pub const BOB: AccountId32 = AccountId32::new([2u8; 32]); -pub const DEFAULT: AccountId32 = AccountId32::new([0u8; 32]); pub const INITIAL_BALANCE: u128 = 1_000; pub fn para_a_account() -> AccountId32 { @@ -146,14 +144,9 @@ decl_test_network! { } pub type RelayBalances = pallet_balances::Pallet; -pub type ParaBalances = pallet_balances::Pallet; - pub type ParaTokens = orml_tokens::Pallet; pub type ParaXTokens = orml_xtokens::Pallet; -pub type RelayChainPalletXcm = pallet_xcm::Pallet; -pub type ParachainPalletXcm = pallet_xcm::Pallet; - pub fn para_ext(para_id: u32) -> TestExternalities { use para::{Runtime, System}; diff --git a/xtokens/src/mock/para.rs b/xtokens/src/mock/para.rs index 0eea55c02..7fcd2d831 100644 --- a/xtokens/src/mock/para.rs +++ b/xtokens/src/mock/para.rs @@ -27,8 +27,8 @@ use xcm_executor::{traits::WeightTrader, Assets, Config, XcmExecutor}; use orml_traits::parameter_type_with_key; use orml_xcm_support::{ - AllowEquivalentParentAccountsFrom, IsNativeConcrete, IsParent, MultiCurrencyAdapter, MultiNativeAsset, - RelaychainAccountId32Aliases, + AllowRelayedPaidExecutionFrom, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, + RelayChainAccountId32Aliases, }; pub type AccountId = AccountId32; @@ -117,7 +117,7 @@ pub type LocationToAccountId = ( ParentIsDefault, SiblingParachainConvertsVia, AccountId32Aliases, - RelaychainAccountId32Aliases, + RelayChainAccountId32Aliases, ); pub type XcmOriginToCallOrigin = ( @@ -147,7 +147,7 @@ pub type XcmRouter = ParachainXcmRouter; pub type Barrier = ( TakeWeightCredit, AllowTopLevelPaidExecutionFrom, - AllowEquivalentParentAccountsFrom, + AllowRelayedPaidExecutionFrom, ); /// A trader who believes all tokens are created equal to "weight" of any chain, diff --git a/xtokens/src/mock/tests.rs b/xtokens/src/mock/tests.rs deleted file mode 100644 index 094f4ad49..000000000 --- a/xtokens/src/mock/tests.rs +++ /dev/null @@ -1,359 +0,0 @@ -#![cfg(test)] - -use super::para::AccountIdToMultiLocation; -use super::*; -use orml_traits::MultiCurrency; -use xcm_builder::IsConcrete; -use xcm_executor::traits::{MatchesFungible, WeightTrader}; -use xcm_simulator::TestExt; - -use crate::mock::para::RelayLocation; -use crate::mock::relay::KsmLocation; -use xcm_executor::Assets; - -#[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(¶_a_account()), 0); - assert_eq!(RelayBalances::free_balance(¶_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 - // `KsmLocation` in `relay.rs` is `Here` - let assets: VersionedMultiAssets = (Here, 100u128).into(); - let assets: MultiAssets = assets.try_into().unwrap(); - let assets: Vec = assets.drain(); - for asset in assets { - let assets: u128 = IsConcrete::::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::::matches_fungible(&asset.clone()).unwrap_or_default(); - assert_eq!(amount, 100u128); - - // `KsmLocation` in `relay.rs` is `Here` - let asset: MultiAsset = (X1(Parachain(1)), 100u128).into(); - let assets: u128 = IsConcrete::::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::::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(DEFAULT)); - - // 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::Kusama, - 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 1: ../Parachain/Account - let destination: MultiLocation = (Parent, Parachain(1), alice.clone()).into(); - let account = para::LocationToAccountId::convert(destination.clone()); - assert_eq!(account, Err(destination)); - - // Error case 2: ./Parachain - let destination: MultiLocation = (Parachain(1),).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_on_dot = 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_on_dot.clone()).into(); - let account = relay::SovereignAccountOf::convert(destination.clone()); - assert_eq!(account, Err(destination)); -} - -#[test] -fn test_parachain_convert_origin() { - use xcm_executor::traits::ConvertOrigin; - - let alice = Junction::AccountId32 { - network: NetworkId::Kusama, - id: ALICE.into(), - }; - let alice_any = Junction::AccountId32 { - network: NetworkId::Any, - id: ALICE.into(), - }; - let alice_on_dot = Junction::AccountId32 { - network: NetworkId::Polkadot, - id: ALICE.into(), - }; - - // supported destination convert with OriginKind::SovereignAccount - let supported_sovereign_account_destination: Vec = vec![ - // ParentIsDefault: parent default account can be kind of sovereign account - Parent.into(), - // SiblingParachainConvertsVia: sibling parachain can be kind of sovereign account - (Parent, Parachain(1)).into(), - // AccountId32Aliases: current chain's account can be kind of sovereign account - (alice.clone()).into(), - // RelaychainAccountId32Aliases: relaychain's account can be kind of sovereign account(xcm-support feature) - (Parent, alice.clone()).into(), - (Parent, alice_any.clone()).into(), - ]; - - // unsupported destination convert with OriginKind::SovereignAccount - let unsupported_sovereign_account_destination: Vec = vec![ - // sibling parachain's account can't be kind of sovereign account - (Parent, Parachain(1), alice.clone()).into(), - // relaychain's account with unmatched network can't be kind of sovereign account - (Parent, alice_on_dot.clone()).into(), - ]; - - for destination in supported_sovereign_account_destination { - let origin = para::XcmOriginToCallOrigin::convert_origin(destination, OriginKind::SovereignAccount); - assert!(origin.is_ok()); - } - for destination in unsupported_sovereign_account_destination { - let origin = para::XcmOriginToCallOrigin::convert_origin(destination, OriginKind::SovereignAccount); - assert!(origin.is_err()); - } - - let supported_native_destination: Vec = vec![ - // RelayChainAsNative - Parent.into(), - // SiblingParachainAsNative - (Parent, Parachain(1)).into(), - // SignedAccountId32AsNative - (alice.clone()).into(), - ]; - - let unsupported_native_destination: Vec = vec![ - (Parent, Parachain(1), alice.clone()).into(), - (Parent, alice.clone()).into(), - ]; - - for destination in supported_native_destination { - let origin = para::XcmOriginToCallOrigin::convert_origin(destination, OriginKind::Native); - assert!(origin.is_ok()); - } - for destination in unsupported_native_destination { - let origin = para::XcmOriginToCallOrigin::convert_origin(destination, OriginKind::Native); - assert!(origin.is_err()); - } - - // XcmPassthrough - let destination: MultiLocation = (Parent, Parachain(1), alice.clone()).into(); - let origin = para::XcmOriginToCallOrigin::convert_origin(destination.clone(), OriginKind::Xcm); - assert!(origin.is_ok()); -} - -#[test] -fn test_call_weight_info() { - use frame_support::weights::GetDispatchInfo; - use para::{Call, Runtime}; - - let expect_weight: u64 = 6000; - let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); - - let weight = call.get_dispatch_info().weight; - assert_eq!(weight, expect_weight); - - let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); - let weight = call.get_dispatch_info().weight; - assert_eq!(weight, expect_weight); - - let call = Call::Balances(pallet_balances::Call::::transfer { dest: BOB, value: 100 }); - let weight = call.get_dispatch_info().weight; - assert_eq!(weight, 195952000); - - let call_para = Call::Balances(pallet_balances::Call::::transfer { dest: BOB, value: 100 }); - let call_relay = relay::Call::XcmPallet(pallet_xcm::Call::::send { - dest: Box::new(VersionedMultiLocation::V1(Parachain(2).into())), - message: Box::new(VersionedXcm::from(Xcm(vec![Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 1000, - call: call_para.encode().into(), - }]))), - }); - let weight = call_relay.get_dispatch_info().weight; - assert_eq!(weight, 100000000); -} - -#[test] -fn test_parachain_weigher_calculate() { - use frame_support::weights::GetDispatchInfo; - use para::{Call, Runtime, XcmConfig}; - - let expect_weight: u64 = 195952000; - let call = Call::Balances(pallet_balances::Call::::transfer { dest: BOB, value: 100 }); - - let weight = call.get_dispatch_info().weight; - assert_eq!(weight, expect_weight); - - let assets: MultiAsset = (Parent, 1).into(); - - let instructions = vec![ - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets.clone(), - weight_limit: Limited(1), - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: expect_weight, - call: call.encode().into(), - }, - ]; - let xcm_weight = ::Weigher::weight(&mut Xcm(instructions)); - assert_eq!(xcm_weight.unwrap(), expect_weight + 30); - - let instructions = vec![ - DescendOrigin(Junctions::X1(Junction::AccountId32 { - network: NetworkId::Any, - id: [0; 32], - })), - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets, - weight_limit: Limited(1), - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: expect_weight, - call: call.encode().into(), - }, - ]; - let xcm_weight = ::Weigher::weight(&mut Xcm(instructions)); - assert_eq!(xcm_weight.unwrap(), expect_weight + 40); -} - -#[test] -fn test_trader() { - use para::XcmConfig; - - let asset: MultiAsset = (Parent, 1000).into(); - - let mut holding = Assets::new(); - holding.subsume(asset.clone()); - - let backup = holding.clone(); - - let fees: MultiAsset = (Parent, 1000).into(); - let max_fee = holding.try_take(fees.into()).unwrap(); - - assert_eq!(holding.is_empty(), true); - assert_eq!(max_fee, backup); - - let mut trader = para::AllTokensAreCreatedEqualToWeight::new(); - let result = ::Trader::buy_weight(&mut trader, 1000, max_fee.clone()); - assert_eq!(result.is_ok(), true); - assert_eq!(result.unwrap().is_empty(), true); - - let result = ::Trader::buy_weight(&mut trader, 2000, max_fee); - assert_eq!(result.is_err(), true); -} diff --git a/xtokens/src/tests.rs b/xtokens/src/tests.rs index 3a495ad4e..be2c8ca78 100644 --- a/xtokens/src/tests.rs +++ b/xtokens/src/tests.rs @@ -404,309 +404,6 @@ fn send_as_sovereign_fails_if_bad_origin() { }); } -#[test] -fn para_transact_to_relay_remark_use_sovereign_account() { - Relay::execute_with(|| { - let _ = RelayBalances::deposit_creating(¶_a_account(), 6030); - }); - - ParaA::execute_with(|| { - parachain_transact_to_relaychian_remark(); - }); - - Relay::execute_with(|| { - use relay::{Event, System}; - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); - }); -} - -#[test] -fn relay_transact_to_para_remark_use_default_sovereign_account() { - ParaA::execute_with(|| { - assert_ok!(ParaTokens::deposit(CurrencyId::R, &DEFAULT, 6030)); - }); - - relaychain_transact_to_parachain_remark(Here, 6030); - - ParaA::execute_with(|| { - use para::{Event, System}; - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); - }); -} - -#[test] -fn relay_transact_to_para_remark_use_normal_account() { - ParaA::execute_with(|| { - assert_ok!(ParaTokens::deposit(CurrencyId::R, &ALICE, 6040)); - assert_eq!(7040, ParaTokens::free_balance(CurrencyId::R, &ALICE)); - }); - - let alice = Junctions::X1(Junction::AccountId32 { - network: NetworkId::Kusama, - id: ALICE.into(), - }); - relaychain_transact_to_parachain_remark(alice.clone(), 6040); - - ParaA::execute_with(|| { - use para::{Event, System}; - assert_eq!(1000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); - System::reset_events(); - }); - relaychain_transact_to_parachain_remark(alice.clone(), 100); - - ParaA::execute_with(|| { - use para::{Event, System}; - assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); - assert_eq!( - System::events() - .iter() - .find(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _)))), - None - ); - }); -} - -#[test] -fn relay_transact_to_para_transfer_use_normal_account() { - ParaA::execute_with(|| { - assert_ok!(ParaTokens::deposit(CurrencyId::R, &ALICE, 195952040)); - assert_eq!(195953040, ParaTokens::free_balance(CurrencyId::R, &ALICE)); - let _ = ParaBalances::deposit_creating(&ALICE, 1_000); - assert_eq!(1000, ParaBalances::free_balance(&ALICE)); - }); - - let alice = Junctions::X1(Junction::AccountId32 { - network: NetworkId::Kusama, - id: ALICE.into(), - }); - relaychain_transact_to_parachain_transfer(alice.clone(), 195952040, 500); - - ParaA::execute_with(|| { - use para::{Event, System}; - assert_eq!(1000, ParaTokens::free_balance(CurrencyId::R, &ALICE)); - assert_eq!(500, ParaBalances::free_balance(&ALICE)); - assert_eq!(500, ParaBalances::free_balance(&BOB)); - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::Balances(pallet_balances::Event::Transfer(_, _, _))))); - System::reset_events(); - }); - - relaychain_transact_to_parachain_transfer(alice.clone(), 100, 100); - - ParaA::execute_with(|| { - use para::{Event, System}; - assert_eq!(900, ParaTokens::free_balance(CurrencyId::R, &ALICE)); - assert_eq!(500, ParaBalances::free_balance(&ALICE)); - assert_eq!(500, ParaBalances::free_balance(&BOB)); - assert_eq!( - System::events() - .iter() - .find(|r| matches!(r.event, Event::Balances(pallet_balances::Event::Transfer(_, _, _)))), - None - ); - }); -} - -#[test] -fn para_transact_to_sibling_remark_use_sovereign_account() { - ParaB::execute_with(|| { - assert_ok!(ParaTokens::deposit(CurrencyId::R, &sibling_a_account(), 6030)); - }); - - parachain_transact_to_sibling_remark(Here, 6030); - - ParaB::execute_with(|| { - use para::{Event, System}; - assert_eq!(0, ParaTokens::free_balance(CurrencyId::R, &sibling_a_account())); - assert!(System::events() - .iter() - .any(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _))))); - }); -} - -#[test] -fn para_transact_to_sibling_remark_use_account_failed() { - let alice = Junctions::X1(Junction::AccountId32 { - network: NetworkId::Any, - id: ALICE.into(), - }); - - // the origin of `WithdrawAsset` in the context of destination parachain is - // `(Parent, Parachain(1), Alice)` and it get error when convert by - // `LocationToAccountId`. - parachain_transact_to_sibling_remark(alice, 6040); - - ParaB::execute_with(|| { - use para::{Event, System}; - assert_eq!( - System::events() - .iter() - .find(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _)))), - None - ); - }); -} - -#[test] -fn relay_transact_to_para_unsupport_kind_failed() { - ParaA::execute_with(|| { - assert_ok!(ParaTokens::deposit(CurrencyId::R, &DEFAULT, 6040)); - }); - - use para::{Call, Runtime}; - let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); - let assets: MultiAsset = (Parent, 6040).into(); - let alice = Junctions::X1(Junction::AccountId32 { - network: NetworkId::Any, - id: ALICE.into(), - }); - - Relay::execute_with(|| { - let xcm = vec![ - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets, - weight_limit: Limited(6040), - }, - Transact { - origin_type: OriginKind::Native, - require_weight_at_most: 6000 as u64, - call: call.encode().into(), - }, - ]; - assert_ok!(RelayChainPalletXcm::send_xcm(alice, Parachain(1).into(), Xcm(xcm),)); - }); - - ParaA::execute_with(|| { - use para::{Event, System}; - assert_eq!( - System::events() - .iter() - .find(|r| matches!(r.event, Event::System(frame_system::Event::Remarked(_, _)))), - None - ); - }); -} - -fn relaychain_transact_to_parachain_remark(junctions: Junctions, amount: u128) { - use para::{Call, Runtime}; - let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); - let assets: MultiAsset = (Parent, amount).into(); - - let limit: u64 = match junctions { - Here => 6030, - _ => 6040, - }; - - Relay::execute_with(|| { - let xcm = vec![ - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets, - weight_limit: Limited(limit), - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 6000 as u64, - call: call.encode().into(), - }, - ]; - assert_ok!(RelayChainPalletXcm::send_xcm(junctions, Parachain(1).into(), Xcm(xcm),)); - }); -} - -fn relaychain_transact_to_parachain_transfer(junctions: Junctions, amount: u128, transfer_amount: u128) { - use para::{Call, Runtime}; - let call = Call::Balances(pallet_balances::Call::::transfer { - dest: BOB, - value: transfer_amount, - }); - let assets: MultiAsset = (Parent, amount).into(); - - let limit: u64 = match junctions { - Here => 195952000 + 30, - _ => 195952000 + 40, - }; - - Relay::execute_with(|| { - let xcm = vec![ - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets, - weight_limit: Limited(limit), - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 195952000 as u64, - call: call.encode().into(), - }, - ]; - assert_ok!(RelayChainPalletXcm::send_xcm(junctions, Parachain(1).into(), Xcm(xcm),)); - }); -} - -fn parachain_transact_to_relaychian_remark() { - use relay::{Call, Runtime}; - let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); - let assets: MultiAsset = (Here, 6030).into(); - - assert_ok!(ParachainPalletXcm::send_xcm( - Here, - Parent, - Xcm(vec![ - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets, - weight_limit: Limited(6030) - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 6000 as u64, - call: call.encode().into(), - }, - ]), - )); -} - -fn parachain_transact_to_sibling_remark(junctions: Junctions, amount: u128) { - use relay::{Call, Runtime}; - let call = Call::System(frame_system::Call::::remark_with_event { remark: vec![1, 2, 3] }); - let assets: MultiAsset = (Parent, amount).into(); - let limit: u64 = match junctions { - Here => 6030, - _ => 6040, - }; - - ParaA::execute_with(|| { - let xcm = vec![ - WithdrawAsset(assets.clone().into()), - BuyExecution { - fees: assets, - weight_limit: Limited(limit), - }, - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: 6000 as u64, - call: call.encode().into(), - }, - ]; - - assert_ok!(ParachainPalletXcm::send_xcm( - junctions, - (Parent, Parachain(2)), - Xcm(xcm) - )); - }); -} - #[test] fn call_size_limit() { // Ensures Call enum doesn't allocate more than 200 bytes in runtime From e1467bacde66d8015b7a1a8ddbcc8b0c76d59197 Mon Sep 17 00:00:00 2001 From: zqh Date: Tue, 16 Nov 2021 13:57:13 +0800 Subject: [PATCH 12/16] clippy --- xcm-support/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 81e62f68b..aca32e69a 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -95,7 +95,7 @@ impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone return Ok(id.into()); } }; - return Err(location); + Err(location) } fn reverse(who: AccountId) -> Result { From 9cffcc57b0061b9351ed1a41776444326be71e14 Mon Sep 17 00:00:00 2001 From: zqh Date: Tue, 16 Nov 2021 14:52:11 +0800 Subject: [PATCH 13/16] rename --- xcm-support/src/lib.rs | 4 ++-- xcm-support/src/tests.rs | 2 +- xtokens/src/mock/para.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index aca32e69a..af34173e3 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -114,8 +114,8 @@ impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone /// /// Only allows exactly alike the order of xcm: `DescendOrigin`, /// `WithdrawAsset`, `BuyExecution` and `Transact`. -pub struct AllowRelayedPaidExecutionFrom(PhantomData); -impl> ShouldExecute for AllowRelayedPaidExecutionFrom { +pub struct AllowRelayedPaidExecutionFromParent(PhantomData); +impl> ShouldExecute for AllowRelayedPaidExecutionFromParent { fn should_execute( origin: &MultiLocation, message: &mut Xcm, diff --git a/xcm-support/src/tests.rs b/xcm-support/src/tests.rs index 86a9de808..c866a881c 100644 --- a/xcm-support/src/tests.rs +++ b/xcm-support/src/tests.rs @@ -143,6 +143,6 @@ fn allow_relayed_paid_execution_works() { call: Encode::encode(&100).into(), }, ]); - let r = AllowRelayedPaidExecutionFrom::::should_execute(&(Parent.into()), &mut xcm, 100, &mut 100); + let r = AllowRelayedPaidExecutionFromParent::::should_execute(&(Parent.into()), &mut xcm, 100, &mut 100); assert_eq!(r, Ok(())); } diff --git a/xtokens/src/mock/para.rs b/xtokens/src/mock/para.rs index 7fcd2d831..686a58fd8 100644 --- a/xtokens/src/mock/para.rs +++ b/xtokens/src/mock/para.rs @@ -27,7 +27,7 @@ use xcm_executor::{traits::WeightTrader, Assets, Config, XcmExecutor}; use orml_traits::parameter_type_with_key; use orml_xcm_support::{ - AllowRelayedPaidExecutionFrom, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, + AllowRelayedPaidExecutionFromParent, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset, RelayChainAccountId32Aliases, }; @@ -147,7 +147,7 @@ pub type XcmRouter = ParachainXcmRouter; pub type Barrier = ( TakeWeightCredit, AllowTopLevelPaidExecutionFrom, - AllowRelayedPaidExecutionFrom, + AllowRelayedPaidExecutionFromParent, ); /// A trader who believes all tokens are created equal to "weight" of any chain, From 631659bde3f12a110d3c8b34a62bf1a18f1aabbb Mon Sep 17 00:00:00 2001 From: zqh Date: Tue, 16 Nov 2021 14:54:04 +0800 Subject: [PATCH 14/16] fmt --- xcm-support/src/tests.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xcm-support/src/tests.rs b/xcm-support/src/tests.rs index c866a881c..fa2040b68 100644 --- a/xcm-support/src/tests.rs +++ b/xcm-support/src/tests.rs @@ -143,6 +143,7 @@ fn allow_relayed_paid_execution_works() { call: Encode::encode(&100).into(), }, ]); - let r = AllowRelayedPaidExecutionFromParent::::should_execute(&(Parent.into()), &mut xcm, 100, &mut 100); + let r = + AllowRelayedPaidExecutionFromParent::::should_execute(&(Parent.into()), &mut xcm, 100, &mut 100); assert_eq!(r, Ok(())); } From b1a2a90b347d8825448d10fdf5046452bd65ebf9 Mon Sep 17 00:00:00 2001 From: zqh Date: Thu, 18 Nov 2021 17:55:46 +0800 Subject: [PATCH 15/16] support withdraw and deposit after buy_execution --- xcm-support/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index af34173e3..49722f876 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -111,9 +111,6 @@ impl, AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone } /// Allows execution from `origin` if it is `Parent`. -/// -/// Only allows exactly alike the order of xcm: `DescendOrigin`, -/// `WithdrawAsset`, `BuyExecution` and `Transact`. pub struct AllowRelayedPaidExecutionFromParent(PhantomData); impl> ShouldExecute for AllowRelayedPaidExecutionFromParent { fn should_execute( @@ -154,7 +151,9 @@ impl> ShouldExecute for AllowRelayedPaidExecutionFromPar Transact { origin_type: OriginKind::SovereignAccount, .. - } => Ok(()), + } + | WithdrawAsset(..) + | DepositAsset { .. } => Ok(()), _ => Err(()), } } From 4177cd6961ff6dd0c7d80ff713ed4839b466cae8 Mon Sep 17 00:00:00 2001 From: zqh Date: Thu, 18 Nov 2021 18:14:22 +0800 Subject: [PATCH 16/16] rm withdraw and more tests --- xcm-support/src/lib.rs | 1 - xcm-support/src/tests.rs | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/xcm-support/src/lib.rs b/xcm-support/src/lib.rs index 49722f876..1d58784fe 100644 --- a/xcm-support/src/lib.rs +++ b/xcm-support/src/lib.rs @@ -152,7 +152,6 @@ impl> ShouldExecute for AllowRelayedPaidExecutionFromPar origin_type: OriginKind::SovereignAccount, .. } - | WithdrawAsset(..) | DepositAsset { .. } => Ok(()), _ => Err(()), } diff --git a/xcm-support/src/tests.rs b/xcm-support/src/tests.rs index fa2040b68..98efc9544 100644 --- a/xcm-support/src/tests.rs +++ b/xcm-support/src/tests.rs @@ -4,7 +4,7 @@ use super::*; -use frame_support::{pallet_prelude::Encode, parameter_types}; +use frame_support::{assert_ok, pallet_prelude::Encode, parameter_types}; use orml_traits::{location::RelativeLocations, ConcreteFungibleAsset}; use sp_runtime::AccountId32; @@ -122,7 +122,7 @@ fn relay_account_convert() { } #[test] -fn allow_relayed_paid_execution_works() { +fn allow_relayed_paid_execution_transact_works() { parameter_types! { const RelayNetwork: NetworkId = NetworkId::Any; } @@ -145,5 +145,36 @@ fn allow_relayed_paid_execution_works() { ]); let r = AllowRelayedPaidExecutionFromParent::::should_execute(&(Parent.into()), &mut xcm, 100, &mut 100); - assert_eq!(r, Ok(())); + assert_ok!(r); +} + +#[test] +fn allow_relayed_paid_execution_weight_not_works() { + parameter_types! { + const RelayNetwork: NetworkId = NetworkId::Any; + } + let bob = X1(Junction::AccountId32 { + network: NetworkId::Kusama, + id: [1; 32], + }); + let assets: MultiAsset = (Parent, 1000).into(); + let mut xcm = Xcm::<()>(vec![ + DescendOrigin(X1(Junction::AccountId32 { + network: NetworkId::Any, + id: [0; 32], + })), + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(1000), + }, + DepositAsset { + assets: All.into(), + max_assets: 1, + beneficiary: (0, bob).into(), + }, + ]); + let r = + AllowRelayedPaidExecutionFromParent::::should_execute(&(Parent.into()), &mut xcm, 2000, &mut 100); + assert_eq!(r, Err(())); }