diff --git a/orml b/orml index d69f226e33..4177cd6961 160000 --- a/orml +++ b/orml @@ -1 +1 @@ -Subproject commit d69f226e332ae29b7b33d53d2f06f309d2986ea0 +Subproject commit 4177cd6961ff6dd0c7d80ff713ed4839b466cae8 diff --git a/runtime/integration-tests/src/relaychain/kusama_cross_chain_transfer.rs b/runtime/integration-tests/src/relaychain/kusama_cross_chain_transfer.rs index b1ad6c02e8..bcf95ebd3a 100644 --- a/runtime/integration-tests/src/relaychain/kusama_cross_chain_transfer.rs +++ b/runtime/integration-tests/src/relaychain/kusama_cross_chain_transfer.rs @@ -82,6 +82,182 @@ fn transfer_to_relay_chain() { } #[test] +fn transact_transfer_call_to_para_chain_use_ksm() { + Karura::execute_with(|| { + let _ = ParaBalances::deposit_creating(&AccountId::from(ALICE), 1000 * dollar(KAR)); + }); + + let alice = Junctions::X1(Junction::AccountId32 { + network: NetworkId::Kusama, + id: ALICE, + }); + let call = Call::Balances(pallet_balances::Call::::transfer { + dest: MultiAddress::Id(AccountId::from(BOB)), + value: 500 * dollar(KAR), + }); + let assets: MultiAsset = (Parent, dollar(KSM)).into(); + + KusamaNet::execute_with(|| { + let xcm = vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(dollar(KSM) as u64), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: (dollar(KSM) as u64) / 10 as u64, + call: call.encode().into(), + }, + DepositAsset { + assets: All.into(), + max_assets: 1, + beneficiary: { (1, alice.clone()).into() }, + }, + ]; + assert_ok!(RelayChainPalletXcm::send_xcm(alice, Parachain(2000).into(), Xcm(xcm),)); + }); + + Karura::execute_with(|| { + use {Event, System}; + assert_eq!(9983840000000, ParaTokens::free_balance(KSM, &AccountId::from(ALICE))); + assert_eq!(500 * dollar(KAR), ParaBalances::free_balance(&AccountId::from(ALICE))); + assert_eq!(500 * dollar(KAR), ParaBalances::free_balance(&AccountId::from(BOB))); + System::assert_has_event(Event::Balances(pallet_balances::Event::Transfer( + AccountId::from(ALICE), + AccountId::from(BOB), + 500 * dollar(KAR), + ))); + }); +} + +#[test] +fn transact_transfer_call_to_para_chain_use_kusd() { + Karura::execute_with(|| { + let _ = ParaBalances::deposit_creating(&AccountId::from(ALICE), 1000 * dollar(KUSD)); + assert_ok!(ParaTokens::deposit(KUSD, &AccountId::from(ALICE), 1000 * dollar(KUSD))); + }); + + let alice = Junctions::X1(Junction::AccountId32 { + network: NetworkId::Kusama, + id: ALICE, + }); + let call = Call::Balances(pallet_balances::Call::::transfer { + dest: MultiAddress::Id(AccountId::from(BOB)), + value: 500 * dollar(KUSD), + }); + let assets: MultiAsset = ( + (Parent, X2(Parachain(2000), GeneralKey(KUSD.encode()))), + 100 * dollar(KUSD), + ) + .into(); + + KusamaNet::execute_with(|| { + let xcm = vec![ + WithdrawAsset(assets.clone().into()), + BuyExecution { + fees: assets, + weight_limit: Limited(100 * dollar(KUSD) as u64), + }, + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: dollar(KUSD) as u64, + call: call.encode().into(), + }, + DepositAsset { + assets: All.into(), + max_assets: 1, + beneficiary: { (0, alice.clone()).into() }, + }, + ]; + assert_ok!(RelayChainPalletXcm::send_xcm(alice, Parachain(2000).into(), Xcm(xcm),)); + }); + + Karura::execute_with(|| { + assert_eq!(935936000000000, ParaTokens::free_balance(KUSD, &AccountId::from(ALICE))); + assert_eq!(500 * dollar(KUSD), ParaBalances::free_balance(&AccountId::from(ALICE))); + assert_eq!(500 * dollar(KUSD), ParaBalances::free_balance(&AccountId::from(BOB))); + System::assert_has_event(Event::Balances(pallet_balances::Event::Transfer( + AccountId::from(ALICE), + AccountId::from(BOB), + 500 * dollar(KUSD), + ))); + }); +} + +#[test] +fn batch_call_execute_then_send_xcm_to_para_chain() { + Karura::execute_with(|| { + assert_ok!(ParaTokens::deposit(KUSD, &AccountId::from(ALICE), 2000 * dollar(KUSD))); + }); + + let alice = Junctions::X1(Junction::AccountId32 { + network: NetworkId::Kusama, + id: ALICE, + }); + let bob = X1(Junction::AccountId32 { + network: NetworkId::Kusama, + id: BOB, + }); + KusamaNet::execute_with(|| { + // current kusama runtime `XcmExecuteFilter = Nothing` cause xcm_relay_call `Filtered` error + let _xcm_relay_call = kusama_runtime::Call::XcmPallet(pallet_xcm::Call::::execute { + message: Box::new(xcm::VersionedXcm::from(Xcm(vec![ + WithdrawAsset((Here, 1100 * dollar(KSM)).into()), + BuyExecution { + fees: (Here, 1100 * dollar(KSM)).into(), + weight_limit: Limited(dollar(KSM) as u64), + }, + DepositAsset { + assets: All.into(), + max_assets: 1, + beneficiary: { (0, alice.clone()).into() }, + }, + ]))), + max_weight: dollar(KSM) as u64, + }); + + let xcm_para_call = kusama_runtime::Call::XcmPallet(pallet_xcm::Call::::send { + dest: Box::new(xcm::VersionedMultiLocation::from(Parachain(2000).into())), + message: Box::new(xcm::VersionedXcm::from(Xcm(vec![ + WithdrawAsset( + ( + (Parent, X2(Parachain(2000), GeneralKey(KUSD.encode()))), + 1000 * dollar(KUSD), + ) + .into(), + ), + BuyExecution { + fees: ( + (Parent, X2(Parachain(2000), GeneralKey(KUSD.encode()))), + 1000 * dollar(KUSD), + ) + .into(), + weight_limit: Limited(dollar(KUSD) as u64), + }, + DepositAsset { + assets: All.into(), + max_assets: 1, + beneficiary: { (0, bob).into() }, + }, + ]))), + }); + + assert_ok!(pallet_utility::Pallet::::batch_all( + kusama_runtime::Origin::signed(AccountId::from(ALICE)), + vec![xcm_para_call] + )); + }); + + Karura::execute_with(|| { + assert_eq!( + 1000 * dollar(KUSD), + ParaTokens::free_balance(KUSD, &AccountId::from(ALICE)) + ); + assert_eq!(999948800000000, ParaTokens::free_balance(KUSD, &AccountId::from(BOB))); + }); +} + fn foreign_asset_transfer_to_relay_chain() { Karura::execute_with(|| { // register KSM as foreign asset diff --git a/runtime/integration-tests/src/relaychain/kusama_test_net.rs b/runtime/integration-tests/src/relaychain/kusama_test_net.rs index 55c71a0e08..c44b3a939e 100644 --- a/runtime/integration-tests/src/relaychain/kusama_test_net.rs +++ b/runtime/integration-tests/src/relaychain/kusama_test_net.rs @@ -53,6 +53,12 @@ decl_test_network! { } } +pub type ParaBalances = pallet_balances::Pallet; + +pub type ParaTokens = orml_tokens::Pallet; + +pub type RelayChainPalletXcm = pallet_xcm::Pallet; + fn default_parachains_host_configuration() -> HostConfiguration { HostConfiguration { validation_upgrade_frequency: 1u32, diff --git a/runtime/karura/src/lib.rs b/runtime/karura/src/lib.rs index fc2e6c1f7f..e09954ba4c 100644 --- a/runtime/karura/src/lib.rs +++ b/runtime/karura/src/lib.rs @@ -101,6 +101,7 @@ pub use sp_runtime::BuildStorage; pub use authority::AuthorityConfigImpl; pub use constants::{fee::*, parachains, time::*}; +use orml_xcm_support::{AllowRelayedPaidExecutionFromParent, RelayChainAccountId32Aliases}; pub use primitives::{ define_combined_task, evm::EstimateResourcesRequest, task::TaskResult, AccountId, AccountIndex, Address, Amount, AuctionId, AuthoritysOriginId, Balance, BlockNumber, CurrencyId, DataProviderId, EraIndex, Hash, Moment, Nonce, @@ -1401,6 +1402,7 @@ pub type LocationToAccountId = ( SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. AccountId32Aliases, + RelayChainAccountId32Aliases, ); /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, @@ -1461,6 +1463,7 @@ pub type Barrier = ( AllowKnownQueryResponses, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, + AllowRelayedPaidExecutionFromParent, ); pub struct ToTreasury;