From 46c2cb59307ecda5e173db7b6cc26d095e0e4aae Mon Sep 17 00:00:00 2001 From: Xiliang Chen Date: Fri, 8 Sep 2023 09:43:23 +1200 Subject: [PATCH] fix reserve transfer from relaychain (#2607) * fix reserve transfer from relaychain * refactor * update --- Cargo.lock | 29 +++ Cargo.toml | 2 + modules/relaychain/Cargo.toml | 2 - modules/relaychain/src/lib.rs | 233 ++++++++---------- modules/support/src/lib.rs | 76 +----- modules/support/src/relaychain.rs | 156 ++++++++++++ modules/xcm-interface/Cargo.toml | 16 +- modules/xcm-interface/src/lib.rs | 53 ++-- modules/xcm-interface/src/migrations.rs | 84 ------- modules/xcm-interface/src/mocks/kusama.rs | 21 ++ .../src/{mock.rs => mocks/mod.rs} | 202 +++++++-------- modules/xcm-interface/src/mocks/polkadot.rs | 21 ++ ...iquid_crowdloan_module_account_kusama.snap | 161 ++++++++++++ ...uid_crowdloan_module_account_polkadot.snap | 161 ++++++++++++ modules/xcm-interface/src/tests.rs | 93 ++----- runtime/acala/Cargo.toml | 2 +- runtime/acala/src/lib.rs | 2 +- runtime/integration-tests/Cargo.toml | 3 - runtime/karura/Cargo.toml | 2 +- runtime/karura/src/lib.rs | 2 +- runtime/mandala/Cargo.toml | 2 +- runtime/mandala/src/lib.rs | 2 +- 22 files changed, 823 insertions(+), 502 deletions(-) create mode 100644 modules/support/src/relaychain.rs delete mode 100644 modules/xcm-interface/src/migrations.rs create mode 100644 modules/xcm-interface/src/mocks/kusama.rs rename modules/xcm-interface/src/{mock.rs => mocks/mod.rs} (56%) create mode 100644 modules/xcm-interface/src/mocks/polkadot.rs create mode 100644 modules/xcm-interface/src/snapshots/module_xcm_interface__tests__build_transfer_to_liquid_crowdloan_module_account_kusama.snap create mode 100644 modules/xcm-interface/src/snapshots/module_xcm_interface__tests__build_transfer_to_liquid_crowdloan_module_account_polkadot.snap diff --git a/Cargo.lock b/Cargo.lock index 9f5b1db076..33c32b558e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4588,6 +4588,19 @@ dependencies = [ "generic-array 0.14.7", ] +[[package]] +name = "insta" +version = "1.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0770b0a3d4c70567f0d58331f3088b0e4c4f56c9b8d764efe654b4a5d46de3a" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "similar", + "yaml-rust", +] + [[package]] name = "instant" version = "0.1.12" @@ -6949,6 +6962,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "insta", "module-currencies", "module-relaychain", "module-support", @@ -13371,6 +13385,12 @@ dependencies = [ "wide", ] +[[package]] +name = "similar" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" + [[package]] name = "siphasher" version = "0.3.10" @@ -16678,6 +16698,15 @@ dependencies = [ "xcm-executor", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "yamux" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index ea8dc1425f..6657368058 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -119,6 +119,8 @@ uint = { opt-level = 3 } x25519-dalek = { opt-level = 3 } yamux = { opt-level = 3 } zeroize = { opt-level = 3 } +insta.opt-level = 3 +similar.opt-level = 3 [workspace.dependencies] frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0" } diff --git a/modules/relaychain/Cargo.toml b/modules/relaychain/Cargo.toml index 430f01cf6b..89470a1b0d 100644 --- a/modules/relaychain/Cargo.toml +++ b/modules/relaychain/Cargo.toml @@ -21,8 +21,6 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1 [features] default = ["std"] -kusama = [] -polkadot = [] std = [ "codec/std", "cumulus-primitives-core/std", diff --git a/modules/relaychain/src/lib.rs b/modules/relaychain/src/lib.rs index 3a03c251cb..0c0547abb9 100644 --- a/modules/relaychain/src/lib.rs +++ b/modules/relaychain/src/lib.rs @@ -24,155 +24,143 @@ #![allow(clippy::unused_unit)] #![allow(clippy::large_enum_variant)] -use codec::{Decode, Encode}; -use sp_runtime::traits::{AccountIdLookup, StaticLookup}; +use codec::{Decode, Encode, FullCodec}; +use sp_runtime::traits::StaticLookup; use frame_support::{traits::Get, RuntimeDebug}; -use module_support::CallBuilder; +use module_support::relaychain::*; use primitives::{AccountId, Balance}; use sp_std::{boxed::Box, marker::PhantomData, prelude::*}; pub use cumulus_primitives_core::ParaId; use xcm::{prelude::*, v3::Weight as XcmWeight}; -// * Since XCM V3, relaychain configs 'SafeCallFilter' to filter the call in Transact: -// * https://github.com/paritytech/polkadot/blob/master/runtime/polkadot/src/xcm_config.rs - +/// The encoded index correspondes to Kusama's Runtime module configuration. +/// https://github.com/paritytech/polkadot/blob/444e96ae34bcec8362f0f947a07bd912b32ca48f/runtime/kusama/src/lib.rs#L1379 #[derive(Encode, Decode, RuntimeDebug)] -pub enum BalancesCall { - #[codec(index = 3)] - TransferKeepAlive(::Source, #[codec(compact)] Balance), /* TODO: because - * param type - * in relaychain is - * u64, - * need to confirm - * Balance(u128) is - * working. */ +pub enum KusamaRelayChainCall { + #[codec(index = 4)] + Balances(BalancesCall), + #[codec(index = 6)] + Staking(StakingCall), + #[codec(index = 24)] + Utility(Box>), + #[codec(index = 30)] + Proxy(Box>), + #[codec(index = 99)] + XcmPallet(XcmCall), } -#[derive(Encode, Decode, RuntimeDebug)] -pub enum UtilityCall { - #[codec(index = 1)] - AsDerivative(u16, RelayChainCall), -} +impl RelayChainCall for KusamaRelayChainCall { + fn balances(call: BalancesCall) -> Self { + KusamaRelayChainCall::Balances(call) + } -#[derive(Encode, Decode, RuntimeDebug)] -pub enum StakingCall { - #[codec(index = 1)] - BondExtra(#[codec(compact)] Balance), /* TODO: because param type in relaychain is u64, need to confirm - * Balance(u128) is working. */ - #[codec(index = 2)] - Unbond(#[codec(compact)] Balance), /* TODO: because param type in relaychain is u64, need to confirm - * Balance(u128) is working. */ - #[codec(index = 3)] - WithdrawUnbonded(u32), -} + fn staking(call: StakingCall) -> Self { + KusamaRelayChainCall::Staking(call) + } -/// `pallet-xcm` calls. -#[derive(Encode, Decode, RuntimeDebug)] -pub enum XcmCall { - /// `reserve_transfer_assets(dest, beneficiary, assets, fee_asset_item)` call. - #[codec(index = 2)] - ReserveTransferAssets( - VersionedMultiLocation, - VersionedMultiLocation, - VersionedMultiAssets, - u32, - ), -} + fn utility(call: UtilityCall) -> Self { + KusamaRelayChainCall::Utility(Box::new(call)) + } -// Same to `Polkadot` and `Kusama` runtime `Lookup` config. -pub type RelayChainLookup = AccountIdLookup; + fn proxy(call: ProxyCall) -> Self { + KusamaRelayChainCall::Proxy(Box::new(call)) + } -/// `pallet-proxy` calls. + fn xcm_pallet(call: XcmCall) -> Self { + KusamaRelayChainCall::XcmPallet(call) + } +} + +/// The encoded index correspondes to Polkadot's Runtime module configuration. +/// https://github.com/paritytech/polkadot/blob/84a3962e76151ac5ed3afa4ef1e0af829531ab42/runtime/polkadot/src/lib.rs#L1040 #[derive(Encode, Decode, RuntimeDebug)] -pub enum ProxyCall { - /// `proxy(real, force_proxy_type, call)` call. Force proxy type is not supported and - /// is always set to `None`. - #[codec(index = 0)] - Proxy(::Source, Option<()>, RelayChainCall), +pub enum PolkadotRelayChainCall { + #[codec(index = 5)] + Balances(BalancesCall), + #[codec(index = 7)] + Staking(StakingCall), + #[codec(index = 26)] + Utility(Box>), + #[codec(index = 29)] + Proxy(Box>), + #[codec(index = 99)] + XcmPallet(XcmCall), } -#[cfg(feature = "kusama")] -mod kusama { - use crate::*; - - /// The encoded index correspondes to Kusama's Runtime module configuration. - /// https://github.com/paritytech/polkadot/blob/444e96ae34bcec8362f0f947a07bd912b32ca48f/runtime/kusama/src/lib.rs#L1379 - #[derive(Encode, Decode, RuntimeDebug)] - pub enum RelayChainCall { - #[codec(index = 4)] - Balances(BalancesCall), - #[codec(index = 6)] - Staking(StakingCall), - #[codec(index = 24)] - Utility(Box>), - #[codec(index = 30)] - Proxy(Box>), - #[codec(index = 99)] - XcmPallet(XcmCall), +impl RelayChainCall for PolkadotRelayChainCall { + fn balances(call: BalancesCall) -> Self { + PolkadotRelayChainCall::Balances(call) } -} -#[cfg(feature = "polkadot")] -mod polkadot { - use crate::*; - - /// The encoded index correspondes to Polkadot's Runtime module configuration. - /// https://github.com/paritytech/polkadot/blob/84a3962e76151ac5ed3afa4ef1e0af829531ab42/runtime/polkadot/src/lib.rs#L1040 - #[derive(Encode, Decode, RuntimeDebug)] - pub enum RelayChainCall { - #[codec(index = 5)] - Balances(BalancesCall), - #[codec(index = 7)] - Staking(StakingCall), - #[codec(index = 26)] - Utility(Box>), - #[codec(index = 29)] - Proxy(Box>), - #[codec(index = 99)] - XcmPallet(XcmCall), + fn staking(call: StakingCall) -> Self { + PolkadotRelayChainCall::Staking(call) } -} -#[cfg(feature = "kusama")] -pub use kusama::*; + fn utility(call: UtilityCall) -> Self { + PolkadotRelayChainCall::Utility(Box::new(call)) + } + + fn proxy(call: ProxyCall) -> Self { + PolkadotRelayChainCall::Proxy(Box::new(call)) + } -#[cfg(feature = "polkadot")] -pub use polkadot::*; + fn xcm_pallet(call: XcmCall) -> Self { + PolkadotRelayChainCall::XcmPallet(call) + } +} -pub struct RelayChainCallBuilder>(PhantomData); +pub struct RelayChainCallBuilder(PhantomData<(ParachainId, RCC)>); -impl> CallBuilder for RelayChainCallBuilder { +impl CallBuilder for RelayChainCallBuilder +where + ParachainId: Get, + RCC: RelayChainCall + FullCodec, +{ type AccountId = AccountId; type Balance = Balance; - type RelayChainCall = RelayChainCall; + type RelayChainCall = RCC; - fn utility_as_derivative_call(call: Self::RelayChainCall, index: u16) -> Self::RelayChainCall { - RelayChainCall::Utility(Box::new(UtilityCall::AsDerivative(index, call))) + fn utility_as_derivative_call(call: RCC, index: u16) -> RCC { + RCC::utility(UtilityCall::AsDerivative(index, call)) } - fn staking_bond_extra(amount: Self::Balance) -> Self::RelayChainCall { - RelayChainCall::Staking(StakingCall::BondExtra(amount)) + fn staking_bond_extra(amount: Self::Balance) -> RCC { + RCC::staking(StakingCall::BondExtra(amount)) } - fn staking_unbond(amount: Self::Balance) -> Self::RelayChainCall { - RelayChainCall::Staking(StakingCall::Unbond(amount)) + fn staking_unbond(amount: Self::Balance) -> RCC { + RCC::staking(StakingCall::Unbond(amount)) } - fn staking_withdraw_unbonded(num_slashing_spans: u32) -> Self::RelayChainCall { - RelayChainCall::Staking(StakingCall::WithdrawUnbonded(num_slashing_spans)) + fn staking_withdraw_unbonded(num_slashing_spans: u32) -> RCC { + RCC::staking(StakingCall::WithdrawUnbonded(num_slashing_spans)) } - fn balances_transfer_keep_alive(to: Self::AccountId, amount: Self::Balance) -> Self::RelayChainCall { - RelayChainCall::Balances(BalancesCall::TransferKeepAlive(RelayChainLookup::unlookup(to), amount)) + fn balances_transfer_keep_alive(to: Self::AccountId, amount: Self::Balance) -> RCC { + RCC::balances(BalancesCall::TransferKeepAlive(RelayChainLookup::unlookup(to), amount)) } - fn finalize_call_into_xcm_message( - call: Self::RelayChainCall, - extra_fee: Self::Balance, - weight: XcmWeight, - ) -> Xcm<()> { + fn xcm_pallet_reserve_transfer_assets( + dest: MultiLocation, + beneficiary: MultiLocation, + assets: MultiAssets, + fee_assets_item: u32, + ) -> RCC { + RCC::xcm_pallet(XcmCall::ReserveTransferAssets( + dest.into_versioned(), + beneficiary.into_versioned(), + assets.into(), + fee_assets_item, + )) + } + + fn proxy_call(real: Self::AccountId, call: RCC) -> RCC { + RCC::proxy(ProxyCall::Proxy(RelayChainLookup::unlookup(real), None, call)) + } + + fn finalize_call_into_xcm_message(call: RCC, extra_fee: Self::Balance, weight: XcmWeight) -> Xcm<()> { let asset = MultiAsset { id: Concrete(MultiLocation::here()), fun: Fungibility::Fungible(extra_fee), @@ -199,10 +187,7 @@ impl> CallBuilder for RelayChainCallBuilder, - extra_fee: Self::Balance, - ) -> Xcm<()> { + fn finalize_multiple_calls_into_xcm_message(calls: Vec<(RCC, XcmWeight)>, extra_fee: Self::Balance) -> Xcm<()> { let asset = MultiAsset { id: Concrete(MultiLocation::here()), fun: Fungibility::Fungible(extra_fee), @@ -239,22 +224,4 @@ impl> CallBuilder for RelayChainCallBuilder Self::RelayChainCall { - RelayChainCall::XcmPallet(XcmCall::ReserveTransferAssets( - dest.into_versioned(), - beneficiary.into_versioned(), - assets.into(), - fee_assets_item, - )) - } - - fn proxy_call(real: Self::AccountId, call: Self::RelayChainCall) -> Self::RelayChainCall { - RelayChainCall::Proxy(Box::new(ProxyCall::Proxy(RelayChainLookup::unlookup(real), None, call))) - } } diff --git a/modules/support/src/lib.rs b/modules/support/src/lib.rs index 164ae2e3f7..aaaa73ed2a 100644 --- a/modules/support/src/lib.rs +++ b/modules/support/src/lib.rs @@ -21,14 +21,13 @@ #![allow(clippy::from_over_into)] #![allow(clippy::type_complexity)] -use codec::FullCodec; use frame_support::pallet_prelude::{DispatchClass, Pays, Weight}; use primitives::{task::TaskResult, Balance, CurrencyId, Multiplier, Nonce, ReserveIdentifier}; use sp_runtime::{ traits::CheckedDiv, transaction_validity::TransactionValidityError, DispatchError, DispatchResult, FixedU128, }; use sp_std::{prelude::*, result::Result}; -use xcm::{prelude::*, v3::Weight as XcmWeight}; +use xcm::prelude::*; pub mod bounded; pub mod dex; @@ -38,6 +37,7 @@ pub mod honzon; pub mod incentives; pub mod liquid_crowdloan; pub mod mocks; +pub mod relaychain; pub mod stable_asset; pub use crate::bounded::*; @@ -133,78 +133,6 @@ pub trait TransactionPayment { fn apply_multiplier_to_fee(fee: Balance, multiplier: Option) -> Balance; } -pub trait CallBuilder { - type AccountId: FullCodec; - type Balance: FullCodec; - type RelayChainCall: FullCodec; - - /// Execute a call, replacing the `Origin` with a sub-account. - /// params: - /// - call: The call to be executed. - /// - index: The index of sub-account to be used as the new origin. - fn utility_as_derivative_call(call: Self::RelayChainCall, index: u16) -> Self::RelayChainCall; - - /// Bond extra on relay-chain. - /// params: - /// - amount: The amount of staking currency to bond. - fn staking_bond_extra(amount: Self::Balance) -> Self::RelayChainCall; - - /// Unbond on relay-chain. - /// params: - /// - amount: The amount of staking currency to unbond. - fn staking_unbond(amount: Self::Balance) -> Self::RelayChainCall; - - /// Withdraw unbonded staking on the relay-chain. - /// params: - /// - num_slashing_spans: The number of slashing spans to withdraw from. - fn staking_withdraw_unbonded(num_slashing_spans: u32) -> Self::RelayChainCall; - - /// Transfer Staking currency to another account, disallowing "death". - /// params: - /// - to: The destination for the transfer - /// - amount: The amount of staking currency to be transferred. - fn balances_transfer_keep_alive(to: Self::AccountId, amount: Self::Balance) -> Self::RelayChainCall; - - /// Wrap the final call into the Xcm format. - /// params: - /// - call: The call to be executed - /// - extra_fee: Extra fee (in staking currency) used for buy the `weight`. - /// - weight: the weight limit used for XCM. - fn finalize_call_into_xcm_message( - call: Self::RelayChainCall, - extra_fee: Self::Balance, - weight: XcmWeight, - ) -> Xcm<()>; - - /// Wrap the final multiple calls into the Xcm format. - /// params: - /// - calls: the multiple calls and its weight limit to be executed - /// - extra_fee: Extra fee (in staking currency) used for buy the `weight`. - fn finalize_multiple_calls_into_xcm_message( - calls: Vec<(Self::RelayChainCall, XcmWeight)>, - extra_fee: Self::Balance, - ) -> Xcm<()>; - - /// Reserve transfer assets. - /// params: - /// - dest: The destination chain. - /// - beneficiary: The beneficiary. - /// - assets: The assets to be transferred. - /// - fee_assets_item: The index of assets for fees. - fn xcm_pallet_reserve_transfer_assets( - dest: MultiLocation, - beneficiary: MultiLocation, - assets: MultiAssets, - fee_assets_item: u32, - ) -> Self::RelayChainCall; - - /// Proxy a call with a `real` account without a forced proxy type. - /// params: - /// - real: The real account. - /// - call: The call to be executed. - fn proxy_call(real: Self::AccountId, call: Self::RelayChainCall) -> Self::RelayChainCall; -} - /// Dispatchable tasks pub trait DispatchableTask { fn dispatch(self, weight: Weight) -> TaskResult; diff --git a/modules/support/src/relaychain.rs b/modules/support/src/relaychain.rs new file mode 100644 index 0000000000..bb4ddc233d --- /dev/null +++ b/modules/support/src/relaychain.rs @@ -0,0 +1,156 @@ +// This file is part of Acala. + +// Copyright (C) 2020-2023 Acala Foundation. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +// * Since XCM V3, relaychain configs 'SafeCallFilter' to filter the call in Transact: +// * https://github.com/paritytech/polkadot/blob/master/runtime/polkadot/src/xcm_config.rs + +use codec::{Decode, Encode, FullCodec}; +use frame_support::RuntimeDebug; +use primitives::{AccountId, Balance}; +use sp_runtime::traits::{AccountIdLookup, StaticLookup}; +use sp_std::prelude::*; +use xcm::{prelude::*, v3::Weight as XcmWeight}; + +#[derive(Encode, Decode, RuntimeDebug)] +pub enum BalancesCall { + #[codec(index = 3)] + TransferKeepAlive(::Source, #[codec(compact)] Balance), +} + +#[derive(Encode, Decode, RuntimeDebug)] +pub enum UtilityCall { + #[codec(index = 1)] + AsDerivative(u16, RCC), +} + +#[derive(Encode, Decode, RuntimeDebug)] +pub enum StakingCall { + #[codec(index = 1)] + BondExtra(#[codec(compact)] Balance), /* TODO: because param type in relaychain is u64, need to confirm + * Balance(u128) is working. */ + #[codec(index = 2)] + Unbond(#[codec(compact)] Balance), /* TODO: because param type in relaychain is u64, need to confirm + * Balance(u128) is working. */ + #[codec(index = 3)] + WithdrawUnbonded(u32), +} + +/// `pallet-xcm` calls. +#[derive(Encode, Decode, RuntimeDebug)] +pub enum XcmCall { + /// `reserve_transfer_assets(dest, beneficiary, assets, fee_asset_item)` call. + #[codec(index = 2)] + ReserveTransferAssets( + VersionedMultiLocation, + VersionedMultiLocation, + VersionedMultiAssets, + u32, + ), +} + +// Same to `Polkadot` and `Kusama` runtime `Lookup` config. +pub type RelayChainLookup = AccountIdLookup; + +/// `pallet-proxy` calls. +#[derive(Encode, Decode, RuntimeDebug)] +pub enum ProxyCall { + /// `proxy(real, force_proxy_type, call)` call. Force proxy type is not supported and + /// is always set to `None`. + #[codec(index = 0)] + Proxy(::Source, Option<()>, RCC), +} + +pub trait RelayChainCall: Sized { + fn balances(call: BalancesCall) -> Self; + fn staking(call: StakingCall) -> Self; + fn utility(call: UtilityCall) -> Self; + fn proxy(call: ProxyCall) -> Self; + fn xcm_pallet(call: XcmCall) -> Self; +} + +pub trait CallBuilder { + type AccountId: FullCodec; + type Balance: FullCodec; + type RelayChainCall: FullCodec + RelayChainCall; + + /// Execute a call, replacing the `Origin` with a sub-account. + /// params: + /// - call: The call to be executed. + /// - index: The index of sub-account to be used as the new origin. + fn utility_as_derivative_call(call: Self::RelayChainCall, index: u16) -> Self::RelayChainCall; + + /// Bond extra on relay-chain. + /// params: + /// - amount: The amount of staking currency to bond. + fn staking_bond_extra(amount: Self::Balance) -> Self::RelayChainCall; + + /// Unbond on relay-chain. + /// params: + /// - amount: The amount of staking currency to unbond. + fn staking_unbond(amount: Self::Balance) -> Self::RelayChainCall; + + /// Withdraw unbonded staking on the relay-chain. + /// params: + /// - num_slashing_spans: The number of slashing spans to withdraw from. + fn staking_withdraw_unbonded(num_slashing_spans: u32) -> Self::RelayChainCall; + + /// Transfer Staking currency to another account, disallowing "death". + /// params: + /// - to: The destination for the transfer + /// - amount: The amount of staking currency to be transferred. + fn balances_transfer_keep_alive(to: Self::AccountId, amount: Self::Balance) -> Self::RelayChainCall; + + /// Reserve transfer assets. + /// params: + /// - dest: The destination chain. + /// - beneficiary: The beneficiary. + /// - assets: The assets to be transferred. + /// - fee_assets_item: The index of assets for fees. + fn xcm_pallet_reserve_transfer_assets( + dest: MultiLocation, + beneficiary: MultiLocation, + assets: MultiAssets, + fee_assets_item: u32, + ) -> Self::RelayChainCall; + + /// Proxy a call with a `real` account without a forced proxy type. + /// params: + /// - real: The real account. + /// - call: The call to be executed. + fn proxy_call(real: Self::AccountId, call: Self::RelayChainCall) -> Self::RelayChainCall; + + /// Wrap the final call into the Xcm format. + /// params: + /// - call: The call to be executed + /// - extra_fee: Extra fee (in staking currency) used for buy the `weight`. + /// - weight: the weight limit used for XCM. + fn finalize_call_into_xcm_message( + call: Self::RelayChainCall, + extra_fee: Self::Balance, + weight: XcmWeight, + ) -> Xcm<()>; + + /// Wrap the final multiple calls into the Xcm format. + /// params: + /// - calls: the multiple calls and its weight limit to be executed + /// - extra_fee: Extra fee (in staking currency) used for buy the `weight`. + fn finalize_multiple_calls_into_xcm_message( + calls: Vec<(Self::RelayChainCall, XcmWeight)>, + extra_fee: Self::Balance, + ) -> Xcm<()>; +} diff --git a/modules/xcm-interface/Cargo.toml b/modules/xcm-interface/Cargo.toml index d64cf64267..a40432ae57 100644 --- a/modules/xcm-interface/Cargo.toml +++ b/modules/xcm-interface/Cargo.toml @@ -20,14 +20,18 @@ orml-traits = { path = "../../orml/traits", default-features = false } module-support = { path = "../../modules/support", default-features = false } [dev-dependencies] -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0" } -module-currencies = { path = "../../modules/currencies" } -orml-tokens = { path = "../../orml/tokens" } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v1.0.0" } +insta = { version = "1.31.0" } + cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v1.0.0" } -module-relaychain = { path = "../relaychain", features = ["polkadot"] } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v1.0.0" } xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v1.0.0" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v1.0.0" } + +orml-tokens = { path = "../../orml/tokens" } + +module-currencies = { path = "../../modules/currencies" } +module-relaychain = { path = "../relaychain" } [features] default = ["std"] diff --git a/modules/xcm-interface/src/lib.rs b/modules/xcm-interface/src/lib.rs index a04b0b54e2..73cedea50a 100644 --- a/modules/xcm-interface/src/lib.rs +++ b/modules/xcm-interface/src/lib.rs @@ -29,7 +29,7 @@ use frame_support::{log, pallet_prelude::*, traits::Get}; use frame_system::pallet_prelude::*; -use module_support::{CallBuilder, CrowdloanVaultXcm, HomaSubAccountXcm}; +use module_support::{relaychain::CallBuilder, CrowdloanVaultXcm, HomaSubAccountXcm}; use orml_traits::XcmTransfer; use primitives::{Balance, CurrencyId, EraIndex}; use scale_info::TypeInfo; @@ -37,10 +37,9 @@ use sp_runtime::traits::Convert; use sp_std::{convert::From, prelude::*, vec, vec::Vec}; use xcm::{prelude::*, v3::Weight as XcmWeight}; -mod mock; +mod mocks; mod tests; -pub mod migrations; pub use module::*; #[frame_support::pallet] @@ -172,7 +171,38 @@ pub mod module { } } - impl Pallet {} + impl Pallet { + pub fn build_transfer_to_liquid_crowdloan_module_account( + vault: T::AccountId, + recipient: T::AccountId, + amount: Balance, + ) -> Result, DispatchError> { + let (xcm_dest_weight, xcm_fee) = + Self::xcm_dest_weight_and_fee(XcmInterfaceOperation::ProxyReserveTransferAssets); + + // self location is relative to self + let loc = T::SelfLocation::get(); + // we need to reanchor it to the parent becuase the call is dispatched on parent + let loc = loc + .reanchored(&MultiLocation::new(1, Here), Here) + .map_err(|_| Error::::XcmFailed)?; + + let proxy_call = T::RelayChainCallBuilder::proxy_call( + vault, + T::RelayChainCallBuilder::xcm_pallet_reserve_transfer_assets( + loc, + T::AccountIdToMultiLocation::convert(recipient), + // Note this message is executed in the relay chain context. + vec![(Concrete(Here.into()), amount).into()].into(), + 0, + ), + ); + let xcm_message = + T::RelayChainCallBuilder::finalize_call_into_xcm_message(proxy_call, xcm_fee, xcm_dest_weight); + + Ok(xcm_message) + } + } impl HomaSubAccountXcm for Pallet { /// Cross-chain transfer staking currency to sub account on relaychain. @@ -292,21 +322,8 @@ pub mod module { recipient: T::AccountId, amount: Balance, ) -> DispatchResult { - let (xcm_dest_weight, xcm_fee) = - Self::xcm_dest_weight_and_fee(XcmInterfaceOperation::ProxyReserveTransferAssets); - - let proxy_call = T::RelayChainCallBuilder::proxy_call( - vault.clone(), - T::RelayChainCallBuilder::xcm_pallet_reserve_transfer_assets( - T::SelfLocation::get(), - T::AccountIdToMultiLocation::convert(recipient.clone()), - // Note this message is executed in the relay chain context. - vec![(Concrete(Here.into()), amount).into()].into(), - 0, - ), - ); let xcm_message = - T::RelayChainCallBuilder::finalize_call_into_xcm_message(proxy_call, xcm_fee, xcm_dest_weight); + Self::build_transfer_to_liquid_crowdloan_module_account(vault.clone(), recipient.clone(), amount)?; let result = pallet_xcm::Pallet::::send_xcm(Here, Parent, xcm_message); log::debug!( diff --git a/modules/xcm-interface/src/migrations.rs b/modules/xcm-interface/src/migrations.rs deleted file mode 100644 index ed05295b43..0000000000 --- a/modules/xcm-interface/src/migrations.rs +++ /dev/null @@ -1,84 +0,0 @@ -// This file is part of Acala. - -// Copyright (C) 2020-2023 Acala Foundation. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -// This file is used for migration MultiLocation and XcmWeight storage -use crate::*; -use frame_support::{log, migration::storage_key_iter, traits::OnRuntimeUpgrade, StoragePrefixedMap}; -use sp_std::marker::PhantomData; -pub use xcm::v2::{MultiLocation as OldMultiLocation, Weight as OldXcmWeight}; - -#[derive(Encode, Decode, Eq, PartialEq, Clone, RuntimeDebug, TypeInfo)] -pub enum OldXcmInterfaceOperation { - // XTokens - XtokensTransfer, - // Homa - HomaWithdrawUnbonded, - HomaBondExtra, - HomaUnbond, - // Parachain fee with location info - ParachainFee(Box), -} - -impl TryInto for OldXcmInterfaceOperation { - type Error = (); - fn try_into(self) -> sp_std::result::Result { - let data = match self { - OldXcmInterfaceOperation::XtokensTransfer => XcmInterfaceOperation::XtokensTransfer, - OldXcmInterfaceOperation::HomaWithdrawUnbonded => XcmInterfaceOperation::HomaWithdrawUnbonded, - OldXcmInterfaceOperation::HomaBondExtra => XcmInterfaceOperation::HomaBondExtra, - OldXcmInterfaceOperation::HomaUnbond => XcmInterfaceOperation::HomaUnbond, - OldXcmInterfaceOperation::ParachainFee(old_multilocation) => { - let v3_multilocation: MultiLocation = - (*old_multilocation).try_into().expect("Stored xcm::v2::MultiLocation"); - XcmInterfaceOperation::ParachainFee(Box::new(v3_multilocation)) - } - }; - Ok(data) - } -} - -/// Migrate both key type and value type of XcmDestWeightAndFee. -pub struct MigrateXcmDestWeightAndFee(PhantomData); -impl OnRuntimeUpgrade for MigrateXcmDestWeightAndFee { - fn on_runtime_upgrade() -> Weight { - log::info!( - target: "xcm-interface", - "MigrateXcmDestWeightAndFee::on_runtime_upgrade execute, will migrate the OldMultiLocation to v3 MultiLocation in - XcmInterfaceOperation::ParachainFee(Box) key type, and migrate OldXcmWeight to v3 XcmWeight in the value tuple.", - ); - - let mut weight: Weight = Weight::zero(); - - let module_prefix = XcmDestWeightAndFee::::module_prefix(); - let storage_prefix = XcmDestWeightAndFee::::storage_prefix(); - let old_data = storage_key_iter::( - module_prefix, - storage_prefix, - ) - .drain() - .collect::>(); - for (old_key, old_value) in old_data { - weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1)); - let new_key: XcmInterfaceOperation = old_key.try_into().expect("Stored xcm::v2::MultiLocation"); - let new_value: (XcmWeight, Balance) = (XcmWeight::from_parts(old_value.0, 128 * 1024), old_value.1); - XcmDestWeightAndFee::::insert(new_key, new_value); - } - - weight - } -} diff --git a/modules/xcm-interface/src/mocks/kusama.rs b/modules/xcm-interface/src/mocks/kusama.rs new file mode 100644 index 0000000000..43759cd700 --- /dev/null +++ b/modules/xcm-interface/src/mocks/kusama.rs @@ -0,0 +1,21 @@ +// This file is part of Acala. + +// Copyright (C) 2020-2023 Acala Foundation. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use super::*; + +impl_mock!(module_relaychain::KusamaRelayChainCall); diff --git a/modules/xcm-interface/src/mock.rs b/modules/xcm-interface/src/mocks/mod.rs similarity index 56% rename from modules/xcm-interface/src/mock.rs rename to modules/xcm-interface/src/mocks/mod.rs index 65ca9a00df..7cf663d2c2 100644 --- a/modules/xcm-interface/src/mock.rs +++ b/modules/xcm-interface/src/mocks/mod.rs @@ -16,8 +16,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! Mocks for the prices module. - #![cfg(test)] use super::*; @@ -33,53 +31,15 @@ use sp_core::H256; use sp_runtime::{traits::IdentityLookup, AccountId32, BuildStorage}; use xcm_builder::{EnsureXcmOrigin, FixedWeightBounds, SignedToAccountId32}; +pub mod kusama; +pub mod polkadot; + pub type AccountId = AccountId32; pub const ALICE: AccountId = AccountId32::new([1u8; 32]); +pub const BOB: AccountId = AccountId32::new([2u8; 32]); pub const DOT: CurrencyId = CurrencyId::Token(TokenSymbol::DOT); -impl frame_system::Config for Runtime { - type RuntimeOrigin = RuntimeOrigin; - type Nonce = u64; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = ::sp_runtime::traits::BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Block = Block; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type BlockWeights = (); - type BlockLength = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type DbWeight = (); - type BaseCallFilter = Everything; - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; -} - -impl pallet_balances::Config for Runtime { - type Balance = Balance; - type DustRemoval = (); - type RuntimeEvent = RuntimeEvent; - type ExistentialDeposit = ConstU128<1>; - type AccountStore = System; - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type WeightInfo = (); - type RuntimeHoldReason = (); - type FreezeIdentifier = (); - type MaxHolds = (); - type MaxFreezes = (); -} - parameter_types! { pub const UnitWeightCost: XcmWeight = XcmWeight::from_parts(10, 10); pub const BaseXcmWeight: XcmWeight = XcmWeight::from_parts(100_000_000, 100_000_000); @@ -93,41 +53,11 @@ parameter_types! { X1(Parachain(2000).into()); } -pub type LocalOriginToLocation = SignedToAccountId32; - #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); } -impl pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = (); - type ExecuteXcmOrigin = EnsureXcmOrigin; - type XcmExecuteFilter = Everything; - type XcmExecutor = (); - type XcmTeleportFilter = Nothing; - type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = (); - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; - type MaxRemoteLockConsumers = ConstU32<0>; - type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; -} - ord_parameter_types! { pub const One: AccountId = ALICE; } @@ -222,29 +152,105 @@ impl Convert for AccountIdToMultiLocation { } } -impl Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type UpdateOrigin = EnsureSignedBy; - type StakingCurrencyId = GetStakingCurrencyId; - type ParachainAccount = ParachainAccount; - type RelayChainUnbondingSlashingSpans = ConstU32<28>; - type SovereignSubAccountLocationConvert = SubAccountIndexMultiLocationConvertor; - type RelayChainCallBuilder = module_relaychain::RelayChainCallBuilder; - type XcmTransfer = MockXcmTransfer; - type SelfLocation = SelfLocation; - type AccountIdToMultiLocation = AccountIdToMultiLocation; -} - -type Block = frame_system::mocking::MockBlock; - -construct_runtime!( - pub enum Runtime { - System: frame_system, - Balances: pallet_balances, - PolkadotXcm: pallet_xcm, - XcmInterface: xcm_interface, +#[macro_export] +macro_rules! impl_mock { + ($relaychain:ty) => { + pub type LocalOriginToLocation = SignedToAccountId32; + pub type Block = frame_system::mocking::MockBlock; + + impl frame_system::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type Nonce = u64; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = ::sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type BlockWeights = (); + type BlockLength = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type DbWeight = (); + type BaseCallFilter = Everything; + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; + } + + impl pallet_balances::Config for Runtime { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU128<1>; + type AccountStore = System; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); + type RuntimeHoldReason = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); + } + + impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = (); + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = (); + type XcmTeleportFilter = Nothing; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type TrustedLockers = (); + type SovereignAccountOf = (); + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + } + + impl Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type UpdateOrigin = EnsureSignedBy; + type StakingCurrencyId = GetStakingCurrencyId; + type ParachainAccount = ParachainAccount; + type RelayChainUnbondingSlashingSpans = ConstU32<28>; + type SovereignSubAccountLocationConvert = SubAccountIndexMultiLocationConvertor; + type RelayChainCallBuilder = module_relaychain::RelayChainCallBuilder; + type XcmTransfer = MockXcmTransfer; + type SelfLocation = SelfLocation; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + } + + construct_runtime!( + pub enum Runtime { + System: frame_system, + Balances: pallet_balances, + PolkadotXcm: pallet_xcm, + XcmInterface: xcm_interface, + } + ); } -); +} pub struct ExtBuilder; @@ -255,13 +261,13 @@ impl Default for ExtBuilder { } impl ExtBuilder { - pub fn build(self) -> sp_io::TestExternalities { + pub fn build(self) -> sp_io::TestExternalities { let t = frame_system::GenesisConfig::::default() .build_storage() .unwrap(); let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); + ext.execute_with(|| frame_system::Pallet::::set_block_number(1u32.into())); ext } } diff --git a/modules/xcm-interface/src/mocks/polkadot.rs b/modules/xcm-interface/src/mocks/polkadot.rs new file mode 100644 index 0000000000..4e18997795 --- /dev/null +++ b/modules/xcm-interface/src/mocks/polkadot.rs @@ -0,0 +1,21 @@ +// This file is part of Acala. + +// Copyright (C) 2020-2023 Acala Foundation. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use super::*; + +impl_mock!(module_relaychain::PolkadotRelayChainCall); diff --git a/modules/xcm-interface/src/snapshots/module_xcm_interface__tests__build_transfer_to_liquid_crowdloan_module_account_kusama.snap b/modules/xcm-interface/src/snapshots/module_xcm_interface__tests__build_transfer_to_liquid_crowdloan_module_account_kusama.snap new file mode 100644 index 0000000000..efcd77cbcf --- /dev/null +++ b/modules/xcm-interface/src/snapshots/module_xcm_interface__tests__build_transfer_to_liquid_crowdloan_module_account_kusama.snap @@ -0,0 +1,161 @@ +--- +source: modules/xcm-interface/src/tests.rs +expression: xcm +--- +Xcm( + [ + WithdrawAsset( + MultiAssets( + [ + MultiAsset { + id: Concrete( + MultiLocation { + parents: 0, + interior: Here, + }, + ), + fun: Fungible( + 0, + ), + }, + ], + ), + ), + BuyExecution { + fees: MultiAsset { + id: Concrete( + MultiLocation { + parents: 0, + interior: Here, + }, + ), + fun: Fungible( + 0, + ), + }, + weight_limit: Unlimited, + }, + Transact { + origin_kind: SovereignAccount, + require_weight_at_most: Weight { + ref_time: 0, + proof_size: 0, + }, + call: [ + 30, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 99, + 2, + 3, + 0, + 1, + 0, + 65, + 31, + 3, + 0, + 1, + 1, + 0, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 3, + 4, + 0, + 0, + 0, + 0, + 7, + 0, + 16, + 165, + 212, + 232, + 0, + 0, + 0, + 0, + ], + }, + RefundSurplus, + DepositAsset { + assets: Wild( + AllCounted( + 1, + ), + ), + beneficiary: MultiLocation { + parents: 0, + interior: X1( + Parachain( + 2000, + ), + ), + }, + }, + ], +) diff --git a/modules/xcm-interface/src/snapshots/module_xcm_interface__tests__build_transfer_to_liquid_crowdloan_module_account_polkadot.snap b/modules/xcm-interface/src/snapshots/module_xcm_interface__tests__build_transfer_to_liquid_crowdloan_module_account_polkadot.snap new file mode 100644 index 0000000000..7c9758d0fc --- /dev/null +++ b/modules/xcm-interface/src/snapshots/module_xcm_interface__tests__build_transfer_to_liquid_crowdloan_module_account_polkadot.snap @@ -0,0 +1,161 @@ +--- +source: modules/xcm-interface/src/tests.rs +expression: xcm +--- +Xcm( + [ + WithdrawAsset( + MultiAssets( + [ + MultiAsset { + id: Concrete( + MultiLocation { + parents: 0, + interior: Here, + }, + ), + fun: Fungible( + 0, + ), + }, + ], + ), + ), + BuyExecution { + fees: MultiAsset { + id: Concrete( + MultiLocation { + parents: 0, + interior: Here, + }, + ), + fun: Fungible( + 0, + ), + }, + weight_limit: Unlimited, + }, + Transact { + origin_kind: SovereignAccount, + require_weight_at_most: Weight { + ref_time: 0, + proof_size: 0, + }, + call: [ + 29, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 99, + 2, + 3, + 0, + 1, + 0, + 65, + 31, + 3, + 0, + 1, + 1, + 0, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 3, + 4, + 0, + 0, + 0, + 0, + 7, + 0, + 16, + 165, + 212, + 232, + 0, + 0, + 0, + 0, + ], + }, + RefundSurplus, + DepositAsset { + assets: Wild( + AllCounted( + 1, + ), + ), + beneficiary: MultiLocation { + parents: 0, + interior: X1( + Parachain( + 2000, + ), + ), + }, + }, + ], +) diff --git a/modules/xcm-interface/src/tests.rs b/modules/xcm-interface/src/tests.rs index af438ffcb5..20c9d6fbf4 100644 --- a/modules/xcm-interface/src/tests.rs +++ b/modules/xcm-interface/src/tests.rs @@ -20,86 +20,23 @@ #![cfg(test)] -use super::*; -use crate::migrations::{MigrateXcmDestWeightAndFee, OldMultiLocation, OldXcmInterfaceOperation, OldXcmWeight}; -use crate::mock::{ExtBuilder, Runtime}; -use frame_support::{ - storage::migration::{get_storage_value, put_storage_value}, - traits::OnRuntimeUpgrade, - StorageHasher, StoragePrefixedMap, -}; +use crate::mocks::{kusama, polkadot, ExtBuilder, ALICE, BOB}; +use insta::assert_debug_snapshot; #[test] -fn simulate_migrate_xcm_dest_weight_and_fee() { - ExtBuilder::default().build().execute_with(|| { - let module_prefix = XcmDestWeightAndFee::::module_prefix(); - let storage_prefix = XcmDestWeightAndFee::::storage_prefix(); - - let old_key_1: OldXcmInterfaceOperation = OldXcmInterfaceOperation::XtokensTransfer; - let old_value_1: (OldXcmWeight, Balance) = (1_000_000_000, 200_000_000); - let old_key_2: OldXcmInterfaceOperation = OldXcmInterfaceOperation::ParachainFee(Box::new( - OldMultiLocation::new(1, xcm::v2::Junctions::X1(xcm::v2::Junction::Parachain(1000))), - )); - let old_value_2: (OldXcmWeight, Balance) = (2_000_000_000, 500_000_000); - let new_key_1: XcmInterfaceOperation = XcmInterfaceOperation::XtokensTransfer; - let new_value_1: (XcmWeight, Balance) = (XcmWeight::from_parts(1_000_000_000, 1024 * 128), 200_000_000); - let new_key_2: XcmInterfaceOperation = - XcmInterfaceOperation::ParachainFee(Box::new(MultiLocation::new(1, X1(Parachain(1000))))); - let new_value_2: (XcmWeight, Balance) = (XcmWeight::from_parts(2_000_000_000, 1024 * 128), 500_000_000); - - // put old raw storage - put_storage_value( - module_prefix, - storage_prefix, - &Twox64Concat::hash(&old_key_1.encode()), - old_value_1, - ); - put_storage_value( - module_prefix, - storage_prefix, - &Twox64Concat::hash(&old_key_2.encode()), - old_value_2, - ); - assert_eq!( - get_storage_value::<(OldXcmWeight, Balance)>( - module_prefix, - storage_prefix, - &Twox64Concat::hash(&old_key_1.encode()), - ), - Some(old_value_1) - ); - assert_eq!( - get_storage_value::<(OldXcmWeight, Balance)>( - module_prefix, - storage_prefix, - &Twox64Concat::hash(&old_key_2.encode()), - ), - Some(old_value_2) - ); - - // Run migration - assert_eq!( - MigrateXcmDestWeightAndFee::::on_runtime_upgrade(), - <::DbWeight as Get>::get() - .reads_writes(2, 2) - ); - assert_eq!( - get_storage_value::<(XcmWeight, Balance)>( - module_prefix, - storage_prefix, - &Twox64Concat::hash(&new_key_1.encode()), - ), - Some(new_value_1) - ); - assert_eq!( - get_storage_value::<(XcmWeight, Balance)>( - module_prefix, - storage_prefix, - &Twox64Concat::hash(&new_key_2.encode()), - ), - Some(new_value_2) - ); +fn build_transfer_to_liquid_crowdloan_module_account_polkadot() { + ExtBuilder::default().build::().execute_with(|| { + let xcm = polkadot::XcmInterface::build_transfer_to_liquid_crowdloan_module_account(ALICE, BOB, 1000000000000) + .unwrap(); + assert_debug_snapshot!(xcm); }); } -// TODO: other unit tests +#[test] +fn build_transfer_to_liquid_crowdloan_module_account_kusama() { + ExtBuilder::default().build::().execute_with(|| { + let xcm = + kusama::XcmInterface::build_transfer_to_liquid_crowdloan_module_account(ALICE, BOB, 1000000000000).unwrap(); + assert_debug_snapshot!(xcm); + }); +} diff --git a/runtime/acala/Cargo.toml b/runtime/acala/Cargo.toml index 6187c079c0..7c45438d01 100644 --- a/runtime/acala/Cargo.toml +++ b/runtime/acala/Cargo.toml @@ -114,7 +114,7 @@ module-liquid-crowdloan = { path = "../../modules/liquid-crowdloan", default-fea module-loans = { path = "../../modules/loans", default-features = false } module-nft = { path = "../../modules/nft", default-features = false } module-prices = { path = "../../modules/prices", default-features = false } -module-relaychain = { path = "../../modules/relaychain", default-features = false, features = ["polkadot"] } +module-relaychain = { path = "../../modules/relaychain", default-features = false } module-session-manager = { path = "../../modules/session-manager", default-features = false } module-support = { path = "../../modules/support", default-features = false } module-transaction-pause = { path = "../../modules/transaction-pause", default-features = false } diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs index 2625c191ec..515a9ad5df 100644 --- a/runtime/acala/src/lib.rs +++ b/runtime/acala/src/lib.rs @@ -1560,7 +1560,7 @@ impl module_xcm_interface::Config for Runtime { type ParachainAccount = ParachainAccount; type RelayChainUnbondingSlashingSpans = ConstU32<5>; type SovereignSubAccountLocationConvert = SubAccountIndexMultiLocationConvertor; - type RelayChainCallBuilder = RelayChainCallBuilder; + type RelayChainCallBuilder = RelayChainCallBuilder; type XcmTransfer = XTokens; type SelfLocation = xcm_config::SelfLocation; type AccountIdToMultiLocation = runtime_common::xcm_config::AccountIdToMultiLocation; diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index 42d4624c66..6612a30a53 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -138,17 +138,14 @@ no_std = [] with-mandala-runtime = [ "mandala-runtime", "acala-service/with-mandala-runtime", - "module-relaychain/polkadot" ] with-karura-runtime = [ "karura-runtime", "acala-service/with-karura-runtime", - "module-relaychain/kusama" ] with-acala-runtime = [ "acala-runtime", "acala-service/with-acala-runtime", - "module-relaychain/polkadot" ] with-ethereum-compatibility = [ "mandala-runtime", diff --git a/runtime/karura/Cargo.toml b/runtime/karura/Cargo.toml index 18845b9230..4b9ae6ef9a 100644 --- a/runtime/karura/Cargo.toml +++ b/runtime/karura/Cargo.toml @@ -114,7 +114,7 @@ module-incentives = { path = "../../modules/incentives", default-features = fals module-loans = { path = "../../modules/loans", default-features = false } module-nft = { path = "../../modules/nft", default-features = false } module-prices = { path = "../../modules/prices", default-features = false } -module-relaychain = { path = "../../modules/relaychain", default-features = false, features = ["kusama"] } +module-relaychain = { path = "../../modules/relaychain", default-features = false } module-session-manager = { path = "../../modules/session-manager", default-features = false } module-support = { path = "../../modules/support", default-features = false } module-transaction-pause = { path = "../../modules/transaction-pause", default-features = false } diff --git a/runtime/karura/src/lib.rs b/runtime/karura/src/lib.rs index b2f162e10f..4e532f9ed7 100644 --- a/runtime/karura/src/lib.rs +++ b/runtime/karura/src/lib.rs @@ -1574,7 +1574,7 @@ impl module_xcm_interface::Config for Runtime { type ParachainAccount = ParachainAccount; type RelayChainUnbondingSlashingSpans = ConstU32<5>; type SovereignSubAccountLocationConvert = SubAccountIndexMultiLocationConvertor; - type RelayChainCallBuilder = RelayChainCallBuilder; + type RelayChainCallBuilder = RelayChainCallBuilder; type XcmTransfer = XTokens; type SelfLocation = xcm_config::SelfLocation; type AccountIdToMultiLocation = runtime_common::xcm_config::AccountIdToMultiLocation; diff --git a/runtime/mandala/Cargo.toml b/runtime/mandala/Cargo.toml index 35c0ec0f40..02806636c8 100644 --- a/runtime/mandala/Cargo.toml +++ b/runtime/mandala/Cargo.toml @@ -123,7 +123,7 @@ module-homa = { path = "../../modules/homa", default-features = false } module-xcm-interface = { path = "../../modules/xcm-interface", default-features = false } module-nominees-election = { path = "../../modules/nominees-election", default-features = false } module-session-manager = { path = "../../modules/session-manager", default-features = false } -module-relaychain = { path = "../../modules/relaychain", default-features = false, features = ["polkadot"]} +module-relaychain = { path = "../../modules/relaychain", default-features = false } module-idle-scheduler = { path = "../../modules/idle-scheduler", default-features = false } module-aggregated-dex = { path = "../../modules/aggregated-dex", default-features = false } module-liquid-crowdloan = { path = "../../modules/liquid-crowdloan", default-features = false } diff --git a/runtime/mandala/src/lib.rs b/runtime/mandala/src/lib.rs index 80eaa39545..c4683cb19a 100644 --- a/runtime/mandala/src/lib.rs +++ b/runtime/mandala/src/lib.rs @@ -1419,7 +1419,7 @@ impl module_xcm_interface::Config for Runtime { type ParachainAccount = ParachainAccount; type RelayChainUnbondingSlashingSpans = ConstU32<5>; type SovereignSubAccountLocationConvert = SubAccountIndexMultiLocationConvertor; - type RelayChainCallBuilder = RelayChainCallBuilder; + type RelayChainCallBuilder = RelayChainCallBuilder; type XcmTransfer = XTokens; type SelfLocation = xcm_config::SelfLocation; type AccountIdToMultiLocation = xcm_config::AccountIdToMultiLocation;