From 4d5c4e9dc91a13016d131aebe45c73a80bb49ff2 Mon Sep 17 00:00:00 2001 From: zqh Date: Mon, 9 May 2022 16:11:42 +0800 Subject: [PATCH 1/6] statemine more test --- .../src/relaychain/statemine.rs | 113 +++++++++++++----- 1 file changed, 84 insertions(+), 29 deletions(-) diff --git a/runtime/integration-tests/src/relaychain/statemine.rs b/runtime/integration-tests/src/relaychain/statemine.rs index 36a484f722..efb8749ce8 100644 --- a/runtime/integration-tests/src/relaychain/statemine.rs +++ b/runtime/integration-tests/src/relaychain/statemine.rs @@ -100,22 +100,50 @@ fn transfer_from_relay_chain() { } #[test] -fn karura_statemine_transfer_works() { +fn karura_statemine_self_sufficient_asset_as_fee() { + TestNet::reset(); + + let asset_id: u32 = 0; + let para_2000: AccountId = Sibling::from(2000).into_account(); + + // Alice in Statemine send RMRK to Bob on Karura + statemine_side(UNIT); + + // Bob on Karura send back RMRK to Bob on Statemine + karura_side(0); + + Statemine::execute_with(|| { + use statemine_runtime::*; + + // in `statemine_side()`, para_2000 account has 10 RMRK. after `karura_side()` transfered + // 1 RMRK back to Statemine, para_2000 account in Statemine left 9 RMRK. + assert_eq!(9 * UNIT, Assets::balance(asset_id, ¶_2000)); + + // Bob not received RMRK, because of `Trader` in Statemine current not support RMRK as fee. + assert_eq!(0, Assets::balance(asset_id, &AccountId::from(BOB))); + }); +} + +#[test] +fn karura_statemine_transfer_use_ksm_as_fee() { TestNet::reset(); let para_2000: AccountId = Sibling::from(2000).into_account(); let child_2000: AccountId = ParaId::from(2000).into_account(); let child_1000: AccountId = ParaId::from(1000).into_account(); + let asset_id: u32 = 0; // minimum asset should be: FEE_WEIGHT+FEE_KUSAMA+max(KUSAMA_ED,STATEMINE_ED+FEE_STATEMINE). // but due to current half fee, sender asset should at lease: FEE_WEIGHT + 2 * FEE_KUSAMA let asset = FEE_WEIGHT + 2 * FEE_KUSAMA; + // Alice in Statemine send RMRK to Bob on Karura statemine_side(UNIT); KusamaNet::execute_with(|| { let _ = kusama_runtime::Balances::make_free_balance_be(&child_2000, TEN); }); + // Bob on Karura send back RMRK with KSM as fee to Bob on Statemine karura_side(asset); KusamaNet::execute_with(|| { @@ -131,10 +159,11 @@ fn karura_statemine_transfer_works() { Statemine::execute_with(|| { use statemine_runtime::*; + // Karura send back custom asset to Statemine, ensure recipient got custom asset - assert_eq!(UNIT, Assets::balance(0, &AccountId::from(BOB))); + assert_eq!(UNIT, Assets::balance(asset_id, &AccountId::from(BOB))); // and withdraw sibling parachain sovereign account - assert_eq!(9 * UNIT, Assets::balance(0, ¶_2000)); + assert_eq!(9 * UNIT, Assets::balance(asset_id, ¶_2000)); assert_eq!( UNIT + FEE_WEIGHT - FEE_STATEMINE, @@ -159,25 +188,49 @@ fn karura_side(fee_amount: u128) { // ensure sender has enough KSM balance to be charged as fee assert_ok!(Tokens::deposit(KSM, &AccountId::from(BOB), TEN)); - assert_ok!(XTokens::transfer_multicurrencies( - Origin::signed(BOB.into()), - vec![(CurrencyId::ForeignAsset(0), UNIT), (KSM, fee_amount)], - 1, - Box::new( - MultiLocation::new( - 1, - X2( - Parachain(1000), - Junction::AccountId32 { - network: NetworkId::Any, - id: BOB.into(), - } + if fee_amount == 0 { + // use custom asset(RMRK/USDT on Statemine) as fee + assert_ok!(XTokens::transfer( + Origin::signed(BOB.into()), + CurrencyId::ForeignAsset(0), + UNIT, + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(1000), + Junction::AccountId32 { + network: NetworkId::Any, + id: BOB.into(), + } + ) ) - ) - .into() - ), - FEE_WEIGHT as u64 - )); + .into() + ), + FEE_WEIGHT as u64 + )); + } else { + // use KSM as fee + assert_ok!(XTokens::transfer_multicurrencies( + Origin::signed(BOB.into()), + vec![(CurrencyId::ForeignAsset(0), UNIT), (KSM, fee_amount)], + 1, + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(1000), + Junction::AccountId32 { + network: NetworkId::Any, + id: BOB.into(), + } + ) + ) + .into() + ), + FEE_WEIGHT as u64 + )); + } assert_eq!( 8_999_936_000_000, @@ -191,7 +244,8 @@ fn karura_side(fee_amount: u128) { fn statemine_side(para_2000_init_amount: u128) { register_asset(); - let para_acc: AccountId = Sibling::from(2000).into_account(); + let para_2000: AccountId = Sibling::from(2000).into_account(); + let asset_id: u32 = 0; Statemine::execute_with(|| { use statemine_runtime::*; @@ -203,7 +257,7 @@ fn statemine_side(para_2000_init_amount: u128) { // create custom asset cost 1 KSM assert_ok!(Assets::create( origin.clone(), - 0, + asset_id, MultiAddress::Id(ALICE.into()), UNIT / 100 )); @@ -211,13 +265,13 @@ fn statemine_side(para_2000_init_amount: u128) { assert_ok!(Assets::mint( origin.clone(), - 0, + asset_id, MultiAddress::Id(ALICE.into()), 1000 * UNIT )); // need to have some KSM to be able to receive user assets - Balances::make_free_balance_be(¶_acc, para_2000_init_amount); + Balances::make_free_balance_be(¶_2000, para_2000_init_amount); assert_ok!(PolkadotXcm::reserve_transfer_assets( origin.clone(), @@ -230,15 +284,16 @@ fn statemine_side(para_2000_init_amount: u128) { .into() .into() ), - Box::new((X2(PalletInstance(50), GeneralIndex(0)), TEN).into()), + Box::new((X2(PalletInstance(50), GeneralIndex(asset_id as u128)), TEN).into()), 0 )); - assert_eq!(0, Assets::balance(0, &AccountId::from(BOB))); + assert_eq!(990 * UNIT, Assets::balance(asset_id, &AccountId::from(ALICE))); + assert_eq!(0, Assets::balance(asset_id, &AccountId::from(BOB))); - assert_eq!(TEN, Assets::balance(0, ¶_acc)); + assert_eq!(TEN, Assets::balance(asset_id, ¶_2000)); // the KSM balance of sibling parachain sovereign account is not changed - assert_eq!(para_2000_init_amount, Balances::free_balance(¶_acc)); + assert_eq!(para_2000_init_amount, Balances::free_balance(¶_2000)); }); // Rerun the Statemine::execute to actually send the egress message via XCM From f236663a8d0bec6c9f81093b606e2712bb7ff591 Mon Sep 17 00:00:00 2001 From: zqh Date: Sat, 21 May 2022 13:53:46 +0800 Subject: [PATCH 2/6] statemine ksm transfer --- .../src/relaychain/statemine.rs | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/runtime/integration-tests/src/relaychain/statemine.rs b/runtime/integration-tests/src/relaychain/statemine.rs index efb8749ce8..ad00983786 100644 --- a/runtime/integration-tests/src/relaychain/statemine.rs +++ b/runtime/integration-tests/src/relaychain/statemine.rs @@ -74,6 +74,8 @@ fn statemine_min_xcm_fee_matched() { #[test] fn transfer_from_relay_chain() { + let child_1000: AccountId = ParaId::from(1000).into_account(); + KusamaNet::execute_with(|| { assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( kusama_runtime::Origin::signed(ALICE.into()), @@ -89,6 +91,7 @@ fn transfer_from_relay_chain() { Box::new((Here, dollar(KSM)).into()), 0 )); + assert_eq!(dollar(KSM), kusama_runtime::Balances::free_balance(&child_1000)); }); Statemine::execute_with(|| { @@ -99,6 +102,95 @@ fn transfer_from_relay_chain() { }); } +#[test] +fn statemine_transfer_ksm_to_karura_failed() { + TestNet::reset(); + + let para_2000: AccountId = Sibling::from(2000).into_account(); + let child_2000: AccountId = ParaId::from(2000).into_account(); + let child_1000: AccountId = ParaId::from(1000).into_account(); + + Statemine::execute_with(|| { + Balances::make_free_balance_be(&ALICE.into(), 2 * dollar(KSM)); + Balances::make_free_balance_be(¶_2000, 2 * dollar(KSM)); + + assert_ok!(statemine_runtime::PolkadotXcm::reserve_transfer_assets( + statemine_runtime::Origin::signed(ALICE.into()), + Box::new(MultiLocation::new(1, X1(Parachain(2000))).into()), + Box::new( + Junction::AccountId32 { + id: BOB, + network: NetworkId::Any + } + .into() + .into() + ), + Box::new((Parent, dollar(KSM)).into()), + 0 + )); + assert_eq!( + dollar(KSM), + statemine_runtime::Balances::free_balance(&AccountId::from(ALICE)) + ); + assert_eq!(3 * dollar(KSM), statemine_runtime::Balances::free_balance(¶_2000)); + }); + + // UntrustedReserveLocation + KusamaNet::execute_with(|| { + assert_eq!(2 * dollar(KSM), kusama_runtime::Balances::free_balance(&child_2000)); + assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); + }); + + Karura::execute_with(|| { + assert_eq!(0, Tokens::free_balance(KSM, &AccountId::from(BOB))); + }); +} + +#[test] +fn karura_transfer_ksm_to_statemine() { + TestNet::reset(); + + let child_2000: AccountId = ParaId::from(2000).into_account(); + let child_1000: AccountId = ParaId::from(1000).into_account(); + + KusamaNet::execute_with(|| { + assert_eq!(2 * UNIT, kusama_runtime::Balances::free_balance(&child_2000)); + assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); + }); + + // Karura transfer KSM to statemine, it's kind of A-[B]-C scene. + Karura::execute_with(|| { + assert_ok!(XTokens::transfer( + Origin::signed(ALICE.into()), + KSM, + dollar(KSM), + Box::new( + MultiLocation::new( + 1, + X2( + Parachain(1000), + Junction::AccountId32 { + network: NetworkId::Any, + id: BOB.into(), + } + ) + ) + .into() + ), + 4_000_000_000 + )); + }); + + KusamaNet::execute_with(|| { + assert_eq!(UNIT, kusama_runtime::Balances::free_balance(&child_2000)); + assert_eq!(999_834_059_328, kusama_runtime::Balances::free_balance(&child_1000)); + }); + + Statemine::execute_with(|| { + assert_eq!(999_823_392_664, Balances::free_balance(&AccountId::from(BOB))); + }); +} + #[test] fn karura_statemine_self_sufficient_asset_as_fee() { TestNet::reset(); From ac49f6d66511fe6a11a98e45669c36f0067ac336 Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Wed, 12 Oct 2022 17:22:18 +0800 Subject: [PATCH 3/6] self sufficient asset as fee works --- ecosystem-modules/stable-asset | 2 +- evm-tests | 2 +- orml | 2 +- predeploy-contracts | 2 +- runtime/integration-tests/Cargo.toml | 2 +- .../src/relaychain/statemine.rs | 266 +++++++++++++----- 6 files changed, 200 insertions(+), 76 deletions(-) diff --git a/ecosystem-modules/stable-asset b/ecosystem-modules/stable-asset index 3d25907eac..77a1a94297 160000 --- a/ecosystem-modules/stable-asset +++ b/ecosystem-modules/stable-asset @@ -1 +1 @@ -Subproject commit 3d25907eacd99d44bc79353cad37a55d77500644 +Subproject commit 77a1a9429739a0a547f19a7eb3231f764b4bc999 diff --git a/evm-tests b/evm-tests index 9220be0606..da8995fe69 160000 --- a/evm-tests +++ b/evm-tests @@ -1 +1 @@ -Subproject commit 9220be060693a8704ebf7c38df19c76e16f5c218 +Subproject commit da8995fe6930f9afea9b8c392e97f0c12fe2ba75 diff --git a/orml b/orml index c673da3374..20969f385b 160000 --- a/orml +++ b/orml @@ -1 +1 @@ -Subproject commit c673da3374dfe1d251cd196041470b9eb191c15b +Subproject commit 20969f385bf77e41386e8d8aa9626b003a306204 diff --git a/predeploy-contracts b/predeploy-contracts index 9d1426bf0d..80b6156556 160000 --- a/predeploy-contracts +++ b/predeploy-contracts @@ -1 +1 @@ -Subproject commit 9d1426bf0d6232652e45cfd4d77e89698ab21f67 +Subproject commit 80b6156556be388baaffb98409cf790b4ffeff4e diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index 93619feafa..4101dbfda5 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -151,7 +151,7 @@ module-aggregated-dex = { path = "../../modules/aggregated-dex" } nutsfinance-stable-asset = { version = "0.1.0", path = "../../ecosystem-modules/stable-asset/lib/stable-asset", package = "nutsfinance-stable-asset" } [features] -default = ["std"] +default = ["std", "with-karura-runtime"] no_std = [] with-mandala-runtime = [ "mandala-runtime", diff --git a/runtime/integration-tests/src/relaychain/statemine.rs b/runtime/integration-tests/src/relaychain/statemine.rs index a66ebda54f..d7ad2cbcbf 100644 --- a/runtime/integration-tests/src/relaychain/statemine.rs +++ b/runtime/integration-tests/src/relaychain/statemine.rs @@ -26,6 +26,7 @@ use frame_support::assert_ok; pub use orml_traits::GetByKey; use polkadot_parachain::primitives::Sibling; use primitives::currency::AssetMetadata; +use sp_runtime::traits::AccountIdConversion; use xcm::v1::{Junction, MultiLocation}; use xcm_emulator::TestExt; @@ -34,6 +35,8 @@ pub const TEN: Balance = 10_000_000_000_000; pub const FEE_WEIGHT: Balance = 4_000_000_000; pub const FEE: Balance = 20_000_000; pub const FEE_STATEMINE: Balance = 15_450_332; +pub const FEE_KUSAMA: Balance = 11_492_737; +const ASSET_ID: u32 = 100; fn init_statemine_xcm_interface() { let xcm_operation = @@ -74,10 +77,14 @@ fn statemine_min_xcm_fee_matched() { } #[test] -fn teleport_from_relay_chain() { - let child_1000: AccountId = ParaId::from(1000).into_account(); +fn teleport_between_relaychain_and_statemine_works() { + TestNet::reset(); + let child_1000: AccountId = ParaId::from(1000).into_account_truncating(); + // Kusama teleport KSM to Statemine KusamaNet::execute_with(|| { + Balances::make_free_balance_be(&ALICE.into(), 2 * UNIT); + assert_ok!(kusama_runtime::XcmPallet::teleport_assets( kusama_runtime::Origin::signed(ALICE.into()), Box::new(Parachain(1000).into().into()), @@ -89,33 +96,135 @@ fn teleport_from_relay_chain() { .into() .into() ), - Box::new((Here, dollar(KSM)).into()), + Box::new((Here, UNIT).into()), 0 )); - assert_eq!(dollar(KSM), kusama_runtime::Balances::free_balance(&child_1000)); + // In teleport mode, parachain sovereign account dont changed. + assert_eq!(UNIT, Balances::free_balance(&AccountId::from(ALICE))); + assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); }); + // Statemine teleport KSM back to Kusama Statemine::execute_with(|| { - assert_eq!( - dollar(KSM) - FEE_STATEMINE, - Balances::free_balance(&AccountId::from(BOB)) - ); + assert_eq!(UNIT - FEE_STATEMINE, Balances::free_balance(&AccountId::from(BOB))); + + assert_ok!(Balances::deposit_into_existing(&BOB.into(), UNIT)); + assert_ok!(statemine_runtime::PolkadotXcm::teleport_assets( + statemine_runtime::Origin::signed(BOB.into()), + Box::new(Parent.into()), + Box::new( + Junction::AccountId32 { + id: ALICE, + network: NetworkId::Any + } + .into() + .into() + ), + Box::new((Parent, UNIT).into()), + 0 + )); + assert_eq!(UNIT - FEE_STATEMINE, Balances::free_balance(&AccountId::from(BOB))); + }); + + KusamaNet::execute_with(|| { + assert_eq!(2 * UNIT - FEE_KUSAMA, Balances::free_balance(&AccountId::from(ALICE))); }); } #[test] -fn statemine_transfer_ksm_to_karura_failed() { +fn reserve_transfer_between_relaychain_and_statemine_should_not_allowed() { TestNet::reset(); - let para_2000: AccountId = Sibling::from(2000).into_account_truncating(); + let child_1000: AccountId = ParaId::from(1000).into_account_truncating(); + + // Kusama reserve transfer KSM to Statemine should not works + KusamaNet::execute_with(|| { + Balances::make_free_balance_be(&ALICE.into(), 2 * UNIT); + + // Error when execute xcm on sender side: Barrier blocked execution! + assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( + kusama_runtime::Origin::signed(ALICE.into()), + Box::new(MultiLocation::new(1, X1(Parachain(1000))).into()), + Box::new( + Junction::AccountId32 { + id: BOB, + network: NetworkId::Any + } + .into() + .into() + ), + Box::new((Parent, UNIT).into()), + 0 + )); + assert_eq!(2 * UNIT, Balances::free_balance(&AccountId::from(ALICE))); + assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); + + // use teleport to transfer some KSM, so that we can test other case. + assert_ok!(kusama_runtime::XcmPallet::teleport_assets( + kusama_runtime::Origin::signed(ALICE.into()), + Box::new(Parachain(1000).into().into()), + Box::new( + Junction::AccountId32 { + id: BOB, + network: NetworkId::Any + } + .into() + .into() + ), + Box::new((Here, UNIT).into()), + 0 + )); + assert_eq!(UNIT, Balances::free_balance(&AccountId::from(ALICE))); + }); + + // Statemine reserve transfer KSM back to Kusama + Statemine::execute_with(|| { + assert_eq!(UNIT - FEE_STATEMINE, Balances::free_balance(&AccountId::from(BOB))); + + // Error when execute xcm on sender side: Barrier blocked execution! + assert_ok!(statemine_runtime::PolkadotXcm::reserve_transfer_assets( + statemine_runtime::Origin::signed(BOB.into()), + Box::new(Parent.into()), + Box::new( + Junction::AccountId32 { + id: ALICE, + network: NetworkId::Any + } + .into() + .into() + ), + Box::new((Parent, UNIT).into()), + 0 + )); + assert_eq!(UNIT - FEE_STATEMINE, Balances::free_balance(&AccountId::from(BOB))); + }); + + KusamaNet::execute_with(|| { + assert_eq!(UNIT, Balances::free_balance(&AccountId::from(ALICE))); + }); +} + +#[test] +fn statemine_reserve_transfer_ksm_to_karura_should_not_allowed() { + TestNet::reset(); + let sibling_2000: AccountId = Sibling::from(2000).into_account_truncating(); let child_2000: AccountId = ParaId::from(2000).into_account_truncating(); let child_1000: AccountId = ParaId::from(1000).into_account_truncating(); + KusamaNet::execute_with(|| { + assert_eq!(2 * UNIT, kusama_runtime::Balances::free_balance(&child_2000)); + assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); + }); + Statemine::execute_with(|| { - Balances::make_free_balance_be(&ALICE.into(), 2 * dollar(KSM)); - Balances::make_free_balance_be(¶_2000, 2 * dollar(KSM)); + Balances::make_free_balance_be(&ALICE.into(), 2 * UNIT); + // Suppose reserve transfer can success, then dest chain(Karura) has a sibling sovereign account on + // source chain(Statemine). + Balances::make_free_balance_be(&sibling_2000, 2 * UNIT); assert_ok!(statemine_runtime::PolkadotXcm::reserve_transfer_assets( statemine_runtime::Origin::signed(ALICE.into()), + // Unlike Statemine reserve transfer to relaychain is not allowed, + // Here Statemine reserve transfer to parachain. let's see what happened. Box::new(MultiLocation::new(1, X1(Parachain(2000))).into()), Box::new( Junction::AccountId32 { @@ -125,45 +234,45 @@ fn statemine_transfer_ksm_to_karura_failed() { .into() .into() ), - Box::new((Parent, dollar(KSM)).into()), + Box::new((Parent, UNIT).into()), 0 )); - assert_eq!( - dollar(KSM), - statemine_runtime::Balances::free_balance(&AccountId::from(ALICE)) - ); - assert_eq!(3 * dollar(KSM), statemine_runtime::Balances::free_balance(¶_2000)); + + // In sender xcm execution is successed, sender account is withdrawn. + assert_eq!(UNIT, statemine_runtime::Balances::free_balance(&AccountId::from(ALICE))); + // And sibling parachain sovereign account on Statemine deposited. + assert_eq!(3 * UNIT, statemine_runtime::Balances::free_balance(&sibling_2000)); }); - // UntrustedReserveLocation KusamaNet::execute_with(|| { - assert_eq!(2 * dollar(KSM), kusama_runtime::Balances::free_balance(&child_2000)); + assert_eq!(2 * UNIT, kusama_runtime::Balances::free_balance(&child_2000)); assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); }); + // Xcm execution error on receiver: UntrustedReserveLocation. + // This means Karura not consider Statemine as reserve chain of KSM. Karura::execute_with(|| { assert_eq!(0, Tokens::free_balance(KSM, &AccountId::from(BOB))); }); } #[test] -fn karura_transfer_ksm_to_statemine() { +fn karura_transfer_ksm_to_statemine_should_not_allowed() { TestNet::reset(); - - let child_2000: AccountId = ParaId::from(2000).into_account(); - let child_1000: AccountId = ParaId::from(1000).into_account(); + let child_2000: AccountId = ParaId::from(2000).into_account_truncating(); + let child_1000: AccountId = ParaId::from(1000).into_account_truncating(); KusamaNet::execute_with(|| { assert_eq!(2 * UNIT, kusama_runtime::Balances::free_balance(&child_2000)); assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); }); - // Karura transfer KSM to statemine, it's kind of A-[B]-C scene. + // Karura transfer KSM to Statemine, it's `NonRerserve` scene(A->[B]->C). Karura::execute_with(|| { assert_ok!(XTokens::transfer( Origin::signed(ALICE.into()), KSM, - dollar(KSM), + UNIT, Box::new( MultiLocation::new( 1, @@ -179,65 +288,70 @@ fn karura_transfer_ksm_to_statemine() { ), 4_000_000_000 )); + + assert_eq!(9 * UNIT, Tokens::free_balance(KSM, &AccountId::from(ALICE))); }); + // In relaychain, two parachain sovereign account balance changed. KusamaNet::execute_with(|| { + // source parachain sovereign account withrawn. assert_eq!(UNIT, kusama_runtime::Balances::free_balance(&child_2000)); - assert_eq!(999_834_059_328, kusama_runtime::Balances::free_balance(&child_1000)); + // destination parachain sovereign account deposited. + assert_eq!(999_970_357_090, kusama_runtime::Balances::free_balance(&child_1000)); }); + // In receiver, xm execution error: UntrustedReserveLocation. + // This's same as Relaychain reserve transfer to Statemine which not allowed. Statemine::execute_with(|| { - assert_eq!(999_823_392_664, Balances::free_balance(&AccountId::from(BOB))); + assert_eq!(0, Balances::free_balance(&AccountId::from(BOB))); }); } #[test] -fn karura_statemine_self_sufficient_asset_as_fee() { +fn karura_transfer_asset_to_statemine_works() { TestNet::reset(); - let asset_id: u32 = 0; - let para_2000: AccountId = Sibling::from(2000).into_account(); + let para_2000: AccountId = Sibling::from(2000).into_account_truncating(); - // Alice in Statemine send RMRK to Bob on Karura - statemine_side(UNIT); + // Alice on Statemine send USDT to Bob on Karura. + statemine_transfer_asset_to_karura(); - // Bob on Karura send back RMRK to Bob on Statemine - karura_side(0); + // Bob on Karura send back USDT to Bob on Statemine. + // Trying use USDT as fee when execte xcm on Statemine. + karura_transfer_asset_to_statemine(0); Statemine::execute_with(|| { use statemine_runtime::*; - // in `statemine_side()`, para_2000 account has 10 RMRK. after `karura_side()` transfered - // 1 RMRK back to Statemine, para_2000 account in Statemine left 9 RMRK. - assert_eq!(9 * UNIT, Assets::balance(asset_id, ¶_2000)); + assert_eq!(9 * UNIT, Assets::balance(ASSET_ID, ¶_2000)); - // Bob not received RMRK, because of `Trader` in Statemine current not support RMRK as fee. - assert_eq!(0, Assets::balance(asset_id, &AccountId::from(BOB))); + // https://github.com/paritytech/cumulus/pull/1278 support using self sufficient asset + // for paying xcm execution fee on Statemine. + assert_eq!(953_648_999_365, Assets::balance(ASSET_ID, &AccountId::from(BOB))); }); } #[test] fn karura_statemine_transfer_use_ksm_as_fee() { TestNet::reset(); - let para_2000: AccountId = Sibling::from(2000).into_account(); - let child_2000: AccountId = ParaId::from(2000).into_account(); - let child_1000: AccountId = ParaId::from(1000).into_account(); - let asset_id: u32 = 0; + let para_2000: AccountId = Sibling::from(2000).into_account_truncating(); + let child_2000: AccountId = ParaId::from(2000).into_account_truncating(); + let child_1000: AccountId = ParaId::from(1000).into_account_truncating(); // minimum asset should be: FEE_WEIGHT+FEE_KUSAMA+max(KUSAMA_ED,STATEMINE_ED+FEE_STATEMINE). // but due to current half fee, sender asset should at lease: FEE_WEIGHT + 2 * FEE_KUSAMA let asset = FEE_WEIGHT + 2 * 31_488_122; - // Alice in Statemine send RMRK to Bob on Karura - statemine_side(UNIT); + // Alice on Statemine send USDT to Bob on Karura + statemine_transfer_asset_to_karura(); KusamaNet::execute_with(|| { let _ = kusama_runtime::Balances::make_free_balance_be(&child_2000, TEN); assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); }); - // Bob on Karura send back RMRK with KSM as fee to Bob on Statemine - karura_side(asset); + // Bob on Karura send back USDT with KSM as fee to Bob on Statemine + karura_transfer_asset_to_statemine(asset); KusamaNet::execute_with(|| { assert_eq!(TEN - (asset - FEE), kusama_runtime::Balances::free_balance(&child_2000)); @@ -247,9 +361,9 @@ fn karura_statemine_transfer_use_ksm_as_fee() { use statemine_runtime::*; // Karura send back custom asset to Statemine, ensure recipient got custom asset - assert_eq!(UNIT, Assets::balance(asset_id, &AccountId::from(BOB))); + assert_eq!(UNIT, Assets::balance(ASSET_ID, &AccountId::from(BOB))); // and withdraw sibling parachain sovereign account - assert_eq!(9 * UNIT, Assets::balance(asset_id, ¶_2000)); + assert_eq!(9 * UNIT, Assets::balance(ASSET_ID, ¶_2000)); assert_eq!( UNIT + FEE - FEE_STATEMINE, @@ -259,8 +373,10 @@ fn karura_statemine_transfer_use_ksm_as_fee() { }); } -// transfer custom asset from Karura to Statemine -fn karura_side(fee_amount: u128) { +// Karura(ForeignAsset) transfer asset(e.g. USDT) back to Statemine(assets) +// `ksm_fee_amount` is used to indicate how much KSM paying as fee. +// If specify `ksm_fee_amount` to 0, then wouldn't use KSM as fee. +fn karura_transfer_asset_to_statemine(ksm_fee_amount: u128) { Karura::execute_with(|| { init_statemine_xcm_interface(); @@ -271,8 +387,8 @@ fn karura_side(fee_amount: u128) { // ensure sender has enough KSM balance to be charged as fee assert_ok!(Tokens::deposit(KSM, &AccountId::from(BOB), TEN)); - if fee_amount == 0 { - // use custom asset(RMRK/USDT on Statemine) as fee + if ksm_fee_amount == 0 { + // use custom asset(USDT on Statemine) as fee assert_ok!(XTokens::transfer( Origin::signed(BOB.into()), CurrencyId::ForeignAsset(0), @@ -296,7 +412,7 @@ fn karura_side(fee_amount: u128) { // use KSM as fee assert_ok!(XTokens::transfer_multicurrencies( Origin::signed(BOB.into()), - vec![(CurrencyId::ForeignAsset(0), UNIT), (KSM, fee_amount)], + vec![(CurrencyId::ForeignAsset(0), UNIT), (KSM, ksm_fee_amount)], 1, Box::new( MultiLocation::new( @@ -319,16 +435,17 @@ fn karura_side(fee_amount: u128) { 8_999_907_304_000, Tokens::free_balance(CurrencyId::ForeignAsset(0), &AccountId::from(BOB)) ); - assert_eq!(TEN - fee_amount, Tokens::free_balance(KSM, &AccountId::from(BOB))); + assert_eq!(TEN - ksm_fee_amount, Tokens::free_balance(KSM, &AccountId::from(BOB))); }); } -// transfer custom asset from Statemine to Karura -fn statemine_side(para_2000_init_amount: u128) { +// Statemine(assets) transfer custom asset(e.g. USDT) to Karura(ForeignAsset) +// Alice is using reserve transfer, and Statemine is indeed the reserve chain of USDT. +// So the reserve transfer can success. On Karura side, USDT is consider as ForeignAsset. +fn statemine_transfer_asset_to_karura() { register_asset(); let para_2000: AccountId = Sibling::from(2000).into_account_truncating(); - let asset_id: u32 = 0; Statemine::execute_with(|| { use statemine_runtime::*; @@ -338,23 +455,24 @@ fn statemine_side(para_2000_init_amount: u128) { Balances::make_free_balance_be(&BOB.into(), UNIT); // create custom asset cost 0.1 KSM - assert_ok!(Assets::create( - origin.clone(), - asset_id, + assert_ok!(Assets::force_create( + Origin::root(), + ASSET_ID, MultiAddress::Id(ALICE.into()), + true, // make sure asset is sufficient. UNIT / 100 )); - assert_eq!(9_900_000_000_000, Balances::free_balance(&AccountId::from(ALICE))); + // assert_eq!(9_900_000_000_000, Balances::free_balance(&AccountId::from(ALICE))); assert_ok!(Assets::mint( origin.clone(), - asset_id, + ASSET_ID, MultiAddress::Id(ALICE.into()), 1000 * UNIT )); // need to have some KSM to be able to receive user assets - Balances::make_free_balance_be(¶_2000, para_2000_init_amount); + Balances::make_free_balance_be(¶_2000, UNIT); assert_ok!(PolkadotXcm::reserve_transfer_assets( origin.clone(), @@ -367,16 +485,16 @@ fn statemine_side(para_2000_init_amount: u128) { .into() .into() ), - Box::new((X2(PalletInstance(50), GeneralIndex(asset_id as u128)), TEN).into()), + Box::new((X2(PalletInstance(50), GeneralIndex(ASSET_ID as u128)), TEN).into()), 0 )); - assert_eq!(990 * UNIT, Assets::balance(asset_id, &AccountId::from(ALICE))); - assert_eq!(0, Assets::balance(asset_id, &AccountId::from(BOB))); + assert_eq!(990 * UNIT, Assets::balance(ASSET_ID, &AccountId::from(ALICE))); + assert_eq!(0, Assets::balance(ASSET_ID, &AccountId::from(BOB))); - assert_eq!(TEN, Assets::balance(asset_id, ¶_2000)); + assert_eq!(TEN, Assets::balance(ASSET_ID, ¶_2000)); // the KSM balance of sibling parachain sovereign account is not changed - assert_eq!(para_2000_init_amount, Balances::free_balance(¶_2000)); + assert_eq!(UNIT, Balances::free_balance(¶_2000)); }); // Rerun the Statemine::execute to actually send the egress message via XCM @@ -388,7 +506,13 @@ fn register_asset() { // register foreign asset assert_ok!(AssetRegistry::register_foreign_asset( Origin::root(), - Box::new(MultiLocation::new(1, X3(Parachain(1000), PalletInstance(50), GeneralIndex(0))).into()), + Box::new( + MultiLocation::new( + 1, + X3(Parachain(1000), PalletInstance(50), GeneralIndex(ASSET_ID as u128)) + ) + .into() + ), Box::new(AssetMetadata { name: b"Sibling Token".to_vec(), symbol: b"ST".to_vec(), From 79135df9c71ab5d865ea5c1f5fe20dd5370026a8 Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Wed, 12 Oct 2022 17:32:10 +0800 Subject: [PATCH 4/6] fmt --- runtime/integration-tests/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index 4101dbfda5..93619feafa 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -151,7 +151,7 @@ module-aggregated-dex = { path = "../../modules/aggregated-dex" } nutsfinance-stable-asset = { version = "0.1.0", path = "../../ecosystem-modules/stable-asset/lib/stable-asset", package = "nutsfinance-stable-asset" } [features] -default = ["std", "with-karura-runtime"] +default = ["std"] no_std = [] with-mandala-runtime = [ "mandala-runtime", From 5c294ac843ab75f31abd23a09330fa90b91e8ed7 Mon Sep 17 00:00:00 2001 From: zqhxuyuan Date: Wed, 12 Oct 2022 17:35:21 +0800 Subject: [PATCH 5/6] udpate --- runtime/integration-tests/src/relaychain/statemine.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/integration-tests/src/relaychain/statemine.rs b/runtime/integration-tests/src/relaychain/statemine.rs index d7ad2cbcbf..fad0004f65 100644 --- a/runtime/integration-tests/src/relaychain/statemine.rs +++ b/runtime/integration-tests/src/relaychain/statemine.rs @@ -454,15 +454,15 @@ fn statemine_transfer_asset_to_karura() { Balances::make_free_balance_be(&ALICE.into(), TEN); Balances::make_free_balance_be(&BOB.into(), UNIT); - // create custom asset cost 0.1 KSM + // If using non root, create custom asset cost 0.1 KSM + // We're using force_create here to make sure asset is sufficient. assert_ok!(Assets::force_create( Origin::root(), ASSET_ID, MultiAddress::Id(ALICE.into()), - true, // make sure asset is sufficient. + true, UNIT / 100 )); - // assert_eq!(9_900_000_000_000, Balances::free_balance(&AccountId::from(ALICE))); assert_ok!(Assets::mint( origin.clone(), From db43ce0ad805937ecfd3913ccc49eac2ac5bbb1b Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Tue, 18 Oct 2022 10:58:17 +1300 Subject: [PATCH 6/6] Remove out of scope tests. --- .../src/relaychain/statemine.rs | 127 ------------------ 1 file changed, 127 deletions(-) diff --git a/runtime/integration-tests/src/relaychain/statemine.rs b/runtime/integration-tests/src/relaychain/statemine.rs index fad0004f65..0093bee4da 100644 --- a/runtime/integration-tests/src/relaychain/statemine.rs +++ b/runtime/integration-tests/src/relaychain/statemine.rs @@ -76,133 +76,6 @@ fn statemine_min_xcm_fee_matched() { }); } -#[test] -fn teleport_between_relaychain_and_statemine_works() { - TestNet::reset(); - let child_1000: AccountId = ParaId::from(1000).into_account_truncating(); - - // Kusama teleport KSM to Statemine - KusamaNet::execute_with(|| { - Balances::make_free_balance_be(&ALICE.into(), 2 * UNIT); - - assert_ok!(kusama_runtime::XcmPallet::teleport_assets( - kusama_runtime::Origin::signed(ALICE.into()), - Box::new(Parachain(1000).into().into()), - Box::new( - Junction::AccountId32 { - id: BOB, - network: NetworkId::Any - } - .into() - .into() - ), - Box::new((Here, UNIT).into()), - 0 - )); - // In teleport mode, parachain sovereign account dont changed. - assert_eq!(UNIT, Balances::free_balance(&AccountId::from(ALICE))); - assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); - }); - - // Statemine teleport KSM back to Kusama - Statemine::execute_with(|| { - assert_eq!(UNIT - FEE_STATEMINE, Balances::free_balance(&AccountId::from(BOB))); - - assert_ok!(Balances::deposit_into_existing(&BOB.into(), UNIT)); - assert_ok!(statemine_runtime::PolkadotXcm::teleport_assets( - statemine_runtime::Origin::signed(BOB.into()), - Box::new(Parent.into()), - Box::new( - Junction::AccountId32 { - id: ALICE, - network: NetworkId::Any - } - .into() - .into() - ), - Box::new((Parent, UNIT).into()), - 0 - )); - assert_eq!(UNIT - FEE_STATEMINE, Balances::free_balance(&AccountId::from(BOB))); - }); - - KusamaNet::execute_with(|| { - assert_eq!(2 * UNIT - FEE_KUSAMA, Balances::free_balance(&AccountId::from(ALICE))); - }); -} - -#[test] -fn reserve_transfer_between_relaychain_and_statemine_should_not_allowed() { - TestNet::reset(); - let child_1000: AccountId = ParaId::from(1000).into_account_truncating(); - - // Kusama reserve transfer KSM to Statemine should not works - KusamaNet::execute_with(|| { - Balances::make_free_balance_be(&ALICE.into(), 2 * UNIT); - - // Error when execute xcm on sender side: Barrier blocked execution! - assert_ok!(kusama_runtime::XcmPallet::reserve_transfer_assets( - kusama_runtime::Origin::signed(ALICE.into()), - Box::new(MultiLocation::new(1, X1(Parachain(1000))).into()), - Box::new( - Junction::AccountId32 { - id: BOB, - network: NetworkId::Any - } - .into() - .into() - ), - Box::new((Parent, UNIT).into()), - 0 - )); - assert_eq!(2 * UNIT, Balances::free_balance(&AccountId::from(ALICE))); - assert_eq!(0, kusama_runtime::Balances::free_balance(&child_1000)); - - // use teleport to transfer some KSM, so that we can test other case. - assert_ok!(kusama_runtime::XcmPallet::teleport_assets( - kusama_runtime::Origin::signed(ALICE.into()), - Box::new(Parachain(1000).into().into()), - Box::new( - Junction::AccountId32 { - id: BOB, - network: NetworkId::Any - } - .into() - .into() - ), - Box::new((Here, UNIT).into()), - 0 - )); - assert_eq!(UNIT, Balances::free_balance(&AccountId::from(ALICE))); - }); - - // Statemine reserve transfer KSM back to Kusama - Statemine::execute_with(|| { - assert_eq!(UNIT - FEE_STATEMINE, Balances::free_balance(&AccountId::from(BOB))); - - // Error when execute xcm on sender side: Barrier blocked execution! - assert_ok!(statemine_runtime::PolkadotXcm::reserve_transfer_assets( - statemine_runtime::Origin::signed(BOB.into()), - Box::new(Parent.into()), - Box::new( - Junction::AccountId32 { - id: ALICE, - network: NetworkId::Any - } - .into() - .into() - ), - Box::new((Parent, UNIT).into()), - 0 - )); - assert_eq!(UNIT - FEE_STATEMINE, Balances::free_balance(&AccountId::from(BOB))); - }); - - KusamaNet::execute_with(|| { - assert_eq!(UNIT, Balances::free_balance(&AccountId::from(ALICE))); - }); -} - #[test] fn statemine_reserve_transfer_ksm_to_karura_should_not_allowed() { TestNet::reset();