From 43ef69484048a526398c8872ea996c85f7bd8e96 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 5 Sep 2023 19:22:36 +0300 Subject: [PATCH 001/124] asset-hubs runtimes: add xcm reserve transfer tests --- Cargo.lock | 1 + .../assets/asset-hub-kusama/tests/tests.rs | 34 ++- .../assets/asset-hub-polkadot/tests/tests.rs | 34 ++- .../assets/asset-hub-westend/tests/tests.rs | 33 ++- .../runtimes/assets/test-utils/Cargo.toml | 2 + .../runtimes/assets/test-utils/src/lib.rs | 42 ++++ .../assets/test-utils/src/test_cases.rs | 197 +++++++++++++++++- 7 files changed, 332 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0ca0b012c64..a3a59c270c47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -960,6 +960,7 @@ dependencies = [ "sp-runtime", "sp-std", "staging-xcm", + "staging-xcm-builder", "staging-xcm-executor", "substrate-wasm-builder", ] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs index 7d49b56e461a..31004dfc62e1 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs @@ -18,13 +18,14 @@ //! Tests for the Statemine (Kusama Assets Hub) chain. use asset_hub_kusama_runtime::xcm_config::{ - AssetFeeAsExistentialDepositMultiplierFeeCharger, KsmLocation, TrustBackedAssetsPalletLocation, + AssetFeeAsExistentialDepositMultiplierFeeCharger, KsmLocation, LocationToAccountId, + TrustBackedAssetsPalletLocation, }; pub use asset_hub_kusama_runtime::{ xcm_config::{CheckingAccount, ForeignCreatorsSovereignAccountOf, XcmConfig}, AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, + RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue, }; use asset_test_utils::{CollatorSessionKeys, ExtBuilder}; use codec::{Decode, Encode}; @@ -632,3 +633,32 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p assert_eq!(ForeignAssets::asset_ids().collect::>().len(), 1); }) ); + +#[test] +fn reserve_transfer_native_asset_works() { + asset_test_utils::test_cases::reserve_transfer_native_asset_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + WeightLimit::Unlimited, + ); +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs index 7200ebc16a28..5dd3cbb80dec 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs @@ -19,12 +19,13 @@ use asset_hub_polkadot_runtime::xcm_config::{ AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, DotLocation, - ForeignCreatorsSovereignAccountOf, TrustBackedAssetsPalletLocation, XcmConfig, + ForeignCreatorsSovereignAccountOf, LocationToAccountId, TrustBackedAssetsPalletLocation, + XcmConfig, }; pub use asset_hub_polkadot_runtime::{ AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, + RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, XcmpQueue, }; use asset_test_utils::{CollatorSessionKeys, ExtBuilder}; use codec::{Decode, Encode}; @@ -657,3 +658,32 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p assert_eq!(ForeignAssets::asset_ids().collect::>().len(), 1); }) ); + +#[test] +fn reserve_transfer_native_asset_works() { + asset_test_utils::test_cases::reserve_transfer_native_asset_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + WeightLimit::Unlimited, + ); +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index 599ff90e254a..4d8eba91b78a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -20,10 +20,10 @@ use asset_hub_westend_runtime::{ xcm_config::{ AssetFeeAsExistentialDepositMultiplierFeeCharger, ForeignCreatorsSovereignAccountOf, - WestendLocation, + LocationToAccountId, WestendLocation, }, AllPalletsWithoutSystem, MetadataDepositBase, MetadataDepositPerByte, RuntimeCall, - RuntimeEvent, + RuntimeEvent, XcmpQueue, }; pub use asset_hub_westend_runtime::{ xcm_config::{CheckingAccount, TrustBackedAssetsPalletLocation, XcmConfig}, @@ -666,3 +666,32 @@ fn plain_receive_teleported_asset_works() { assert_eq!(outcome.ensure_complete(), Ok(())); }) } + +#[test] +fn reserve_transfer_native_asset_works() { + asset_test_utils::test_cases::reserve_transfer_native_asset_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + WeightLimit::Unlimited, + ); +} diff --git a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml index 0a27535ed22b..699d6b9198bd 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml @@ -35,6 +35,7 @@ parachains-runtimes-test-utils = { path = "../../test-utils", default-features = # Polkadot xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false} +xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false} xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false} pallet-xcm = { path = "../../../../../polkadot/xcm/pallet-xcm", default-features = false} polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain", default-features = false} @@ -71,6 +72,7 @@ std = [ "sp-io/std", "sp-runtime/std", "sp-std/std", + "xcm-builder/std", "xcm-executor/std", "xcm/std", ] diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs index 7177726e0704..f9ccb0cd61d1 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs @@ -17,4 +17,46 @@ //! Module contains predefined test-case scenarios for `Runtime` with various assets. pub mod test_cases; + +use frame_support::traits::ProcessMessageError; pub use parachains_runtimes_test_utils::*; + +use xcm::latest::prelude::*; +use xcm_builder::{CreateMatcher, MatchXcm}; + +/// Helper function to verify `xcm` contains all relevant instructions expected on destination +/// chain as part of a reserve-asset-transfer. +pub(crate) fn assert_matches_reserve_asset_deposited_instructions( + xcm: &mut Xcm, + expected_reserve_assets_deposited: &MultiAssets, + expected_beneficiary: &MultiLocation, +) { + let _ = xcm + .0 + .matcher() + .skip_inst_while(|inst| !matches!(inst, ReserveAssetDeposited(..))) + .expect("no instruction ReserveAssetDeposited?") + .match_next_inst(|instr| match instr { + ReserveAssetDeposited(reserve_assets) + if reserve_assets == expected_reserve_assets_deposited => + Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction ReserveAssetDeposited") + .match_next_inst(|instr| match instr { + ClearOrigin => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction ClearOrigin") + .match_next_inst(|instr| match instr { + BuyExecution { .. } => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction BuyExecution") + .match_next_inst(|instr| match instr { + DepositAsset { assets: _, beneficiary } if beneficiary == expected_beneficiary => + Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction DepositAsset"); +} diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 7a8d571403c6..fefe5863b4b0 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -15,23 +15,25 @@ //! Module contains predefined test-case scenarios for `Runtime` with various assets. +use crate::assert_matches_reserve_asset_deposited_instructions; use codec::Encode; +use cumulus_primitives_core::XcmpMessageSource; use frame_support::{ assert_noop, assert_ok, - traits::{fungibles::InspectEnumerable, Get, OnFinalize, OnInitialize, OriginTrait}, + traits::{fungibles::InspectEnumerable, Currency, Get, OnFinalize, OnInitialize, OriginTrait}, weights::Weight, }; use frame_system::pallet_prelude::BlockNumberFor; use parachains_common::{AccountId, Balance}; use parachains_runtimes_test_utils::{ - assert_metadata, assert_total, AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, - ValidatorIdOf, XcmReceivedFrom, + assert_metadata, assert_total, mock_open_hrmp_channel, AccountIdOf, BalanceOf, + CollatorSessionKeys, ExtBuilder, ValidatorIdOf, XcmReceivedFrom, }; use sp_runtime::{ traits::{MaybeEquivalence, StaticLookup, Zero}, DispatchError, Saturating, }; -use xcm::latest::prelude::*; +use xcm::{latest::prelude::*, VersionedMultiAssets}; use xcm_executor::{traits::ConvertLocation, XcmExecutor}; type RuntimeHelper = @@ -1059,7 +1061,7 @@ pub fn create_and_manage_foreign_assets_for_local_consensus_parachain_assets_wor AssetId: Clone + Copy, AssetIdConverter: MaybeEquivalence, { - // foreign parachain with the same consenus currency as asset + // foreign parachain with the same consensus currency as asset let foreign_asset_id_multilocation = MultiLocation { parents: 1, interior: X2(Parachain(2222), GeneralIndex(1234567)) }; let asset_id = AssetIdConverter::convert(&foreign_asset_id_multilocation).unwrap(); @@ -1339,3 +1341,188 @@ macro_rules! include_create_and_manage_foreign_assets_for_local_consensus_parach } } ); + +/// Test-case makes sure that `Runtime` can reserve-transfer asset to other parachains +pub fn reserve_transfer_native_asset_works< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + HrmpChannelOpener, + HrmpChannelSource, + LocationToAccountId, +>( + collator_session_keys: CollatorSessionKeys, + existential_deposit: BalanceOf, + alice_account: AccountIdOf, + unwrap_pallet_xcm_event: Box) -> Option>>, + unwrap_xcmp_queue_event: Box< + dyn Fn(Vec) -> Option>, + >, + weight_limit: WeightLimit, +) where + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + cumulus_pallet_parachain_system::Config + + cumulus_pallet_xcmp_queue::Config, + AllPalletsWithoutSystem: + OnInitialize> + OnFinalize>, + AccountIdOf: Into<[u8; 32]>, + ValidatorIdOf: From>, + BalanceOf: From, + ::Balance: From + Into, + XcmConfig: xcm_executor::Config, + LocationToAccountId: ConvertLocation>, + ::AccountId: + Into<<::RuntimeOrigin as OriginTrait>::AccountId>, + <::Lookup as StaticLookup>::Source: + From<::AccountId>, + ::AccountId: From, + HrmpChannelOpener: frame_support::inherent::ProvideInherent< + Call = cumulus_pallet_parachain_system::Call, + >, + HrmpChannelSource: XcmpMessageSource, +{ + let runtime_para_id = 1000; + ExtBuilder::::default() + .with_collators(collator_session_keys.collators()) + .with_session_keys(collator_session_keys.session_keys()) + .with_tracing() + .with_safe_xcm_version(3) + .with_para_id(runtime_para_id.into()) + .build() + .execute_with(|| { + let mut alice = [0u8; 32]; + alice[0] = 1; + let included_head = RuntimeHelper::::run_to_block( + 2, + AccountId::from(alice).into(), + ); + + // reserve-transfer native asset with local reserve to remote parachain (1234) + + let other_para_id = 1234; + let native_asset = MultiLocation::parent(); + let dest = MultiLocation::new(1, X1(Parachain(other_para_id))); + let dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id))) + .appended_with(AccountId32 { + network: None, + id: sp_runtime::AccountId32::new([3; 32]).into(), + }) + .unwrap(); + + let reserve_account = LocationToAccountId::convert_location(&dest) + .expect("Sovereign account for reserves"); + let balance_to_transfer = 1_000_000_000_000_u128; + + // open HRMP to other parachain + mock_open_hrmp_channel::( + runtime_para_id.into(), + other_para_id.into(), + included_head, + &alice, + ); + + // drip ED to account + let alice_account_init_balance = existential_deposit + balance_to_transfer.into(); + let _ = >::deposit_creating( + &alice_account, + alice_account_init_balance, + ); + // SA of target location needs to have at least ED, otherwise making reserve fails + let _ = >::deposit_creating( + &reserve_account, + existential_deposit, + ); + + // we just check here, that user retains enough balance after withdrawal + // and also we check if `balance_to_transfer` is more than `existential_deposit`, + assert!( + (>::free_balance(&alice_account) - + balance_to_transfer.into()) >= + existential_deposit + ); + // SA has just ED + assert_eq!( + >::free_balance(&reserve_account), + existential_deposit + ); + + // local native asset (pallet_balances) + let asset_to_transfer = MultiAsset { + fun: Fungible(balance_to_transfer.into()), + id: Concrete(native_asset), + }; + + // pallet_xcm call reserve transfer + assert_ok!(>::limited_reserve_transfer_assets( + RuntimeHelper::::origin_of(alice_account.clone()), + Box::new(dest.into_versioned()), + Box::new(dest_beneficiary.into_versioned()), + Box::new(VersionedMultiAssets::from(MultiAssets::from(asset_to_transfer))), + 0, + weight_limit, + )); + + // check alice account decreased by balance_to_transfer + // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot/pull/7005) merged + assert_eq!( + >::free_balance(&alice_account), + alice_account_init_balance - balance_to_transfer.into() + ); + + // check reserve account + // check reserve account increased by balance_to_transfer + assert_eq!( + >::free_balance(&reserve_account), + existential_deposit + balance_to_transfer.into() + ); + + // check events + // check pallet_xcm attempted + RuntimeHelper::::assert_pallet_xcm_event_outcome( + &unwrap_pallet_xcm_event, + |outcome| { + assert_ok!(outcome.ensure_complete()); + }, + ); + + // check that xcm was sent + let xcm_sent_message_hash = >::events() + .into_iter() + .filter_map(|e| unwrap_xcmp_queue_event(e.event.encode())) + .find_map(|e| match e { + cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { message_hash } => + Some(message_hash), + _ => None, + }); + + // read xcm + let xcm_sent = RuntimeHelper::::take_xcm( + other_para_id.into(), + ) + .unwrap(); + + assert_eq!( + xcm_sent_message_hash, + Some(xcm_sent.using_encoded(sp_io::hashing::blake2_256)) + ); + let mut xcm_sent: Xcm<()> = xcm_sent.try_into().expect("versioned xcm"); + + // check sent XCM Program to other parachain + println!("reserve_transfer_native_asset_works sent xcm: {:?}", xcm_sent); + let reserve_assets_deposited = MultiAssets::from(vec![MultiAsset { + id: Concrete(MultiLocation { parents: 1, interior: Here }), + fun: Fungible(1000000000000), + }]); + + assert_matches_reserve_asset_deposited_instructions( + &mut xcm_sent, + &reserve_assets_deposited, + &dest_beneficiary, + ); + }) +} From 945b34c2d6119803dfa83be544edb56b2a96eeef Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 21 Sep 2023 17:59:20 +0300 Subject: [PATCH 002/124] pallet-xcm: filter assets teleports based on XcmExecutor configuration Add AssetTransferFilter trait for configuring transfer types. Implement it for XcmExecutor based on existing executor teleports and reserves configuration. Filter assets on pallet-xcm::limited_teleport_assets() based on above. --- .../assets/asset-hub-kusama/tests/tests.rs | 6 -- .../assets/asset-hub-polkadot/tests/tests.rs | 6 -- .../assets/asset-hub-westend/tests/tests.rs | 6 -- .../assets/test-utils/src/test_cases.rs | 57 ++++++++----------- .../bridge-hub-kusama/tests/tests.rs | 6 -- .../bridge-hub-polkadot/tests/tests.rs | 6 -- .../bridge-hub-rococo/tests/tests.rs | 12 ---- polkadot/xcm/pallet-xcm/src/lib.rs | 22 ++++++- polkadot/xcm/xcm-executor/src/lib.rs | 6 ++ .../xcm-executor/src/traits/asset_transfer.rs | 29 ++++++++++ polkadot/xcm/xcm-executor/src/traits/mod.rs | 6 +- 11 files changed, 84 insertions(+), 78 deletions(-) create mode 100644 polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs index 31004dfc62e1..b8e59966b641 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs @@ -519,12 +519,6 @@ asset_test_utils::include_teleports_for_native_asset_works!( _ => None, } }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), 1000 ); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs index 5dd3cbb80dec..b232a1703302 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs @@ -532,12 +532,6 @@ asset_test_utils::include_teleports_for_native_asset_works!( _ => None, } }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), 1000 ); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index 4d8eba91b78a..66ae2fe09aa4 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -526,12 +526,6 @@ asset_test_utils::include_teleports_for_native_asset_works!( _ => None, } }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), 1000 ); diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index fefe5863b4b0..25360171cc8f 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -42,8 +42,8 @@ type RuntimeHelper = // Re-export test_case from `parachains-runtimes-test-utils` pub use parachains_runtimes_test_utils::test_cases::change_storage_constant_by_governance_works; -/// Test-case makes sure that `Runtime` can receive native asset from relay chain -/// and can teleport it back and to the other parachains +/// Test-case makes sure that `Runtime` can receive native asset from relay chain and can teleport +/// it back pub fn teleports_for_native_asset_works< Runtime, AllPalletsWithoutSystem, @@ -56,9 +56,6 @@ pub fn teleports_for_native_asset_works< existential_deposit: BalanceOf, target_account: AccountIdOf, unwrap_pallet_xcm_event: Box) -> Option>>, - unwrap_xcmp_queue_event: Box< - dyn Fn(Vec) -> Option>, - >, runtime_para_id: u32, ) where Runtime: frame_system::Config @@ -204,7 +201,8 @@ pub fn teleports_for_native_asset_works< ); } - // 3. try to teleport asset away to other parachain (1234) + // 3. try to teleport assets away to other parachain (1234): should not work as we don't + // trust `IsTeleporter` for `(relay-native-asset, para(1234))` pair { let other_para_id = 1234; let dest = MultiLocation::new(1, X1(Parachain(other_para_id))); @@ -217,41 +215,38 @@ pub fn teleports_for_native_asset_works< let target_account_balance_before_teleport = >::free_balance(&target_account); + let native_asset_to_teleport_away = native_asset_amount_unit * 3.into(); assert!( native_asset_to_teleport_away < target_account_balance_before_teleport - existential_deposit ); - - assert_ok!(RuntimeHelper::::do_teleport_assets::( - RuntimeHelper::::origin_of(target_account.clone()), - dest, - dest_beneficiary, - (native_asset_id, native_asset_to_teleport_away.into()), - Some((runtime_para_id, other_para_id)), - included_head, - &alice, - )); + assert_eq!( + RuntimeHelper::::do_teleport_assets::( + RuntimeHelper::::origin_of(target_account.clone()), + dest, + dest_beneficiary, + (native_asset_id, native_asset_to_teleport_away.into()), + Some((runtime_para_id, other_para_id)), + included_head, + &alice, + ), + Err(DispatchError::Module(sp_runtime::ModuleError { + index: 31, + error: [2, 0, 0, 0,], + message: Some("Filtered",), + },),) + ); // check balances assert_eq!( >::free_balance(&target_account), - target_account_balance_before_teleport - native_asset_to_teleport_away + target_account_balance_before_teleport ); assert_eq!( >::free_balance(&CheckingAccount::get()), 0.into() ); - - // check events - RuntimeHelper::::assert_pallet_xcm_event_outcome( - &unwrap_pallet_xcm_event, - |outcome| { - assert_ok!(outcome.ensure_complete()); - }, - ); - assert!(RuntimeHelper::::xcmp_queue_message_sent(unwrap_xcmp_queue_event) - .is_some()); } }) } @@ -268,7 +263,6 @@ macro_rules! include_teleports_for_native_asset_works( $collator_session_key:expr, $existential_deposit:expr, $unwrap_pallet_xcm_event:expr, - $unwrap_xcmp_queue_event:expr, $runtime_para_id:expr ) => { #[test] @@ -288,15 +282,14 @@ macro_rules! include_teleports_for_native_asset_works( $existential_deposit, target_account, $unwrap_pallet_xcm_event, - $unwrap_xcmp_queue_event, $runtime_para_id ) } } ); -/// Test-case makes sure that `Runtime` can receive teleported assets from sibling parachain relay -/// chain +/// Test-case makes sure that `Runtime` can receive teleported assets from sibling parachain, and +/// can teleport it back pub fn teleports_for_foreign_assets_works< Runtime, AllPalletsWithoutSystem, @@ -442,7 +435,7 @@ pub fn teleports_for_foreign_assets_works< >(foreign_asset_id_multilocation, 0, 0); assert!(teleported_foreign_asset_amount > asset_minimum_asset_balance); - // 1. process received teleported assets from relaychain + // 1. process received teleported assets from sibling parachain (foreign_para_id) let xcm = Xcm(vec![ // BuyExecution with relaychain native token WithdrawAsset(buy_execution_fee.clone().into()), diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs index 893524e12f66..36d8f0846af2 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs @@ -47,11 +47,5 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( _ => None, } }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), 1002 ); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs index 0be87bd46fac..3156a5fe68e5 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs @@ -47,11 +47,5 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( _ => None, } }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), 1002 ); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index e5fe67f2a8e5..cc8052008824 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -118,12 +118,6 @@ mod bridge_hub_rococo_tests { _ => None, } }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), bp_bridge_hub_rococo::BRIDGE_HUB_ROCOCO_PARACHAIN_ID ); @@ -297,12 +291,6 @@ mod bridge_hub_wococo_tests { _ => None, } }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), bp_bridge_hub_wococo::BRIDGE_HUB_WOCOCO_PARACHAIN_ID ); diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 321bb294b88d..58adb90e1729 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -41,7 +41,7 @@ use sp_runtime::{ }; use sp_std::{boxed::Box, marker::PhantomData, prelude::*, result::Result, vec}; use xcm::{latest::QueryResponseInfo, prelude::*}; -use xcm_executor::traits::{ConvertOrigin, Properties}; +use xcm_executor::traits::{AssetTransferFilter, ConvertOrigin, Properties}; use frame_support::{ dispatch::GetDispatchInfo, pallet_prelude::*, traits::WithdrawReasons, PalletId, @@ -206,7 +206,7 @@ pub mod pallet { type XcmExecuteFilter: Contains<(MultiLocation, Xcm<::RuntimeCall>)>; /// Something to execute an XCM message. - type XcmExecutor: ExecuteXcm<::RuntimeCall>; + type XcmExecutor: ExecuteXcm<::RuntimeCall> + AssetTransferFilter; /// Our XCM filter which messages to be teleported using the dedicated extrinsic must pass. type XcmTeleportFilter: Contains<(MultiLocation, Vec)>; @@ -1212,6 +1212,18 @@ impl Pallet { let value = (origin_location, assets.into_inner()); ensure!(T::XcmReserveTransferFilter::contains(&value), Error::::Filtered); let (origin_location, assets) = value; + // Don't allow inclusion of teleportable assets in this reserve-based-transfer (other than + // fee asset). + for (idx, asset) in assets.iter().enumerate() { + ensure!( + idx == fee_asset_item as usize || + !::IsTeleporter::contains( + asset, &dest + ), + Error::::Filtered + ); + } + let context = T::UniversalLocation::get(); let fees = assets .get(fee_asset_item as usize) @@ -1256,6 +1268,12 @@ impl Pallet { let value = (origin_location, assets.into_inner()); ensure!(T::XcmTeleportFilter::contains(&value), Error::::Filtered); let (origin_location, assets) = value; + for asset in assets.iter() { + ensure!( + ::IsTeleporter::contains(asset, &dest), + Error::::Filtered + ); + } let context = T::UniversalLocation::get(); let fees = assets .get(fee_asset_item as usize) diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index a48cd3259d67..a5575b6952f1 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -38,6 +38,7 @@ use traits::{ mod assets; pub use assets::Assets; mod config; +use crate::traits::AssetTransferFilter; pub use config::Config; /// A struct to specify how fees are being paid. @@ -254,6 +255,11 @@ impl ExecuteXcm for XcmExecutor AssetTransferFilter for XcmExecutor { + type IsReserve = Config::IsReserve; + type IsTeleporter = Config::IsTeleporter; +} + #[derive(Debug)] pub struct ExecutorError { pub index: u32, diff --git a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs new file mode 100644 index 000000000000..c8fdc582bf11 --- /dev/null +++ b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs @@ -0,0 +1,29 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +use frame_support::traits::ContainsPair; +use xcm::prelude::*; + +/// A trait for identifying asset transfer type. +pub trait AssetTransferFilter { + /// Combinations of (Asset, Location) pairs which we trust as reserves. Meaning + /// reserve-based-transfers are to be used for assets matching this filter. + type IsReserve: ContainsPair; + + /// Combinations of (Asset, Location) pairs which we trust as teleporters. Meaning teleports are + /// to be used for assets matching this filter. + type IsTeleporter: ContainsPair; +} diff --git a/polkadot/xcm/xcm-executor/src/traits/mod.rs b/polkadot/xcm/xcm-executor/src/traits/mod.rs index a9439968fa6c..201634c7bcbb 100644 --- a/polkadot/xcm/xcm-executor/src/traits/mod.rs +++ b/polkadot/xcm/xcm-executor/src/traits/mod.rs @@ -20,10 +20,12 @@ mod conversion; pub use conversion::{CallDispatcher, ConvertLocation, ConvertOrigin, WithOriginFilter}; mod drop_assets; pub use drop_assets::{ClaimAssets, DropAssets}; -mod asset_lock; -pub use asset_lock::{AssetLock, Enact, LockError}; mod asset_exchange; pub use asset_exchange::AssetExchange; +mod asset_lock; +pub use asset_lock::{AssetLock, Enact, LockError}; +mod asset_transfer; +pub use asset_transfer::AssetTransferFilter; mod export; pub use export::{export_xcm, validate_export, ExportXcm}; mod fee_manager; From ce215a1415caaa49c4b513a0d89cc6a1cdeea568 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 20 Sep 2023 15:12:47 +0300 Subject: [PATCH 003/124] xcm: MultiLocation: add .chain_location() helper function --- .../assets/test-utils/src/test_cases.rs | 2 +- polkadot/xcm/src/v3/junction.rs | 8 +++ polkadot/xcm/src/v3/multilocation.rs | 65 +++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 25360171cc8f..4b5350f0e2aa 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -343,7 +343,7 @@ pub fn teleports_for_foreign_assets_works< From<::AccountId>, ForeignAssetsPalletInstance: 'static, { - // foreign parachain with the same consenus currency as asset + // foreign parachain with the same consensus currency as asset let foreign_para_id = 2222; let foreign_asset_id_multilocation = MultiLocation { parents: 1, diff --git a/polkadot/xcm/src/v3/junction.rs b/polkadot/xcm/src/v3/junction.rs index b5dd5bc7c88f..cd6d4f85dc26 100644 --- a/polkadot/xcm/src/v3/junction.rs +++ b/polkadot/xcm/src/v3/junction.rs @@ -437,6 +437,14 @@ impl Junction { _ => {}, } } + + /// Specifies whether junction identifies a chain. + pub fn is_chain_identifier(&self) -> bool { + match self { + Junction::Parachain(_) | Junction::GlobalConsensus(_) => true, + _ => false, + } + } } #[cfg(test)] diff --git a/polkadot/xcm/src/v3/multilocation.rs b/polkadot/xcm/src/v3/multilocation.rs index 8a1575d9bc95..0f226a1f1565 100644 --- a/polkadot/xcm/src/v3/multilocation.rs +++ b/polkadot/xcm/src/v3/multilocation.rs @@ -444,6 +444,20 @@ impl MultiLocation { } } } + + /// Return the MultiLocation subsection identifying the chain that `self` points to. + pub fn chain_location(mut self) -> MultiLocation { + // start popping junctions until we reach chain identifier + while let Some(j) = self.last() { + if j.is_chain_identifier() { + // return chain subsection + return self + } else { + (self, _) = self.split_last_interior(); + } + } + MultiLocation::new(self.parents, Junctions::Here) + } } impl TryFrom for MultiLocation { @@ -674,6 +688,57 @@ mod tests { assert_eq!(iter.next_back(), None); } + #[test] + fn chain_location_works() { + // Relay-chain or parachain context pointing to local resource, + let relay_to_local = MultiLocation::new(0, (PalletInstance(42), GeneralIndex(42))); + assert_eq!(relay_to_local.chain_location(), MultiLocation::here()); + + // Relay-chain context pointing to child parachain, + let relay_to_child = + MultiLocation::new(0, (Parachain(42), PalletInstance(42), GeneralIndex(42))); + let expected = MultiLocation::new(0, Parachain(42)); + assert_eq!(relay_to_child.chain_location(), expected); + + // Relay-chain context pointing to different consensus relay, + let relay_to_remote_relay = + MultiLocation::new(1, (GlobalConsensus(Kusama), PalletInstance(42), GeneralIndex(42))); + let expected = MultiLocation::new(1, GlobalConsensus(Kusama)); + assert_eq!(relay_to_remote_relay.chain_location(), expected); + + // Relay-chain context pointing to different consensus parachain, + let relay_to_remote_para = MultiLocation::new( + 1, + (GlobalConsensus(Kusama), Parachain(42), PalletInstance(42), GeneralIndex(42)), + ); + let expected = MultiLocation::new(1, (GlobalConsensus(Kusama), Parachain(42))); + assert_eq!(relay_to_remote_para.chain_location(), expected); + + // Parachain context pointing to relay chain, + let para_to_relay = MultiLocation::new(1, (PalletInstance(42), GeneralIndex(42))); + assert_eq!(para_to_relay.chain_location(), MultiLocation::parent()); + + // Parachain context pointing to sibling parachain, + let para_to_sibling = + MultiLocation::new(1, (Parachain(42), PalletInstance(42), GeneralIndex(42))); + let expected = MultiLocation::new(1, Parachain(42)); + assert_eq!(para_to_sibling.chain_location(), expected); + + // Parachain context pointing to different consensus relay, + let para_to_remote_relay = + MultiLocation::new(2, (GlobalConsensus(Kusama), PalletInstance(42), GeneralIndex(42))); + let expected = MultiLocation::new(2, GlobalConsensus(Kusama)); + assert_eq!(para_to_remote_relay.chain_location(), expected); + + // Parachain context pointing to different consensus parachain, + let para_to_remote_para = MultiLocation::new( + 2, + (GlobalConsensus(Kusama), Parachain(42), PalletInstance(42), GeneralIndex(42)), + ); + let expected = MultiLocation::new(2, (GlobalConsensus(Kusama), Parachain(42))); + assert_eq!(para_to_remote_para.chain_location(), expected); + } + #[test] fn conversion_from_other_types_works() { use crate::v2; From a5fd7460e787d8a1893aa2e47e5841a8003fc10e Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 25 Sep 2023 19:09:22 +0300 Subject: [PATCH 004/124] pallet-xcm: enchance reserve_transfer_assets() to support various reserves 'reserve_transfer_assets()' assumed all provided `assets` (fees included) have same, local reserve. This commit enhances the extrinsic to support various scenarios: - transferring assets with reserve on destination, - transferring assets with reserve on remote/third-party chain, - transferring assets with reserve different than the reserve of the asset to be used as fees - meaning can use to transfer random asset with random reserve while using DOT for fees on all involved chains, even if local chain is NOT a reserve location of DOT (aka most chains), - transferring assets with any type of local/dest/remote reserve while using fees which can be teleported between involved chains. All of the above is done by pallet inner logic without the user having to specify which scenario/reserves/teleports/etc. The correct scenario and corresponding XCM programs are identified, and respectively, built automatically based on runtime configuration of trusted teleporters and trusted reserves. Current limitations: - while `fees` and "non-fee" `assets` CAN have different reserves (or fees CAN be teleported), the remaining "non-fee" `assets` CANNOT have different reserve locations (this is also implicitly enforced by `MAX_ASSETS_FOR_TRANSFER=2`, but this can be safely increased in the future). - `fees` and "non-fee" `assets` CANNOT have **different remote** reserves (this can also be supported in the future, but adds even more complexity while possibly not being worth it - we'll see what the future holds). --- polkadot/xcm/pallet-xcm/src/lib.rs | 329 ++++++++++++++++++++++++++--- 1 file changed, 299 insertions(+), 30 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 58adb90e1729..a0788eab29fa 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -442,6 +442,10 @@ pub mod pallet { LockNotFound, /// The unlock operation cannot succeed because there are still consumers of the lock. InUse, + /// Reserve chain could not be determined for assets to be transferred. + UnknownReserve, + /// Too many assets with different reserve locations have been attempted for transfer. + TooManyReserves, } impl From for Error { @@ -1193,14 +1197,89 @@ impl QueryHandler for Pallet { } } +#[derive(Copy, Clone, PartialEq, Debug)] +enum TransferType { + Teleport, + LocalReserve, + DestinationReserve, + RemoteReserve(MultiLocation), +} + +impl TransferType { + /// Determine transfer type to be used for transferring `asset` from local chain to `dest`. + pub fn determine_for( + asset: &MultiAsset, + dest: &MultiLocation, + ) -> Result> { + if ::IsTeleporter::contains(asset, dest) { + // we trust destination for teleporting asset + return Ok(TransferType::Teleport) + } else if ::IsReserve::contains(asset, dest) { + // we trust destination as asset reserve location + return Ok(TransferType::DestinationReserve) + } + + // try to determine reserve location based on asset id/location + let asset_location = match asset.id { + Concrete(location) => Ok(location.chain_location()), + _ => Err(Error::::InvalidAsset), + }?; + if asset_location == MultiLocation::here() || + ::IsTeleporter::contains( + asset, + &asset_location, + ) { + // local asset, or remote location that allows local teleports => local reserve + Ok(TransferType::LocalReserve) + } else if ::IsReserve::contains( + asset, + &asset_location, + ) { + // remote location that is recognized as reserve location for asset + Ok(TransferType::RemoteReserve(asset_location)) + } else { + // remote location that is not configured either as teleporter or reserve => cannot + // determine asset reserve + Err(Error::::UnknownReserve) + } + } +} + impl Pallet { + /// Validate `assets` to be reserve-transferred and return their reserve location. + fn validate_assets_and_find_reserve( + assets: &[MultiAsset], + dest: &MultiLocation, + ) -> Result> { + let mut reserve = None; + for asset in assets.iter() { + // Ensure fungible asset. + ensure!( + matches!(asset.fun, Fungibility::Fungible(x) if !x.is_zero()), + Error::::InvalidAsset + ); + let transfer_type = TransferType::determine_for::(&asset, dest)?; + // Ensure asset is not teleportable to `dest`. + ensure!(transfer_type != TransferType::Teleport, Error::::Filtered); + if let Some(reserve) = reserve.as_ref() { + // Ensure transfer for multiple assets uses same reserve location (only fee may have + // different reserve location) + ensure!(reserve == &transfer_type, Error::::TooManyReserves); + } else { + // asset reserve identified + reserve = Some(transfer_type); + } + } + reserve.ok_or(Error::::Empty) + } + fn do_reserve_transfer_assets( origin: OriginFor, dest: Box, beneficiary: Box, assets: Box, fee_asset_item: u32, - weight_limit: WeightLimit, + mut weight_limit: WeightLimit, ) -> DispatchResult { let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; @@ -1211,43 +1290,215 @@ impl Pallet { ensure!(assets.len() <= MAX_ASSETS_FOR_TRANSFER, Error::::TooManyAssets); let value = (origin_location, assets.into_inner()); ensure!(T::XcmReserveTransferFilter::contains(&value), Error::::Filtered); - let (origin_location, assets) = value; - // Don't allow inclusion of teleportable assets in this reserve-based-transfer (other than - // fee asset). - for (idx, asset) in assets.iter().enumerate() { - ensure!( - idx == fee_asset_item as usize || - !::IsTeleporter::contains( - asset, &dest - ), - Error::::Filtered - ); + let (origin_location, mut assets) = value; + + if fee_asset_item as usize >= assets.len() { + return Err(Error::::Empty.into()) + } + let fees = assets.swap_remove(fee_asset_item as usize); + let fees_transfer_type = TransferType::determine_for::(&fees, &dest)?; + let assets_transfer_type = if assets.is_empty() { + // Single asset to transfer (also used for fees). + fees_transfer_type.clone() + } else { + // Find reserve for non-fee assets. + Self::validate_assets_and_find_reserve(&assets, &dest)? + }; + + // Disallow (for now) different _remote_ reserves for assets and fees. + match (&fees_transfer_type, &assets_transfer_type) { + (TransferType::RemoteReserve(a), TransferType::RemoteReserve(b)) if a != b => + return Err(Error::::TooManyReserves.into()), + _ => (), + }; + + if fees_transfer_type == assets_transfer_type { + // Same reserve location (fees not teleportable), we can batch together fees and assets + // in same reserve-based-transfer. + assets.push(fees.clone()); + } else { + // Different transfer types: we have to do separate transfers for fees and assets. + // This code block handles transferring the assets *used for fees*. + + // Use only half the weight limit for fees transfer, then other half for assets + // transfer. + weight_limit = Self::halve_weight_limit(&weight_limit); + + // When assets reserve is remote chain, we need to "prefund" fees to be able to + // BuyExecution on both chains. Split fees, and deposit half at assets-reserve chain + // and half at destination. + if let TransferType::RemoteReserve(assets_reserve) = assets_transfer_type { + let (fees_for_reserve, fees_for_dest) = Self::equal_split_asset(&fees)?; + // Halve weight limit again to be used for the two fees transfers. + let quarter_weight_limit = Self::halve_weight_limit(&weight_limit); + // TODO: + // let assets_reserve_beneficiary = sov_acc_of(dest, assets_reserve); + let assets_reserve_beneficiary = beneficiary.clone(); + // Send half the `fees` to + Self::prefund_transfer_fees( + origin_location, + assets_reserve, + assets_reserve_beneficiary, + fees_for_reserve, + quarter_weight_limit.clone(), + )?; + Self::prefund_transfer_fees( + origin_location, + dest, + beneficiary, + fees_for_dest, + quarter_weight_limit, + )?; + } else { + Self::prefund_transfer_fees( + origin_location, + dest, + beneficiary, + fees.clone(), + weight_limit.clone(), + )?; + } } + // Fees have been prefunded/transferred (or batched together with assets), now do + // reserve-transfer assets. + Self::build_and_execute_xcm_transfer_type( + origin_location, + dest, + beneficiary, + assets, + assets_transfer_type, + fees, + weight_limit, + ) + } + + /// Teleport or reserve transfer `fees` - not to be used by itself, it is a helper function for + /// prefunding fees for subsequent assets transfer. + /// + /// Fees are allowed to be either teleported or reserve transferred. + fn prefund_transfer_fees( + origin: impl Into, + dest: MultiLocation, + beneficiary: MultiLocation, + asset: MultiAsset, + weight_limit: WeightLimit, + ) -> DispatchResult { + // TODO + Ok(()) + } + + fn build_and_execute_xcm_transfer_type( + origin: impl Into, + dest: MultiLocation, + beneficiary: MultiLocation, + assets: Vec, + transfer_type: TransferType, + fees: MultiAsset, + weight_limit: WeightLimit, + ) -> DispatchResult { + let mut message = match transfer_type { + TransferType::LocalReserve => + Self::local_reserve_transfer_message(dest, beneficiary, assets, fees, weight_limit), + TransferType::DestinationReserve => Self::destination_reserve_transfer_message( + dest, + beneficiary, + assets, + fees, + weight_limit, + ), + TransferType::RemoteReserve(reserve) => Self::remote_reserve_transfer_message( + reserve, + dest, + beneficiary, + assets, + fees, + weight_limit, + ), + TransferType::Teleport => todo!(), + }?; + let weight = + T::Weigher::weight(&mut message).map_err(|()| Error::::UnweighableMessage)?; + let hash = message.using_encoded(sp_io::hashing::blake2_256); + let outcome = T::XcmExecutor::execute_xcm_in_credit(origin, message, hash, weight, weight); + Self::deposit_event(Event::Attempted { outcome }); + Ok(()) + } + + fn local_reserve_transfer_message( + dest: MultiLocation, + beneficiary: MultiLocation, + assets: Vec, + fees: MultiAsset, + weight_limit: WeightLimit, + ) -> Result::RuntimeCall>, Error> { let context = T::UniversalLocation::get(); - let fees = assets - .get(fee_asset_item as usize) - .ok_or(Error::::Empty)? - .clone() - .reanchored(&dest, context) - .map_err(|_| Error::::CannotReanchor)?; + let fees = fees.reanchored(&dest, context).map_err(|_| Error::::CannotReanchor)?; let max_assets = assets.len() as u32; - let assets: MultiAssets = assets.into(); - let xcm = Xcm(vec![ + let xcm_on_dest = Xcm(vec![ BuyExecution { fees, weight_limit }, DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, ]); - let mut message = Xcm(vec![ + Ok(Xcm(vec![ SetFeesMode { jit_withdraw: true }, - TransferReserveAsset { assets, dest, xcm }, - ]); - let weight = - T::Weigher::weight(&mut message).map_err(|()| Error::::UnweighableMessage)?; - let hash = message.using_encoded(sp_io::hashing::blake2_256); - let outcome = - T::XcmExecutor::execute_xcm_in_credit(origin_location, message, hash, weight, weight); - Self::deposit_event(Event::Attempted { outcome }); - Ok(()) + TransferReserveAsset { assets: assets.into(), dest, xcm: xcm_on_dest }, + ])) + } + + fn destination_reserve_transfer_message( + dest: MultiLocation, + beneficiary: MultiLocation, + assets: Vec, + fees: MultiAsset, + weight_limit: WeightLimit, + ) -> Result::RuntimeCall>, Error> { + // let context = T::UniversalLocation::get(); + // let fees = assets.get(fee_asset_item as usize).reanchored(&dest, context); + // Ok(Xcm(vec![ + // WithdrawAsset(assets), + // InitiateReserveWithdraw { + // assets: Wild(AllCounted(max_assets)), + // reserve: dest, + // xcm: Xcm(vec![ + // BuyExecution { fees, weight_limit }, + // DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, + // ]), + // }, + // ])) + todo!() + } + + fn remote_reserve_transfer_message( + reserve: MultiLocation, + dest: MultiLocation, + beneficiary: MultiLocation, + assets: Vec, + fees: MultiAsset, + weight_limit: WeightLimit, + ) -> Result::RuntimeCall>, Error> { + // let context = T::UniversalLocation::get(); + // let reserve_fees = assets.get(fee_asset_item as usize).reanchored(&reserve, context); + // let dest_fees = assets.get(fee_asset_item as usize).reanchored(&dest, context); + // let dest = dest.reanchored(&reserve, context); + // Ok(Xcm(vec![ + // WithdrawAsset(assets), + // InitiateReserveWithdraw { + // assets: Wild(AllCounted(max_assets)), + // reserve, + // xcm: Xcm(vec![ + // BuyExecution { fees: reserve_fees, weight_limit }, + // DepositReserveAsset { + // assets: Wild(AllCounted(max_assets)), + // dest, + // xcm: Xcm(vec![ + // BuyExecution { fees: dest_fees, weight_limit }, + // DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, + // ]), + // }, + // ]), + // }, + // ])) + todo!() } fn do_teleport_assets( @@ -1635,6 +1886,24 @@ impl Pallet { Self::deposit_event(Event::FeesPaid { paying: location, fees: assets }); Ok(()) } + + /// Return `WeightLimit` with half the given weight `limit`. + fn halve_weight_limit(limit: &WeightLimit) -> WeightLimit { + match limit { + Unlimited => Unlimited, + Limited(w) => Limited(w.saturating_div(2)), + } + } + + /// Split fungible `asset` in two equal `MultiAsset`s. + fn equal_split_asset(asset: &MultiAsset) -> Result<(MultiAsset, MultiAsset), Error> { + let half_amount = match &asset.fun { + Fungible(amount) => amount.saturating_div(2), + NonFungible(_) => return Err(Error::::InvalidAsset), + }; + let half = MultiAsset { fun: Fungible(half_amount), id: asset.id }; + Ok((half.clone(), half)) + } } pub struct LockTicket { From c581d763cfc9b154003cb611c88981b35776226e Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 25 Sep 2023 19:55:36 +0300 Subject: [PATCH 005/124] use correct fees beneficiary on assets reserve chain --- polkadot/xcm/pallet-xcm/src/lib.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index a0788eab29fa..98b30d212f1e 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1331,10 +1331,12 @@ impl Pallet { let (fees_for_reserve, fees_for_dest) = Self::equal_split_asset(&fees)?; // Halve weight limit again to be used for the two fees transfers. let quarter_weight_limit = Self::halve_weight_limit(&weight_limit); - // TODO: - // let assets_reserve_beneficiary = sov_acc_of(dest, assets_reserve); - let assets_reserve_beneficiary = beneficiary.clone(); - // Send half the `fees` to + let context = T::UniversalLocation::get(); + // Send half the `fees` to the Sovereign Account of `dest` on assets-reserve chain. + let assets_reserve_beneficiary = dest + .clone() + .reanchored(&assets_reserve, context) + .map_err(|_| Error::::CannotReanchor)?; Self::prefund_transfer_fees( origin_location, assets_reserve, From fe52d4807f9d27348e394910f93445debc7aa718 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 26 Sep 2023 14:44:44 +0300 Subject: [PATCH 006/124] build dest-reserve and remote-reserve XCM programs --- polkadot/xcm/pallet-xcm/src/lib.rs | 104 ++++++++++++++++------------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 98b30d212f1e..7ae28d43f495 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1352,6 +1352,10 @@ impl Pallet { quarter_weight_limit, )?; } else { + if let TransferType::RemoteReserve(_fees_reserve) = fees_transfer_type { + // TODO: change beneficiary on `fee_reserve` to be SA-of-Here. + // But beneficiary on `dest` should stay unchanged... + } Self::prefund_transfer_fees( origin_location, dest, @@ -1380,14 +1384,13 @@ impl Pallet { /// /// Fees are allowed to be either teleported or reserve transferred. fn prefund_transfer_fees( - origin: impl Into, - dest: MultiLocation, - beneficiary: MultiLocation, - asset: MultiAsset, - weight_limit: WeightLimit, + _origin: impl Into, + _dest: MultiLocation, + _beneficiary: MultiLocation, + _asset: MultiAsset, + _weight_limit: WeightLimit, ) -> DispatchResult { - // TODO - Ok(()) + todo!() } fn build_and_execute_xcm_transfer_type( @@ -1431,11 +1434,11 @@ impl Pallet { dest: MultiLocation, beneficiary: MultiLocation, assets: Vec, - fees: MultiAsset, + mut fees: MultiAsset, weight_limit: WeightLimit, ) -> Result::RuntimeCall>, Error> { let context = T::UniversalLocation::get(); - let fees = fees.reanchored(&dest, context).map_err(|_| Error::::CannotReanchor)?; + fees.reanchor(&dest, context).map_err(|_| Error::::CannotReanchor)?; let max_assets = assets.len() as u32; let xcm_on_dest = Xcm(vec![ BuyExecution { fees, weight_limit }, @@ -1451,23 +1454,24 @@ impl Pallet { dest: MultiLocation, beneficiary: MultiLocation, assets: Vec, - fees: MultiAsset, + mut fees: MultiAsset, weight_limit: WeightLimit, ) -> Result::RuntimeCall>, Error> { - // let context = T::UniversalLocation::get(); - // let fees = assets.get(fee_asset_item as usize).reanchored(&dest, context); - // Ok(Xcm(vec![ - // WithdrawAsset(assets), - // InitiateReserveWithdraw { - // assets: Wild(AllCounted(max_assets)), - // reserve: dest, - // xcm: Xcm(vec![ - // BuyExecution { fees, weight_limit }, - // DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, - // ]), - // }, - // ])) - todo!() + let context = T::UniversalLocation::get(); + fees.reanchor(&dest, context).map_err(|_| Error::::CannotReanchor)?; + let max_assets = assets.len() as u32; + let xcm_on_dest = Xcm(vec![ + BuyExecution { fees, weight_limit }, + DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, + ]); + Ok(Xcm(vec![ + WithdrawAsset(assets.into()), + InitiateReserveWithdraw { + assets: Wild(AllCounted(max_assets)), + reserve: dest, + xcm: xcm_on_dest, + }, + ])) } fn remote_reserve_transfer_message( @@ -1478,29 +1482,35 @@ impl Pallet { fees: MultiAsset, weight_limit: WeightLimit, ) -> Result::RuntimeCall>, Error> { - // let context = T::UniversalLocation::get(); - // let reserve_fees = assets.get(fee_asset_item as usize).reanchored(&reserve, context); - // let dest_fees = assets.get(fee_asset_item as usize).reanchored(&dest, context); - // let dest = dest.reanchored(&reserve, context); - // Ok(Xcm(vec![ - // WithdrawAsset(assets), - // InitiateReserveWithdraw { - // assets: Wild(AllCounted(max_assets)), - // reserve, - // xcm: Xcm(vec![ - // BuyExecution { fees: reserve_fees, weight_limit }, - // DepositReserveAsset { - // assets: Wild(AllCounted(max_assets)), - // dest, - // xcm: Xcm(vec![ - // BuyExecution { fees: dest_fees, weight_limit }, - // DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, - // ]), - // }, - // ]), - // }, - // ])) - todo!() + let max_assets = assets.len() as u32; + let context = T::UniversalLocation::get(); + // identifies fee item as seen by `reserve` - to be used at reserve chain + let reserve_fees = fees + .clone() + .reanchored(&reserve, context) + .map_err(|_| Error::::CannotReanchor)?; + // identifies fee item as seen by `dest` - to be used at destination chain + let dest_fees = fees.reanchored(&dest, context).map_err(|_| Error::::CannotReanchor)?; + // identifies `dest` as seen by `reserve` + let dest = dest.reanchored(&reserve, context).map_err(|_| Error::::CannotReanchor)?; + // xcm to be executed at dest + let xcm_on_dest = Xcm(vec![ + BuyExecution { fees: dest_fees, weight_limit: weight_limit.clone() }, + DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, + ]); + // xcm to be executed on reserve + let xcm_on_reserve = Xcm(vec![ + BuyExecution { fees: reserve_fees, weight_limit }, + DepositReserveAsset { assets: Wild(AllCounted(max_assets)), dest, xcm: xcm_on_dest }, + ]); + Ok(Xcm(vec![ + WithdrawAsset(assets.into()), + InitiateReserveWithdraw { + assets: Wild(AllCounted(max_assets)), + reserve, + xcm: xcm_on_reserve, + }, + ])) } fn do_teleport_assets( From 5d847e35f02a823585700752d55fca9f0d8bb8f5 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 26 Sep 2023 15:12:27 +0300 Subject: [PATCH 007/124] deduplicate teleport and reserve transfer tests --- polkadot/xcm/pallet-xcm/src/mock.rs | 4 +- polkadot/xcm/pallet-xcm/src/tests.rs | 274 +++++++++------------------ 2 files changed, 90 insertions(+), 188 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index b09bcb80ed67..9895249148ef 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -370,10 +370,10 @@ pub(crate) fn buy_execution(fees: impl Into) -> Instruction { pub(crate) fn buy_limited_execution( fees: impl Into, - weight: Weight, + weight_limit: WeightLimit, ) -> Instruction { use xcm::latest::prelude::*; - BuyExecution { fees: fees.into(), weight_limit: Limited(weight) } + BuyExecution { fees: fees.into(), weight_limit } } pub(crate) fn new_test_ext_with_balances( diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 5d8aee8d665f..522ca00a2886 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -346,12 +346,12 @@ fn send_fails_when_xcm_router_blocks() { }); } -/// Test `teleport_assets` -/// -/// Asserts that the sender's balance is decreased as a result of execution of -/// local effects. -#[test] -fn teleport_assets_works() { +// Helper function to deduplicate testing different teleport types. +fn do_test_and_verify_teleport_assets( + dest: MultiLocation, + call: Call, + expected_weight_limit: WeightLimit, +) { let balances = vec![ (ALICE, INITIAL_BALANCE), (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), @@ -359,14 +359,8 @@ fn teleport_assets_works() { new_test_ext_with_balances(balances).execute_with(|| { let weight = BaseXcmWeight::get() * 3; assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into(); - assert_ok!(XcmPallet::teleport_assets( - RuntimeOrigin::signed(ALICE), - Box::new(RelayLocation::get().into()), - Box::new(dest.into()), - Box::new((Here, SEND_AMOUNT).into()), - 0, - )); + // call extrinsic + call(); assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); assert_eq!( sent_xcm(), @@ -375,7 +369,7 @@ fn teleport_assets_works() { Xcm(vec![ ReceiveTeleportedAsset((Here, SEND_AMOUNT).into()), ClearOrigin, - buy_execution((Here, SEND_AMOUNT)), + buy_limited_execution((Here, SEND_AMOUNT), expected_weight_limit), DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, ]), )] @@ -389,113 +383,68 @@ fn teleport_assets_works() { }); } -/// Test `limited_teleport_assets` +/// Test `teleport_assets` /// /// Asserts that the sender's balance is decreased as a result of execution of /// local effects. #[test] -fn limited_teleport_assets_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - new_test_ext_with_balances(balances).execute_with(|| { - let weight = BaseXcmWeight::get() * 3; - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into(); - assert_ok!(XcmPallet::limited_teleport_assets( - RuntimeOrigin::signed(ALICE), - Box::new(RelayLocation::get().into()), - Box::new(dest.into()), - Box::new((Here, SEND_AMOUNT).into()), - 0, - WeightLimit::Limited(Weight::from_parts(5000, 5000)), - )); - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); - assert_eq!( - sent_xcm(), - vec![( - RelayLocation::get().into(), - Xcm(vec![ - ReceiveTeleportedAsset((Here, SEND_AMOUNT).into()), - ClearOrigin, - buy_limited_execution((Here, SEND_AMOUNT), Weight::from_parts(5000, 5000)), - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]), - )] - ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) - ); - }); +fn teleport_assets_works() { + let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into(); + do_test_and_verify_teleport_assets( + dest, + || { + assert_ok!(XcmPallet::teleport_assets( + RuntimeOrigin::signed(ALICE), + Box::new(RelayLocation::get().into()), + Box::new(dest.into()), + Box::new((Here, SEND_AMOUNT).into()), + 0, + )); + }, + Unlimited, + ); } -/// Test `limited_teleport_assets` with unlimited weight +/// Test `limited_teleport_assets` /// /// Asserts that the sender's balance is decreased as a result of execution of /// local effects. #[test] -fn unlimited_teleport_assets_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - new_test_ext_with_balances(balances).execute_with(|| { - let weight = BaseXcmWeight::get() * 3; - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into(); - assert_ok!(XcmPallet::limited_teleport_assets( - RuntimeOrigin::signed(ALICE), - Box::new(RelayLocation::get().into()), - Box::new(dest.into()), - Box::new((Here, SEND_AMOUNT).into()), - 0, - WeightLimit::Unlimited, - )); - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); - assert_eq!( - sent_xcm(), - vec![( - RelayLocation::get().into(), - Xcm(vec![ - ReceiveTeleportedAsset((Here, SEND_AMOUNT).into()), - ClearOrigin, - buy_execution((Here, SEND_AMOUNT)), - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]), - )] - ); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) - ); - }); +fn limited_teleport_assets_works() { + let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into(); + let weight_limit = WeightLimit::Limited(Weight::from_parts(5000, 5000)); + let expected_weight_limit = weight_limit.clone(); + do_test_and_verify_teleport_assets( + dest, + || { + assert_ok!(XcmPallet::limited_teleport_assets( + RuntimeOrigin::signed(ALICE), + Box::new(RelayLocation::get().into()), + Box::new(dest.into()), + Box::new((Here, SEND_AMOUNT).into()), + 0, + weight_limit, + )); + }, + expected_weight_limit, + ); } -/// Test `reserve_transfer_assets` -/// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. -#[test] -fn reserve_transfer_assets_works() { +// Helper function to deduplicate testing different reserve-transfer types. +fn do_test_and_verify_reserve_transfer_assets( + dest: MultiLocation, + call: Call, + expected_weight_limit: WeightLimit, +) { let balances = vec![ (ALICE, INITIAL_BALANCE), (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; new_test_ext_with_balances(balances).execute_with(|| { let weight = BaseXcmWeight::get() * 2; - let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - assert_ok!(XcmPallet::reserve_transfer_assets( - RuntimeOrigin::signed(ALICE), - Box::new(Parachain(PARA_ID).into()), - Box::new(dest.into()), - Box::new((Here, SEND_AMOUNT).into()), - 0, - )); + // call extrinsic + call(); // Alice spent amount assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); // Destination account (parachain account) has amount @@ -508,7 +457,7 @@ fn reserve_transfer_assets_works() { Xcm(vec![ ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), ClearOrigin, - buy_execution((Parent, SEND_AMOUNT)), + buy_limited_execution((Parent, SEND_AMOUNT), expected_weight_limit), DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, ]), )] @@ -522,98 +471,51 @@ fn reserve_transfer_assets_works() { }); } -/// Test `limited_reserve_transfer_assets` +/// Test `reserve_transfer_assets` /// /// Asserts that the sender's balance is decreased and the beneficiary's balance /// is increased. Verifies the correct message is sent and event is emitted. #[test] -fn limited_reserve_transfer_assets_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - new_test_ext_with_balances(balances).execute_with(|| { - let weight = BaseXcmWeight::get() * 2; - let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - assert_ok!(XcmPallet::limited_reserve_transfer_assets( - RuntimeOrigin::signed(ALICE), - Box::new(Parachain(PARA_ID).into()), - Box::new(dest.into()), - Box::new((Here, SEND_AMOUNT).into()), - 0, - WeightLimit::Limited(Weight::from_parts(5000, 5000)), - )); - // Alice spent amount - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); - // Destination account (parachain account) has amount - let para_acc: AccountId = ParaId::from(PARA_ID).into_account_truncating(); - assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT); - assert_eq!( - sent_xcm(), - vec![( - Parachain(PARA_ID).into(), - Xcm(vec![ - ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), - ClearOrigin, - buy_limited_execution((Parent, SEND_AMOUNT), Weight::from_parts(5000, 5000)), - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]), - )] - ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) - ); - }); +fn reserve_transfer_assets_works() { + let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + do_test_and_verify_reserve_transfer_assets( + dest, + || { + assert_ok!(XcmPallet::reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(Parachain(PARA_ID).into()), + Box::new(dest.into()), + Box::new((Here, SEND_AMOUNT).into()), + 0, + )); + }, + Unlimited, + ); } -/// Test `limited_reserve_transfer_assets` with unlimited weight purchasing +/// Test `limited_reserve_transfer_assets` /// /// Asserts that the sender's balance is decreased and the beneficiary's balance /// is increased. Verifies the correct message is sent and event is emitted. #[test] -fn unlimited_reserve_transfer_assets_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - new_test_ext_with_balances(balances).execute_with(|| { - let weight = BaseXcmWeight::get() * 2; - let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - assert_ok!(XcmPallet::limited_reserve_transfer_assets( - RuntimeOrigin::signed(ALICE), - Box::new(Parachain(PARA_ID).into()), - Box::new(dest.into()), - Box::new((Here, SEND_AMOUNT).into()), - 0, - WeightLimit::Unlimited, - )); - // Alice spent amount - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); - // Destination account (parachain account) has amount - let para_acc: AccountId = ParaId::from(PARA_ID).into_account_truncating(); - assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT); - assert_eq!( - sent_xcm(), - vec![( - Parachain(PARA_ID).into(), - Xcm(vec![ - ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), - ClearOrigin, - buy_execution((Parent, SEND_AMOUNT)), - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]), - )] - ); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) - ); - }); +fn limited_reserve_transfer_assets_works() { + let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + let weight_limit = WeightLimit::Limited(Weight::from_parts(5000, 5000)); + let expected_weight_limit = weight_limit.clone(); + do_test_and_verify_reserve_transfer_assets( + dest, + || { + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(Parachain(PARA_ID).into()), + Box::new(dest.into()), + Box::new((Here, SEND_AMOUNT).into()), + 0, + weight_limit, + )); + }, + expected_weight_limit, + ); } /// Test local execution of XCM From 026a779fe21bb53f6c2dcd71de7fc60e642b7e5c Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 26 Sep 2023 15:46:19 +0300 Subject: [PATCH 008/124] add test cases plan --- polkadot/xcm/pallet-xcm/src/lib.rs | 3 +- polkadot/xcm/pallet-xcm/src/tests.rs | 171 +++++++++++++++++++++++---- 2 files changed, 149 insertions(+), 25 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 7ae28d43f495..c23f08198aaf 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1299,7 +1299,7 @@ impl Pallet { let fees_transfer_type = TransferType::determine_for::(&fees, &dest)?; let assets_transfer_type = if assets.is_empty() { // Single asset to transfer (also used for fees). - fees_transfer_type.clone() + fees_transfer_type } else { // Find reserve for non-fee assets. Self::validate_assets_and_find_reserve(&assets, &dest)? @@ -1334,7 +1334,6 @@ impl Pallet { let context = T::UniversalLocation::get(); // Send half the `fees` to the Sovereign Account of `dest` on assets-reserve chain. let assets_reserve_beneficiary = dest - .clone() .reanchored(&assets_reserve, context) .map_err(|_| Error::::CannotReanchor)?; Self::prefund_transfer_fees( diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 522ca00a2886..cce09f2af9a2 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -348,7 +348,7 @@ fn send_fails_when_xcm_router_blocks() { // Helper function to deduplicate testing different teleport types. fn do_test_and_verify_teleport_assets( - dest: MultiLocation, + expected_beneficiary: MultiLocation, call: Call, expected_weight_limit: WeightLimit, ) { @@ -370,7 +370,10 @@ fn do_test_and_verify_teleport_assets( ReceiveTeleportedAsset((Here, SEND_AMOUNT).into()), ClearOrigin, buy_limited_execution((Here, SEND_AMOUNT), expected_weight_limit), - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, + DepositAsset { + assets: AllCounted(1).into(), + beneficiary: expected_beneficiary + }, ]), )] ); @@ -389,14 +392,14 @@ fn do_test_and_verify_teleport_assets( /// local effects. #[test] fn teleport_assets_works() { - let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into(); + let beneficiary: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into(); do_test_and_verify_teleport_assets( - dest, + beneficiary, || { assert_ok!(XcmPallet::teleport_assets( RuntimeOrigin::signed(ALICE), Box::new(RelayLocation::get().into()), - Box::new(dest.into()), + Box::new(beneficiary.into()), Box::new((Here, SEND_AMOUNT).into()), 0, )); @@ -411,16 +414,16 @@ fn teleport_assets_works() { /// local effects. #[test] fn limited_teleport_assets_works() { - let dest: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into(); + let beneficiary: MultiLocation = AccountId32 { network: None, id: BOB.into() }.into(); let weight_limit = WeightLimit::Limited(Weight::from_parts(5000, 5000)); let expected_weight_limit = weight_limit.clone(); do_test_and_verify_teleport_assets( - dest, + beneficiary, || { assert_ok!(XcmPallet::limited_teleport_assets( RuntimeOrigin::signed(ALICE), Box::new(RelayLocation::get().into()), - Box::new(dest.into()), + Box::new(beneficiary.into()), Box::new((Here, SEND_AMOUNT).into()), 0, weight_limit, @@ -430,9 +433,27 @@ fn limited_teleport_assets_works() { ); } +// For reserve-based transfers, we want to support: +// - non-fee assets reserve: +// - local reserve +// - destination reserve +// - remote reserve +// - fee assests: +// - reserve-transferred with reserve: +// - local reserve +// - destination reserve +// - remote reserve +// - teleported +// +// Bringing unique scenarios total to 3*4 = 12. So, following reserve-transfer tests try to cover +// the happy-case for each of these 12 scenarios. +// +// TODO: also add negative tests for testing various error conditions. + // Helper function to deduplicate testing different reserve-transfer types. -fn do_test_and_verify_reserve_transfer_assets( - dest: MultiLocation, +// Currently hardcoded for AssetsReserve=Local and FeeReserve=Local. +fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( + expected_beneficiary: MultiLocation, call: Call, expected_weight_limit: WeightLimit, ) { @@ -458,7 +479,10 @@ fn do_test_and_verify_reserve_transfer_assets( ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), ClearOrigin, buy_limited_execution((Parent, SEND_AMOUNT), expected_weight_limit), - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, + DepositAsset { + assets: AllCounted(1).into(), + beneficiary: expected_beneficiary + }, ]), )] ); @@ -471,20 +495,21 @@ fn do_test_and_verify_reserve_transfer_assets( }); } -/// Test `reserve_transfer_assets` +/// Test `reserve_transfer_assets` with local asset reserve and local fee reserve. /// /// Asserts that the sender's balance is decreased and the beneficiary's balance /// is increased. Verifies the correct message is sent and event is emitted. #[test] -fn reserve_transfer_assets_works() { - let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - do_test_and_verify_reserve_transfer_assets( - dest, +fn reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works() { + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( + beneficiary, || { assert_ok!(XcmPallet::reserve_transfer_assets( RuntimeOrigin::signed(ALICE), Box::new(Parachain(PARA_ID).into()), - Box::new(dest.into()), + Box::new(beneficiary.into()), Box::new((Here, SEND_AMOUNT).into()), 0, )); @@ -493,22 +518,23 @@ fn reserve_transfer_assets_works() { ); } -/// Test `limited_reserve_transfer_assets` +/// Test `limited_reserve_transfer_assets` with local asset reserve and local fee reserve. /// /// Asserts that the sender's balance is decreased and the beneficiary's balance /// is increased. Verifies the correct message is sent and event is emitted. #[test] -fn limited_reserve_transfer_assets_works() { - let dest: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); +fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works() { + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); let weight_limit = WeightLimit::Limited(Weight::from_parts(5000, 5000)); let expected_weight_limit = weight_limit.clone(); - do_test_and_verify_reserve_transfer_assets( - dest, + do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( + beneficiary, || { assert_ok!(XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), Box::new(Parachain(PARA_ID).into()), - Box::new(dest.into()), + Box::new(beneficiary.into()), Box::new((Here, SEND_AMOUNT).into()), 0, weight_limit, @@ -518,6 +544,105 @@ fn limited_reserve_transfer_assets_works() { ); } +/// Test `reserve_transfer_assets` with destination asset reserve and local fee reserve. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with remote asset reserve and local fee reserve. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with local asset reserve and destination fee reserve. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with destination asset reserve and destination fee reserve. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_reserve_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with remote asset reserve and destination fee reserve. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with local asset reserve and remote fee reserve. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with destination asset reserve and local fee reserve. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with remote asset reserve and local fee reserve. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with local asset reserve and teleported fee. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with destination asset reserve and teleported fee. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_works() { + todo!() +} + +/// Test `reserve_transfer_assets` with remote asset reserve and teleported fee. +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the correct message is sent and event is emitted. +#[test] +fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() { + todo!() +} + /// Test local execution of XCM /// /// Asserts that the sender's balance is decreased and the beneficiary's balance From 4465c6535c4837fb3df4e3367bd26dfab663fe09 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 26 Sep 2023 17:05:11 +0300 Subject: [PATCH 009/124] add pallet-assets to mock test runtime --- Cargo.lock | 1 + polkadot/xcm/pallet-xcm/Cargo.toml | 3 +++ polkadot/xcm/pallet-xcm/src/mock.rs | 26 +++++++++++++++++++++++++- polkadot/xcm/pallet-xcm/src/tests.rs | 4 ++-- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3a59c270c47..8a7168b86388 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10662,6 +10662,7 @@ dependencies = [ "frame-support", "frame-system", "log", + "pallet-assets", "pallet-balances", "parity-scale-codec", "polkadot-parachain-primitives", diff --git a/polkadot/xcm/pallet-xcm/Cargo.toml b/polkadot/xcm/pallet-xcm/Cargo.toml index 4946a8d11ce9..2b45c984728a 100644 --- a/polkadot/xcm/pallet-xcm/Cargo.toml +++ b/polkadot/xcm/pallet-xcm/Cargo.toml @@ -25,6 +25,7 @@ xcm = { package = "staging-xcm", path = "..", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../xcm-executor", default-features = false } [dev-dependencies] +pallet-assets = { path = "../../../substrate/frame/assets" } pallet-balances = { path = "../../../substrate/frame/balances" } polkadot-runtime-parachains = { path = "../../runtime/parachains" } polkadot-parachain-primitives = { path = "../../parachain" } @@ -51,6 +52,7 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", "polkadot-runtime-parachains/runtime-benchmarks", @@ -61,6 +63,7 @@ runtime-benchmarks = [ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", + "pallet-assets/try-runtime", "pallet-balances/try-runtime", "polkadot-runtime-parachains/try-runtime", "sp-runtime/try-runtime", diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 9895249148ef..6884e201944e 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -17,7 +17,7 @@ use codec::Encode; use frame_support::{ construct_runtime, parameter_types, - traits::{ConstU32, Everything, Nothing}, + traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, Everything, Nothing}, weights::Weight, }; use frame_system::EnsureRoot; @@ -135,6 +135,7 @@ construct_runtime!( { System: frame_system::{Pallet, Call, Storage, Config, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Assets: pallet_assets::{Pallet, Call, Storage, Config, Event}, ParasOrigin: origin::{Pallet, Origin}, XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config}, TestNotifier: pallet_test_notifier::{Pallet, Call, Event}, @@ -245,6 +246,29 @@ impl pallet_balances::Config for Test { type MaxFreezes = ConstU32<0>; } +impl pallet_assets::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = u64; + type AssetId = u32; + type AssetIdParameter = u32; + type Currency = Balances; + type CreateOrigin = AsEnsureOriginWithArg>; + type ForceOrigin = EnsureRoot; + type AssetDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; + type MetadataDepositBase = ConstU128<1>; + type MetadataDepositPerByte = ConstU128<1>; + type ApprovalDeposit = ConstU128<1>; + type StringLimit = ConstU32<50>; + type Freezer = (); + type WeightInfo = (); + type CallbackHandle = (); + type Extra = (); + type RemoveItemsLimit = ConstU32<5>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + parameter_types! { pub const RelayLocation: MultiLocation = Here.into_location(); pub const AnyNetwork: Option = None; diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index cce09f2af9a2..17374814c19d 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -75,7 +75,7 @@ fn report_outcome_notify_works() { let querier: MultiLocation = Here.into(); let status = QueryStatus::Pending { responder: MultiLocation::from(Parachain(PARA_ID)).into(), - maybe_notify: Some((4, 2)), + maybe_notify: Some((5, 2)), timeout: 100, maybe_match_querier: Some(querier.into()), }; @@ -105,7 +105,7 @@ fn report_outcome_notify_works() { )), RuntimeEvent::XcmPallet(crate::Event::Notified { query_id: 0, - pallet_index: 4, + pallet_index: 5, call_index: 2 }), ] From 2392dd915a662a499865cebe954786e335688ea4 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 26 Sep 2023 17:53:28 +0300 Subject: [PATCH 010/124] fix add assets to mock pallet-xcm runtime --- polkadot/xcm/pallet-xcm/src/mock.rs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 6884e201944e..f1a60c7ed34a 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -31,8 +31,8 @@ use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, - FixedWeightBounds, IsConcrete, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, + FixedWeightBounds, IsConcrete, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, }; use xcm_executor::XcmExecutor; @@ -249,8 +249,8 @@ impl pallet_balances::Config for Test { impl pallet_assets::Config for Test { type RuntimeEvent = RuntimeEvent; type Balance = u64; - type AssetId = u32; - type AssetIdParameter = u32; + type AssetId = MultiLocation; + type AssetIdParameter = MultiLocation; type Currency = Balances; type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; @@ -276,8 +276,11 @@ parameter_types! { pub UnitWeightCost: u64 = 1_000; } -pub type SovereignAccountOf = - (ChildParachainConvertsVia, AccountId32Aliases); +pub type SovereignAccountOf = ( + ChildParachainConvertsVia, + AccountId32Aliases, + SiblingParachainConvertsVia, +); pub type LocalAssetTransactor = XcmCurrencyAdapter, SovereignAccountOf, AccountId, ()>; @@ -289,10 +292,19 @@ type LocalOriginConverter = ( ChildSystemParachainAsSuperuser, ); +// This sibling parachain acts as trusted reserve for its assets in tests. +pub const RESERVE_PARA_ID: u32 = 2001; +// This sibling parachain is not configured as trusted reserve or teleport location for any assets. +pub const OTHER_PARA_ID: u32 = 2009; + parameter_types! { pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000); pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1); pub TrustedAssets: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into()); + pub TrustedReserves: (MultiAssetFilter, MultiLocation) = ( + All.into(), + MultiLocation { parents: 1, interior: X1(Parachain(RESERVE_PARA_ID)) } + ); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; } @@ -310,7 +322,7 @@ impl xcm_executor::Config for XcmConfig { type XcmSender = TestSendXcm; type AssetTransactor = LocalAssetTransactor; type OriginConverter = LocalOriginConverter; - type IsReserve = (); + type IsReserve = Case; type IsTeleporter = Case; type UniversalLocation = UniversalLocation; type Barrier = Barrier; From 67daafe2f903f4f14340a9046b3f74fd677ff88d Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 27 Sep 2023 13:30:57 +0300 Subject: [PATCH 011/124] add test for asset-reserve and fee-reserve both at destination --- polkadot/xcm/pallet-xcm/src/mock.rs | 66 ++++++++++++---- polkadot/xcm/pallet-xcm/src/tests.rs | 111 ++++++++++++++++++++++++--- 2 files changed, 150 insertions(+), 27 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index f1a60c7ed34a..d951520f926d 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -17,7 +17,9 @@ use codec::Encode; use frame_support::{ construct_runtime, parameter_types, - traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, Everything, Nothing}, + traits::{ + AsEnsureOriginWithArg, ConstU128, ConstU32, Contains, Everything, EverythingBut, Nothing, + }, weights::Weight, }; use frame_system::EnsureRoot; @@ -31,12 +33,16 @@ use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, - FixedWeightBounds, IsConcrete, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + FixedWeightBounds, FungiblesAdapter, IsConcrete, MatchedConvertedConcreteId, NoChecking, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, +}; +use xcm_executor::{ + traits::{Identity, JustTry}, + XcmExecutor, }; -use xcm_executor::XcmExecutor; -use crate::{self as pallet_xcm, TestWeightInfo}; +use crate::{self as pallet_xcm, Get, TestWeightInfo}; pub type AccountId = AccountId32; pub type Balance = u128; @@ -248,7 +254,7 @@ impl pallet_balances::Config for Test { impl pallet_assets::Config for Test { type RuntimeEvent = RuntimeEvent; - type Balance = u64; + type Balance = Balance; type AssetId = MultiLocation; type AssetIdParameter = MultiLocation; type Currency = Balances; @@ -269,11 +275,21 @@ impl pallet_assets::Config for Test { type BenchmarkHelper = (); } +// This child parachain acts as trusted reserve for its assets in tests. +pub const RESERVE_PARA_ID: u32 = 2001; +// This child parachain is not configured as trusted reserve or teleport location for any assets. +pub const OTHER_PARA_ID: u32 = 2009; + parameter_types! { pub const RelayLocation: MultiLocation = Here.into_location(); + pub const ForeignReserveLocation: MultiLocation = MultiLocation { + parents: 0, + interior: X1(Parachain(RESERVE_PARA_ID)) + }; pub const AnyNetwork: Option = None; pub UniversalLocation: InteriorMultiLocation = Here; pub UnitWeightCost: u64 = 1_000; + pub CheckingAccount: AccountId = XcmPallet::check_account(); } pub type SovereignAccountOf = ( @@ -282,8 +298,33 @@ pub type SovereignAccountOf = ( SiblingParachainConvertsVia, ); -pub type LocalAssetTransactor = - XcmCurrencyAdapter, SovereignAccountOf, AccountId, ()>; +pub struct Equals(PhantomData); +impl> Contains for Equals { + fn contains(t: &MultiLocation) -> bool { + t == &Location::get() + } +} + +pub type ForeignAssetsConvertedConcreteId = MatchedConvertedConcreteId< + MultiLocation, + Balance, + // Excludes relay/parent chain currency + EverythingBut<(Equals,)>, + Identity, + JustTry, +>; + +pub type AssetTransactors = ( + XcmCurrencyAdapter, SovereignAccountOf, AccountId, ()>, + FungiblesAdapter< + Assets, + ForeignAssetsConvertedConcreteId, + SovereignAccountOf, + AccountId, + NoChecking, + CheckingAccount, + >, +); type LocalOriginConverter = ( SovereignSignedViaLocation, @@ -292,18 +333,13 @@ type LocalOriginConverter = ( ChildSystemParachainAsSuperuser, ); -// This sibling parachain acts as trusted reserve for its assets in tests. -pub const RESERVE_PARA_ID: u32 = 2001; -// This sibling parachain is not configured as trusted reserve or teleport location for any assets. -pub const OTHER_PARA_ID: u32 = 2009; - parameter_types! { pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000); pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1); pub TrustedAssets: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into()); pub TrustedReserves: (MultiAssetFilter, MultiLocation) = ( All.into(), - MultiLocation { parents: 1, interior: X1(Parachain(RESERVE_PARA_ID)) } + MultiLocation { parents: 0, interior: X1(Parachain(RESERVE_PARA_ID)) } ); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; @@ -320,7 +356,7 @@ pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; type XcmSender = TestSendXcm; - type AssetTransactor = LocalAssetTransactor; + type AssetTransactor = AssetTransactors; type OriginConverter = LocalOriginConverter; type IsReserve = Case; type IsTeleporter = Case; diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 17374814c19d..9d5a057995fd 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -29,7 +29,7 @@ use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash}; use xcm::{latest::QueryResponseInfo, prelude::*}; use xcm_builder::AllowKnownQueryResponses; use xcm_executor::{ - traits::{Properties, QueryHandler, QueryResponseStatus, ShouldExecute}, + traits::{ConvertLocation, Properties, QueryHandler, QueryResponseStatus, ShouldExecute}, XcmExecutor, }; @@ -550,7 +550,7 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_works() { - todo!() + // TODO } /// Test `reserve_transfer_assets` with remote asset reserve and local fee reserve. @@ -559,7 +559,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works() { - todo!() + // TODO } /// Test `reserve_transfer_assets` with local asset reserve and destination fee reserve. @@ -568,7 +568,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_works() { - todo!() + // TODO } /// Test `reserve_transfer_assets` with destination asset reserve and destination fee reserve. @@ -577,7 +577,94 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_reserve_works() { - todo!() + // foreign creator in this case sibling parachain acting as reserve + let foreign_creator_location = + RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); + let foreign_creator_as_account_id = + SovereignAccountOf::convert_location(&foreign_creator_location).unwrap(); + + // foreign parachain with the same consensus currency as asset + let foreign_asset_id_multilocation = + foreign_creator_location.pushed_with_interior(GeneralIndex(1234567)).unwrap(); + let foreign_asset_amount = 142; + + // transfer destination is reserve location + let dest = foreign_creator_location; + let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); + + let balances = + vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient (to be used as fees as well) foreign asset (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + true, + 1 + )); + // this asset should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_amount + )); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + let expected_weight = BaseXcmWeight::get() * 2; + let mut expected_assets = assets.clone(); + expected_assets.reanchor(&dest, UniversalLocation::get()).unwrap(); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + 0, + Unlimited, + )); + assert_eq!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { + outcome: Outcome::Complete(expected_weight) + }) + ); + // Alice spent (transferred) amount + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_amount - SEND_AMOUNT + ); + // Alice's native asset balance is untouched + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + // Destination account (parachain account) has expected (same) balances + assert_eq!(Balances::free_balance(foreign_creator_as_account_id.clone()), INITIAL_BALANCE); + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), + 0 + ); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![( + Parachain(RESERVE_PARA_ID).into(), + Xcm(vec![ + WithdrawAsset(expected_assets.clone()), + ClearOrigin, + buy_limited_execution(expected_assets.get(0).unwrap().clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]), + )] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with remote asset reserve and destination fee reserve. @@ -586,7 +673,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve_works() { - todo!() + // TODO } /// Test `reserve_transfer_assets` with local asset reserve and remote fee reserve. @@ -595,7 +682,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works() { - todo!() + // TODO } /// Test `reserve_transfer_assets` with destination asset reserve and local fee reserve. @@ -604,7 +691,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve_works() { - todo!() + // TODO } /// Test `reserve_transfer_assets` with remote asset reserve and local fee reserve. @@ -613,7 +700,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_works() { - todo!() + // TODO } /// Test `reserve_transfer_assets` with local asset reserve and teleported fee. @@ -622,7 +709,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { - todo!() + // TODO } /// Test `reserve_transfer_assets` with destination asset reserve and teleported fee. @@ -631,7 +718,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_works() { - todo!() + // TODO } /// Test `reserve_transfer_assets` with remote asset reserve and teleported fee. @@ -640,7 +727,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() { - todo!() + // TODO } /// Test local execution of XCM From 88b302494db97140504d6f8f25a84b2510d1d8d6 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 27 Sep 2023 14:57:41 +0300 Subject: [PATCH 012/124] add test for asset-reserve and fee-reserve both at remote chain --- polkadot/xcm/pallet-xcm/src/tests.rs | 126 ++++++++++++++++++++++++--- 1 file changed, 114 insertions(+), 12 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 9d5a057995fd..d993699f8d18 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -577,19 +577,19 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_reserve_works() { - // foreign creator in this case sibling parachain acting as reserve - let foreign_creator_location = + // foreign creator in this case child parachain acting as reserve + let reserve_location = RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); let foreign_creator_as_account_id = - SovereignAccountOf::convert_location(&foreign_creator_location).unwrap(); + SovereignAccountOf::convert_location(&reserve_location).unwrap(); // foreign parachain with the same consensus currency as asset let foreign_asset_id_multilocation = - foreign_creator_location.pushed_with_interior(GeneralIndex(1234567)).unwrap(); + reserve_location.pushed_with_interior(GeneralIndex(1234567)).unwrap(); let foreign_asset_amount = 142; // transfer destination is reserve location - let dest = foreign_creator_location; + let dest = reserve_location; let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); let balances = @@ -616,7 +616,6 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - let expected_weight = BaseXcmWeight::get() * 2; let mut expected_assets = assets.clone(); expected_assets.reanchor(&dest, UniversalLocation::get()).unwrap(); @@ -629,12 +628,10 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re 0, Unlimited, )); - assert_eq!( + assert!(matches!( last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { - outcome: Outcome::Complete(expected_weight) - }) - ); + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); // Alice spent (transferred) amount assert_eq!( Assets::balance(foreign_asset_id_multilocation, ALICE), @@ -700,7 +697,112 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_works() { - // TODO + // foreign creator in this case child parachain acting as reserve + let reserve_location = + RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); + let foreign_creator_as_account_id = + SovereignAccountOf::convert_location(&reserve_location).unwrap(); + + // foreign parachain with the same consensus currency as asset + let foreign_asset_id_multilocation = + reserve_location.pushed_with_interior(GeneralIndex(1234567)).unwrap(); + let foreign_asset_amount = 142; + + let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); + // transfer destination is other parachain => remote reserve location (RESERVE_PARA_ID) + let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); + + let balances = + vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient (to be used as fees as well) foreign asset (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + true, + 1 + )); + // this asset should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_amount + )); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + let context = UniversalLocation::get(); + println!("assets to transfer: {:?}", assets); + let mut expected_fee_on_reserve = assets.get(0).unwrap().clone(); + expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); + println!("expected fees on reserve (reanchored): {:?}", expected_fee_on_reserve); + let mut expected_assets = assets.clone(); + expected_assets.reanchor(&dest, context).unwrap(); + println!("assets expected to be received on dest (reanchored): {:?}", expected_assets); + let expected_dest = dest.reanchored(&reserve_location, context).unwrap(); + println!("dest location as seen by reserve (reanchored): {:?}", expected_dest); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + 0, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice spent (transferred) amount + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_amount - SEND_AMOUNT + ); + // Alice's native asset balance is untouched + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + // Destination account (parachain account) has expected (same) balances + assert_eq!(Balances::free_balance(foreign_creator_as_account_id.clone()), INITIAL_BALANCE); + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), + 0 + ); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![( + // first message sent to reserve chain + Parachain(RESERVE_PARA_ID).into(), + Xcm(vec![ + WithdrawAsset(expected_fee_on_reserve.clone().into()), + ClearOrigin, + BuyExecution { fees: expected_fee_on_reserve, weight_limit: Unlimited }, + DepositReserveAsset { + assets: Wild(AllCounted(1)), + // final destination is `dest` as seen by `reserve` + dest: expected_dest, + // message sent onward to `dest` + xcm: Xcm(vec![ + buy_limited_execution( + expected_assets.get(0).unwrap().clone(), + Unlimited + ), + DepositAsset { assets: AllCounted(1).into(), beneficiary } + ]) + } + ]) + )], + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with local asset reserve and teleported fee. From 513e15aa3856f82361d096de61902f6040f14421 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 27 Sep 2023 16:21:24 +0300 Subject: [PATCH 013/124] add test for asset-reserve at destination while fee-reserve is local --- polkadot/xcm/pallet-xcm/src/lib.rs | 13 ++- polkadot/xcm/pallet-xcm/src/mock.rs | 17 +++- polkadot/xcm/pallet-xcm/src/tests.rs | 120 ++++++++++++++++++++++++++- 3 files changed, 140 insertions(+), 10 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index c23f08198aaf..7e1051134281 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1354,19 +1354,24 @@ impl Pallet { if let TransferType::RemoteReserve(_fees_reserve) = fees_transfer_type { // TODO: change beneficiary on `fee_reserve` to be SA-of-Here. // But beneficiary on `dest` should stay unchanged... + // Or maybe not required, fees can be used from Holding register, we'll see :D } - Self::prefund_transfer_fees( + // execute fees transfer - have to do it separately than assets because of the + // different transfer type (different XCM program required) + Self::build_and_execute_xcm_transfer_type( origin_location, dest, beneficiary, + vec![fees.clone()], + fees_transfer_type, fees.clone(), weight_limit.clone(), )?; } } - // Fees have been prefunded/transferred (or batched together with assets), now do - // reserve-transfer assets. + // Fees have been prefunded/transferred (or batched together with assets to be transferred + // here), now do reserve-transfer assets. Self::build_and_execute_xcm_transfer_type( origin_location, dest, @@ -1389,6 +1394,8 @@ impl Pallet { _asset: MultiAsset, _weight_limit: WeightLimit, ) -> DispatchResult { + // let fee_transfer_type = TransferType::determine_for::(&fee_asset, &dest)?; + // Ok(()) todo!() } diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index d951520f926d..a27a6cd51891 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -277,6 +277,8 @@ impl pallet_assets::Config for Test { // This child parachain acts as trusted reserve for its assets in tests. pub const RESERVE_PARA_ID: u32 = 2001; +// Inner junction of reserve asset on `RESERVE_PARA_ID`. +pub const RESERVE_ASSET_INNER_JUNCTION: Junction = GeneralIndex(1234567); // This child parachain is not configured as trusted reserve or teleport location for any assets. pub const OTHER_PARA_ID: u32 = 2009; @@ -333,14 +335,21 @@ type LocalOriginConverter = ( ChildSystemParachainAsSuperuser, ); +pub const RESERVE_LOCATION: MultiLocation = + MultiLocation { parents: 0, interior: X1(Parachain(RESERVE_PARA_ID)) }; +pub const RESERVE_ASSET: MultiAsset = MultiAsset { + fun: Fungible(10), + id: Concrete(MultiLocation { + parents: 0, + interior: X2(Parachain(RESERVE_PARA_ID), RESERVE_ASSET_INNER_JUNCTION), + }), +}; + parameter_types! { pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000); pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1); pub TrustedAssets: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into()); - pub TrustedReserves: (MultiAssetFilter, MultiLocation) = ( - All.into(), - MultiLocation { parents: 0, interior: X1(Parachain(RESERVE_PARA_ID)) } - ); + pub TrustedReserves: (MultiAssetFilter, MultiLocation) = (vec![RESERVE_ASSET].into(), RESERVE_LOCATION); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; } diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index d993699f8d18..d0b368e1d124 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -38,6 +38,7 @@ const BOB: AccountId = AccountId::new([1u8; 32]); const PARA_ID: u32 = 2000; const INITIAL_BALANCE: u128 = 100; const SEND_AMOUNT: u128 = 10; +const FEE_AMOUNT: u128 = 1; #[test] fn report_outcome_notify_works() { @@ -550,7 +551,120 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_works() { - // TODO + // foreign creator in this case child parachain acting as reserve + let reserve_location = + RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); + let foreign_creator_as_account_id = + SovereignAccountOf::convert_location(&reserve_location).unwrap(); + + // foreign parachain with the same consensus currency as asset + let foreign_asset_id_multilocation = + reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); + let foreign_asset_amount = 142; + + // transfer destination is reserve location (no teleport trust) + let dest = reserve_location; + let assets: MultiAssets = vec![ + // native asset for fee + (MultiLocation::here(), FEE_AMOUNT).into(), + // foreign asset to transfer + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ] + .into(); + + let balances = + vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + + new_test_ext_with_balances(balances).execute_with(|| { + // create non-sufficient foreign asset (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + false, + 1 + )); + // this asset should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_amount + )); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(0).unwrap().clone(); + expected_fee.reanchor(&dest, context).unwrap(); + let mut expected_asset = assets.get(1).unwrap().clone(); + expected_asset.reanchor(&dest, context).unwrap(); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + 0, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice spent (transferred) amount + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_amount - SEND_AMOUNT + ); + // Alice used native asset for fees + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - FEE_AMOUNT); + // Destination account (parachain account) added native reserve used as fee to balances + assert_eq!( + Balances::free_balance(foreign_creator_as_account_id.clone()), + INITIAL_BALANCE + FEE_AMOUNT + ); + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), + 0 + ); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![ + ( + // first message is to prefund fees on `dest` + dest, + Xcm(vec![ + // fees are being sent through local-reserve transfer because fee reserve + // is local chain + ReserveAssetDeposited((Parent, FEE_AMOUNT).into()), + ClearOrigin, + buy_limited_execution((Parent, FEE_AMOUNT), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ), + ( + // second message is to transfer/deposit foreign assets on `dest` while paying + // using prefunded (transferred above) fees + dest, + Xcm(vec![ + WithdrawAsset(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ) + ] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with remote asset reserve and local fee reserve. @@ -585,7 +699,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re // foreign parachain with the same consensus currency as asset let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(GeneralIndex(1234567)).unwrap(); + reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); let foreign_asset_amount = 142; // transfer destination is reserve location @@ -705,7 +819,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work // foreign parachain with the same consensus currency as asset let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(GeneralIndex(1234567)).unwrap(); + reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); let foreign_asset_amount = 142; let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); From 19eec1780115025214f7fb363b1ed4a09ad0a223 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 27 Sep 2023 17:37:40 +0300 Subject: [PATCH 014/124] add test for asset local-reserve while fee-reserve is destination --- polkadot/xcm/pallet-xcm/src/tests.rs | 136 +++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 7 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index d0b368e1d124..530a77636dad 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -571,6 +571,8 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ (foreign_asset_id_multilocation, SEND_AMOUNT).into(), ] .into(); + let fee_index = 0; + let asset_index = 1; let balances = vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; @@ -598,9 +600,9 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); let context = UniversalLocation::get(); - let mut expected_fee = assets.get(0).unwrap().clone(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); expected_fee.reanchor(&dest, context).unwrap(); - let mut expected_asset = assets.get(1).unwrap().clone(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); expected_asset.reanchor(&dest, context).unwrap(); // do the transfer @@ -609,7 +611,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ Box::new(dest.into()), Box::new(beneficiary.into()), Box::new(assets.into()), - 0, + fee_index as u32, Unlimited, )); assert!(matches!( @@ -652,6 +654,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ ( // second message is to transfer/deposit foreign assets on `dest` while paying // using prefunded (transferred above) fees + // (dest is reserve location for `expected_asset`) dest, Xcm(vec![ WithdrawAsset(expected_asset.into()), @@ -682,7 +685,124 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_works() { - // TODO + // foreign creator in this case child parachain acting as reserve + let fee_reserve_location = + RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); + let foreign_creator_as_account_id = + SovereignAccountOf::convert_location(&fee_reserve_location).unwrap(); + + // foreign parachain with the same consensus currency as asset + let foreign_asset_id_multilocation = + fee_reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); + let foreign_asset_amount = 142; + + // transfer destination is fee reserve location (no teleport trust) + let dest = fee_reserve_location; + let assets: MultiAssets = vec![ + // native asset to transfer (not used for fees) + (MultiLocation::here(), SEND_AMOUNT).into(), + // foreign asset for fees (is sufficient on local chain too) + (foreign_asset_id_multilocation, FEE_AMOUNT).into(), + ] + .into(); + let fee_index = 1; + let asset_index = 0; + + let balances = + vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + + new_test_ext_with_balances(balances).execute_with(|| { + // create non-sufficient foreign asset (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + false, + 1 + )); + // this asset should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_amount + )); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + expected_fee.reanchor(&dest, context).unwrap(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + expected_asset.reanchor(&dest, context).unwrap(); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice spent (fees) amount + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_amount - FEE_AMOUNT + ); + // Alice used native asset for transfer + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); + // Sovereign account of dest parachain holds `SEND_AMOUNT` native asset in local reserve + assert_eq!( + Balances::free_balance(foreign_creator_as_account_id.clone()), + INITIAL_BALANCE + SEND_AMOUNT + ); + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), + 0 + ); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![ + ( + // first message is to prefund fees on `dest` + dest, + // fees are being sent through destination-reserve transfer because fee reserve + // is destination chain + Xcm(vec![ + WithdrawAsset(expected_fee.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee.clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ), + ( + // second message is to transfer/deposit foreign assets on `dest` while paying + // using prefunded (transferred above) fees + // transfer is through local-reserve transfer because `assets` (native asset) + // have local reserve + dest, + Xcm(vec![ + ReserveAssetDeposited(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ) + ] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with destination asset reserve and destination fee reserve. @@ -705,6 +825,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re // transfer destination is reserve location let dest = reserve_location; let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); + let fee_index = 0; let balances = vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; @@ -739,7 +860,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re Box::new(dest.into()), Box::new(beneficiary.into()), Box::new(assets.into()), - 0, + fee_index, Unlimited, )); assert!(matches!( @@ -823,6 +944,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work let foreign_asset_amount = 142; let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); + let fee_index = 0; // transfer destination is other parachain => remote reserve location (RESERVE_PARA_ID) let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); @@ -852,7 +974,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work let context = UniversalLocation::get(); println!("assets to transfer: {:?}", assets); - let mut expected_fee_on_reserve = assets.get(0).unwrap().clone(); + let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); println!("expected fees on reserve (reanchored): {:?}", expected_fee_on_reserve); let mut expected_assets = assets.clone(); @@ -867,7 +989,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work Box::new(dest.into()), Box::new(beneficiary.into()), Box::new(assets.into()), - 0, + fee_index as u32, Unlimited, )); assert!(matches!( From 1687c533d32272787630f99b3737ec516553be55 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 27 Sep 2023 18:56:03 +0300 Subject: [PATCH 015/124] add test for asset local-reserve while fee-reserve is remote chain --- polkadot/xcm/pallet-xcm/src/tests.rs | 146 +++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 11 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 530a77636dad..a7d4ea9e7b26 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -714,12 +714,12 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ Junction::AccountId32 { network: None, id: ALICE.into() }.into(); new_test_ext_with_balances(balances).execute_with(|| { - // create non-sufficient foreign asset (0 total issuance) + // create sufficient foreign asset (0 total issuance) assert_ok!(Assets::force_create( RuntimeOrigin::root(), foreign_asset_id_multilocation, BOB, - false, + true, 1 )); // this asset should have been teleported/reserve-transferred in, but for this test we just @@ -786,11 +786,11 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ ]) ), ( - // second message is to transfer/deposit foreign assets on `dest` while paying + // second message is to transfer/deposit (native) asset on `dest` while paying // using prefunded (transferred above) fees + dest, // transfer is through local-reserve transfer because `assets` (native asset) // have local reserve - dest, Xcm(vec![ ReserveAssetDeposited(expected_asset.into()), ClearOrigin, @@ -914,7 +914,135 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works() { - // TODO + // foreign creator in this case child parachain acting as reserve + let fee_reserve_location = + RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); + let foreign_creator_as_account_id = + SovereignAccountOf::convert_location(&fee_reserve_location).unwrap(); + + // foreign parachain with the same consensus currency as asset + let foreign_asset_id_multilocation = + fee_reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); + let foreign_asset_amount = 142; + + // transfer destination is other parachain than fee reserve location (no teleport trust) + let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); + let dest_as_account_id = SovereignAccountOf::convert_location(&dest).unwrap(); + let assets: MultiAssets = vec![ + // native asset to transfer (not used for fees) - local reserve + (MultiLocation::here(), SEND_AMOUNT).into(), + // foreign asset for fees (is sufficient on local chain too) - remote reserve + (foreign_asset_id_multilocation, FEE_AMOUNT).into(), + ] + .into(); + let fee_index = 1; + let asset_index = 0; + + let balances = + vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient foreign asset (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + true, + 1 + )); + // this asset should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_amount + )); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + let context = UniversalLocation::get(); + let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); + expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); + let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + expected_asset.reanchor(&dest, context).unwrap(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + expected_fee.reanchor(&dest, context).unwrap(); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice spent (fees) amount + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_amount - FEE_AMOUNT + ); + // Alice used native asset for transfer + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); + // Sovereign account of reserve parachain is unchanged + assert_eq!(Balances::free_balance(foreign_creator_as_account_id.clone()), INITIAL_BALANCE); + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), + 0 + ); + // Sovereign account of destination parachain holds `SEND_AMOUNT` in local reserve + assert_eq!(Balances::free_balance(dest_as_account_id), SEND_AMOUNT); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![ + ( + // first message is to prefund (foreign-asset) fees on `dest` (by going through + // fee remote reserve) + fee_reserve_location, + Xcm(vec![ + WithdrawAsset(expected_fee_on_reserve.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee_on_reserve, Unlimited), + DepositReserveAsset { + assets: Wild(AllCounted(1)), + // final destination is `dest` as seen by `reserve` + dest: expected_dest_on_reserve, + // message sent onward to final `dest` to deposit/prefund fees + xcm: Xcm(vec![ + buy_limited_execution(expected_fee.clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary } + ]) + } + ]) + ), + ( + // second message is to transfer/deposit (native) asset on `dest` while paying + // using prefunded (transferred above) fees + dest, + // transfer is through local-reserve transfer because `assets` (native asset) + // have local reserve + Xcm(vec![ + ReserveAssetDeposited(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ) + ] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with destination asset reserve and local fee reserve. @@ -973,15 +1101,11 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); let context = UniversalLocation::get(); - println!("assets to transfer: {:?}", assets); let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); - println!("expected fees on reserve (reanchored): {:?}", expected_fee_on_reserve); let mut expected_assets = assets.clone(); expected_assets.reanchor(&dest, context).unwrap(); - println!("assets expected to be received on dest (reanchored): {:?}", expected_assets); - let expected_dest = dest.reanchored(&reserve_location, context).unwrap(); - println!("dest location as seen by reserve (reanchored): {:?}", expected_dest); + let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); // do the transfer assert_ok!(XcmPallet::limited_reserve_transfer_assets( @@ -1023,7 +1147,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work DepositReserveAsset { assets: Wild(AllCounted(1)), // final destination is `dest` as seen by `reserve` - dest: expected_dest, + dest: expected_dest_on_reserve, // message sent onward to `dest` xcm: Xcm(vec![ buy_limited_execution( From abf029da8163c32eb7b5be71f160b2a488add339 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 27 Sep 2023 19:42:34 +0300 Subject: [PATCH 016/124] refactor tests using better naming and conceptual examples --- polkadot/xcm/pallet-xcm/src/mock.rs | 47 ++-- polkadot/xcm/pallet-xcm/src/tests.rs | 309 ++++++++++++++++----------- 2 files changed, 215 insertions(+), 141 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index a27a6cd51891..982df882b873 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -276,9 +276,15 @@ impl pallet_assets::Config for Test { } // This child parachain acts as trusted reserve for its assets in tests. -pub const RESERVE_PARA_ID: u32 = 2001; -// Inner junction of reserve asset on `RESERVE_PARA_ID`. -pub const RESERVE_ASSET_INNER_JUNCTION: Junction = GeneralIndex(1234567); +pub const FOREIGN_ASSET_RESERVE_PARA_ID: u32 = 2001; +// Inner junction of reserve asset on `FOREIGN_ASSET_RESERVE_PARA_ID`. +pub const FOREIGN_ASSET_INNER_JUNCTION: Junction = GeneralIndex(1234567); + +// This child parachain acts as trusted reserve for say.. USDC that can be used for fees. +pub const USDC_RESERVE_PARA_ID: u32 = 2002; +// Inner junction of reserve asset on `USDC_RESERVE_PARA_ID`. +pub const USDC_INNER_JUNCTION: Junction = PalletInstance(42); + // This child parachain is not configured as trusted reserve or teleport location for any assets. pub const OTHER_PARA_ID: u32 = 2009; @@ -286,7 +292,25 @@ parameter_types! { pub const RelayLocation: MultiLocation = Here.into_location(); pub const ForeignReserveLocation: MultiLocation = MultiLocation { parents: 0, - interior: X1(Parachain(RESERVE_PARA_ID)) + interior: X1(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) + }; + pub const ForeignAsset: MultiAsset = MultiAsset { + fun: Fungible(10), + id: Concrete(MultiLocation { + parents: 0, + interior: X2(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID), FOREIGN_ASSET_INNER_JUNCTION), + }), + }; + pub const UsdcReserveLocation: MultiLocation = MultiLocation { + parents: 0, + interior: X1(Parachain(USDC_RESERVE_PARA_ID)) + }; + pub const Usdc: MultiAsset = MultiAsset { + fun: Fungible(10), + id: Concrete(MultiLocation { + parents: 0, + interior: X2(Parachain(USDC_RESERVE_PARA_ID), USDC_INNER_JUNCTION), + }), }; pub const AnyNetwork: Option = None; pub UniversalLocation: InteriorMultiLocation = Here; @@ -335,21 +359,12 @@ type LocalOriginConverter = ( ChildSystemParachainAsSuperuser, ); -pub const RESERVE_LOCATION: MultiLocation = - MultiLocation { parents: 0, interior: X1(Parachain(RESERVE_PARA_ID)) }; -pub const RESERVE_ASSET: MultiAsset = MultiAsset { - fun: Fungible(10), - id: Concrete(MultiLocation { - parents: 0, - interior: X2(Parachain(RESERVE_PARA_ID), RESERVE_ASSET_INNER_JUNCTION), - }), -}; - parameter_types! { pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000); pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1); pub TrustedAssets: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into()); - pub TrustedReserves: (MultiAssetFilter, MultiLocation) = (vec![RESERVE_ASSET].into(), RESERVE_LOCATION); + pub TrustedReserve1: (MultiAssetFilter, MultiLocation) = (vec![ForeignAsset::get()].into(), ForeignReserveLocation::get()); + pub TrustedReserve2: (MultiAssetFilter, MultiLocation) = (vec![Usdc::get()].into(), UsdcReserveLocation::get()); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; } @@ -367,7 +382,7 @@ impl xcm_executor::Config for XcmConfig { type XcmSender = TestSendXcm; type AssetTransactor = AssetTransactors; type OriginConverter = LocalOriginConverter; - type IsReserve = Case; + type IsReserve = (Case, Case); type IsTeleporter = Case; type UniversalLocation = UniversalLocation; type Barrier = Barrier; diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index a7d4ea9e7b26..4ac8733b4284 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -35,7 +35,6 @@ use xcm_executor::{ const ALICE: AccountId = AccountId::new([0u8; 32]); const BOB: AccountId = AccountId::new([1u8; 32]); -const PARA_ID: u32 = 2000; const INITIAL_BALANCE: u128 = 100; const SEND_AMOUNT: u128 = 10; const FEE_AMOUNT: u128 = 1; @@ -44,7 +43,7 @@ const FEE_AMOUNT: u128 = 1; fn report_outcome_notify_works() { let balances = vec![ (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into(); let mut message = @@ -57,7 +56,7 @@ fn report_outcome_notify_works() { new_test_ext_with_balances(balances).execute_with(|| { XcmPallet::report_outcome_notify( &mut message, - Parachain(PARA_ID).into_location(), + Parachain(OTHER_PARA_ID).into_location(), notify, 100, ) @@ -75,7 +74,7 @@ fn report_outcome_notify_works() { ); let querier: MultiLocation = Here.into(); let status = QueryStatus::Pending { - responder: MultiLocation::from(Parachain(PARA_ID)).into(), + responder: MultiLocation::from(Parachain(OTHER_PARA_ID)).into(), maybe_notify: Some((5, 2)), timeout: 100, maybe_match_querier: Some(querier.into()), @@ -90,7 +89,7 @@ fn report_outcome_notify_works() { }]); let hash = fake_message_hash(&message); let r = XcmExecutor::::execute_xcm( - Parachain(PARA_ID), + Parachain(OTHER_PARA_ID), message, hash, Weight::from_parts(1_000_000_000, 1_000_000_000), @@ -100,7 +99,7 @@ fn report_outcome_notify_works() { last_events(2), vec![ RuntimeEvent::TestNotifier(pallet_test_notifier::Event::ResponseReceived( - Parachain(PARA_ID).into(), + Parachain(OTHER_PARA_ID).into(), 0, Response::ExecutionResult(None), )), @@ -119,13 +118,14 @@ fn report_outcome_notify_works() { fn report_outcome_works() { let balances = vec![ (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into(); let mut message = Xcm(vec![TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }]); new_test_ext_with_balances(balances).execute_with(|| { - XcmPallet::report_outcome(&mut message, Parachain(PARA_ID).into_location(), 100).unwrap(); + XcmPallet::report_outcome(&mut message, Parachain(OTHER_PARA_ID).into_location(), 100) + .unwrap(); assert_eq!( message, Xcm(vec![ @@ -139,7 +139,7 @@ fn report_outcome_works() { ); let querier: MultiLocation = Here.into(); let status = QueryStatus::Pending { - responder: MultiLocation::from(Parachain(PARA_ID)).into(), + responder: MultiLocation::from(Parachain(OTHER_PARA_ID)).into(), maybe_notify: None, timeout: 100, maybe_match_querier: Some(querier.into()), @@ -154,7 +154,7 @@ fn report_outcome_works() { }]); let hash = fake_message_hash(&message); let r = XcmExecutor::::execute_xcm( - Parachain(PARA_ID), + Parachain(OTHER_PARA_ID), message, hash, Weight::from_parts(1_000_000_000, 1_000_000_000), @@ -178,7 +178,7 @@ fn report_outcome_works() { fn custom_querier_works() { let balances = vec![ (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; new_test_ext_with_balances(balances).execute_with(|| { let querier: MultiLocation = @@ -282,7 +282,7 @@ fn custom_querier_works() { fn send_works() { let balances = vec![ (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; new_test_ext_with_balances(balances).execute_with(|| { let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into(); @@ -326,7 +326,7 @@ fn send_works() { fn send_fails_when_xcm_router_blocks() { let balances = vec![ (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; new_test_ext_with_balances(balances).execute_with(|| { let sender: MultiLocation = @@ -355,7 +355,7 @@ fn do_test_and_verify_teleport_assets( ) { let balances = vec![ (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; new_test_ext_with_balances(balances).execute_with(|| { let weight = BaseXcmWeight::get() * 3; @@ -460,7 +460,7 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( ) { let balances = vec![ (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; new_test_ext_with_balances(balances).execute_with(|| { let weight = BaseXcmWeight::get() * 2; @@ -470,12 +470,12 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( // Alice spent amount assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); // Destination account (parachain account) has amount - let para_acc: AccountId = ParaId::from(PARA_ID).into_account_truncating(); + let para_acc: AccountId = ParaId::from(OTHER_PARA_ID).into_account_truncating(); assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT); assert_eq!( sent_xcm(), vec![( - Parachain(PARA_ID).into(), + Parachain(OTHER_PARA_ID).into(), Xcm(vec![ ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), ClearOrigin, @@ -498,7 +498,18 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( /// Test `reserve_transfer_assets` with local asset reserve and local fee reserve. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// Transferring native asset (local reserve) to some `OTHER_PARA_ID` (no teleport trust). +/// Using native asset for fees as well. +/// +/// Here (source) OTHER_PARA_ID (destination) +/// | `assets` reserve +/// | `fees` reserve +/// | +/// | 1. execute `TransferReserveAsset(assets_and_fees_batched_together)` +/// | \--> sends `ReserveAssetDeposited(both), ClearOrigin, BuyExecution(fees), DepositAsset` +/// \------------------------------------------> +/// +/// Asserts that the sender's balance is decreased and the destination SA balance /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works() { @@ -509,7 +520,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works( || { assert_ok!(XcmPallet::reserve_transfer_assets( RuntimeOrigin::signed(ALICE), - Box::new(Parachain(PARA_ID).into()), + Box::new(Parachain(OTHER_PARA_ID).into()), Box::new(beneficiary.into()), Box::new((Here, SEND_AMOUNT).into()), 0, @@ -521,7 +532,9 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works( /// Test `limited_reserve_transfer_assets` with local asset reserve and local fee reserve. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// Same as test above but with limited weight. +/// +/// Asserts that the sender's balance is decreased and the destination SA balance /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works() { @@ -534,7 +547,7 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv || { assert_ok!(XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), - Box::new(Parachain(PARA_ID).into()), + Box::new(Parachain(OTHER_PARA_ID).into()), Box::new(beneficiary.into()), Box::new((Here, SEND_AMOUNT).into()), 0, @@ -547,19 +560,32 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv /// Test `reserve_transfer_assets` with destination asset reserve and local fee reserve. /// +/// Transferring foreign asset (`FOREIGN_ASSET_RESERVE_PARA_ID` reserve) to +/// `FOREIGN_ASSET_RESERVE_PARA_ID` (no teleport trust). +/// Using native asset (local reserve) for fees. +/// +/// Here (source) FOREIGN_ASSET_RESERVE_PARA_ID (destination) +/// | `fees` reserve `assets` reserve +/// | +/// | 1. execute `TransferReserveAsset(fees)` +/// | \-> sends `ReserveAssetDeposited(fees), ClearOrigin, BuyExecution(fees), DepositAsset` +/// | 2. execute `InitiateReserveWithdraw(assets)` +/// | \--> sends `WithdrawAsset(assets), ClearOrigin, BuyExecution(fees), DepositAsset` +/// \------------------------------------------> +/// /// Asserts that the sender's balance is decreased and the beneficiary's balance /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_works() { // foreign creator in this case child parachain acting as reserve - let reserve_location = - RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); + let reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) + .unwrap(); let foreign_creator_as_account_id = SovereignAccountOf::convert_location(&reserve_location).unwrap(); - // foreign parachain with the same consensus currency as asset let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); + reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); let foreign_asset_amount = 142; // transfer destination is reserve location (no teleport trust) @@ -681,43 +707,51 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works /// Test `reserve_transfer_assets` with local asset reserve and destination fee reserve. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Transferring native asset (local reserve) to `USDC_RESERVE_PARA_ID` (no teleport trust). Using +/// foreign asset (`USDC_RESERVE_PARA_ID` reserve) for fees. +/// +/// Here (source) USDC_RESERVE_PARA_ID (destination) +/// | `assets` reserve `fees` reserve +/// | +/// | 1. execute `InitiateReserveWithdraw(fees)` +/// | \--> sends `WithdrawAsset(fees), ClearOrigin, BuyExecution(fees), DepositAsset` +/// | 2. execute `TransferReserveAsset(assts)` +/// | \-> sends `ReserveAssetDeposited(assts), ClearOrigin, BuyExecution(fees), DepositAsset` +/// \------------------------------------------> #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_works() { - // foreign creator in this case child parachain acting as reserve - let fee_reserve_location = - RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); - let foreign_creator_as_account_id = - SovereignAccountOf::convert_location(&fee_reserve_location).unwrap(); + let usdc_reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) + .unwrap(); + let usdc_chain_sovereign_account = + SovereignAccountOf::convert_location(&usdc_reserve_location).unwrap(); - // foreign parachain with the same consensus currency as asset - let foreign_asset_id_multilocation = - fee_reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_amount = 142; + let usdc_id_multilocation = + usdc_reserve_location.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); + let usdc_initial_local_amount = 142; - // transfer destination is fee reserve location (no teleport trust) - let dest = fee_reserve_location; + // native assets transfer destination is same as fee reserve location (no teleport trust) + let dest = usdc_reserve_location; let assets: MultiAssets = vec![ // native asset to transfer (not used for fees) (MultiLocation::here(), SEND_AMOUNT).into(), - // foreign asset for fees (is sufficient on local chain too) - (foreign_asset_id_multilocation, FEE_AMOUNT).into(), + // usdc for fees (is sufficient on local chain too) + (usdc_id_multilocation, FEE_AMOUNT).into(), ] .into(); let fee_index = 1; let asset_index = 0; let balances = - vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + vec![(ALICE, INITIAL_BALANCE), (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); new_test_ext_with_balances(balances).execute_with(|| { - // create sufficient foreign asset (0 total issuance) + // create sufficient foreign asset USDC (0 total issuance) assert_ok!(Assets::force_create( RuntimeOrigin::root(), - foreign_asset_id_multilocation, + usdc_id_multilocation, BOB, true, 1 @@ -726,11 +760,11 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ // mint it locally. assert_ok!(Assets::mint( RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, + usdc_id_multilocation, ALICE, - foreign_asset_amount + usdc_initial_local_amount )); - assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); let context = UniversalLocation::get(); @@ -754,20 +788,17 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ )); // Alice spent (fees) amount assert_eq!( - Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_amount - FEE_AMOUNT + Assets::balance(usdc_id_multilocation, ALICE), + usdc_initial_local_amount - FEE_AMOUNT ); // Alice used native asset for transfer assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); // Sovereign account of dest parachain holds `SEND_AMOUNT` native asset in local reserve assert_eq!( - Balances::free_balance(foreign_creator_as_account_id.clone()), + Balances::free_balance(usdc_chain_sovereign_account.clone()), INITIAL_BALANCE + SEND_AMOUNT ); - assert_eq!( - Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), - 0 - ); + assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); // Verify sent XCM program assert_eq!( @@ -807,19 +838,24 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ /// Test `reserve_transfer_assets` with destination asset reserve and destination fee reserve. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Here (source) FOREIGN_ASSET_RESERVE_PARA_ID (destination) +/// | `fees` reserve +/// | `assets` reserve +/// | +/// | 1. execute `InitiateReserveWithdraw(assets_and_fees_batched_together)` +/// | \--> sends `WithdrawAsset(batch), ClearOrigin, BuyExecution(fees), DepositAsset` +/// \------------------------------------------> #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_reserve_works() { - // foreign creator in this case child parachain acting as reserve - let reserve_location = - RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); + // we'll send just this foreign asset back to its reserve location and use it for fees as well + let reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) + .unwrap(); let foreign_creator_as_account_id = SovereignAccountOf::convert_location(&reserve_location).unwrap(); - // foreign parachain with the same consensus currency as asset let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); + reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); let foreign_asset_amount = 142; // transfer destination is reserve location @@ -885,7 +921,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re assert_eq!( sent_xcm(), vec![( - Parachain(RESERVE_PARA_ID).into(), + Parachain(FOREIGN_ASSET_RESERVE_PARA_ID).into(), Xcm(vec![ WithdrawAsset(expected_assets.clone()), ClearOrigin, @@ -910,57 +946,67 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve /// Test `reserve_transfer_assets` with local asset reserve and remote fee reserve. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Transferring native asset (local reserve) to `OTHER_PARA_ID` (no teleport trust). Using foreign +/// asset (`USDC_RESERVE_PARA_ID` remote reserve) for fees. +/// +/// | chain `A` | chain `C` | chain `B` +/// | Here (source) | USDC_RESERVE_PARA_ID | OTHER_PARA_ID (destination) +/// | `assets` reserve | `fees` reserve | +/// | +/// | 1. `A` executes `InitiateReserveWithdraw(fees)` dest `C` +/// | -----------------> `DepositReserveAsset(fees)` dest `B` +/// | --------------------------> `DepositAsset(fees)` +/// | 2. `A` executes `TransferReserveAsset(assets)` dest `B` +/// | --------------------------------------------------> `ReserveAssetDeposited(assets)` #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works() { // foreign creator in this case child parachain acting as reserve - let fee_reserve_location = - RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); - let foreign_creator_as_account_id = + let fee_reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) + .unwrap(); + let usdc_chain_sovereign_account = SovereignAccountOf::convert_location(&fee_reserve_location).unwrap(); - // foreign parachain with the same consensus currency as asset - let foreign_asset_id_multilocation = - fee_reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_amount = 142; + let usdc_id_multilocation = + fee_reserve_location.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); + let usdc_initial_local_amount = 142; - // transfer destination is other parachain than fee reserve location (no teleport trust) + // transfer destination is some other parachain != fee reserve location (no teleport trust) let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); - let dest_as_account_id = SovereignAccountOf::convert_location(&dest).unwrap(); + let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); let assets: MultiAssets = vec![ // native asset to transfer (not used for fees) - local reserve (MultiLocation::here(), SEND_AMOUNT).into(), - // foreign asset for fees (is sufficient on local chain too) - remote reserve - (foreign_asset_id_multilocation, FEE_AMOUNT).into(), + // USDC for fees (is sufficient on local chain too) - remote reserve + (usdc_id_multilocation, FEE_AMOUNT).into(), ] .into(); let fee_index = 1; let asset_index = 0; let balances = - vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + vec![(ALICE, INITIAL_BALANCE), (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); new_test_ext_with_balances(balances).execute_with(|| { - // create sufficient foreign asset (0 total issuance) + // create sufficient foreign asset USDC (0 total issuance) assert_ok!(Assets::force_create( RuntimeOrigin::root(), - foreign_asset_id_multilocation, + usdc_id_multilocation, BOB, true, 1 )); - // this asset should have been teleported/reserve-transferred in, but for this test we just + // USDC should have been teleported/reserve-transferred in, but for this test we just // mint it locally. assert_ok!(Assets::mint( RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, + usdc_id_multilocation, ALICE, - foreign_asset_amount + usdc_initial_local_amount )); - assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); let context = UniversalLocation::get(); @@ -987,27 +1033,24 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works )); // Alice spent (fees) amount assert_eq!( - Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_amount - FEE_AMOUNT + Assets::balance(usdc_id_multilocation, ALICE), + usdc_initial_local_amount - FEE_AMOUNT ); // Alice used native asset for transfer assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); // Sovereign account of reserve parachain is unchanged - assert_eq!(Balances::free_balance(foreign_creator_as_account_id.clone()), INITIAL_BALANCE); - assert_eq!( - Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), - 0 - ); + assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); // Sovereign account of destination parachain holds `SEND_AMOUNT` in local reserve - assert_eq!(Balances::free_balance(dest_as_account_id), SEND_AMOUNT); + assert_eq!(Balances::free_balance(dest_sovereign_account), SEND_AMOUNT); // Verify sent XCM program assert_eq!( sent_xcm(), vec![ ( - // first message is to prefund (foreign-asset) fees on `dest` (by going through - // fee remote reserve) + // first message is to prefund (USDC) fees on `dest` (by going through + // fee remote (USDC) reserve) fee_reserve_location, Xcm(vec![ WithdrawAsset(expected_fee_on_reserve.clone().into()), @@ -1027,7 +1070,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works ), ( // second message is to transfer/deposit (native) asset on `dest` while paying - // using prefunded (transferred above) fees + // using prefunded (transferred above) fees/USDC dest, // transfer is through local-reserve transfer because `assets` (native asset) // have local reserve @@ -1045,46 +1088,65 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works }); } -/// Test `reserve_transfer_assets` with destination asset reserve and local fee reserve. +/// Test `reserve_transfer_assets` with destination asset reserve and remote fee reserve. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Transferring native asset (local reserve) to `OTHER_PARA_ID` (no teleport trust). Using foreign +/// asset (`USDC_RESERVE_PARA_ID` remote reserve) for fees. +/// +/// | chain `A` | chain `C` | chain `B` +/// | Here (source) | USDC_RESERVE_PARA_ID | FOREIGN_ASSET_RESERVE_PARA_ID (destination) +/// | | `fees` reserve | `assets` reserve +/// | +/// | 1. `A` executes `InitiateReserveWithdraw(fees)` dest `C` +/// | -----------------> `DepositReserveAsset(fees)` dest `B` +/// | --------------------------> `DepositAsset(fees)` +/// | 2. `A` executes `InitiateReserveWithdraw(assets)` dest `B` +/// | --------------------------------------------------> `DepositAsset(assets)` #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve_works() { // TODO } -/// Test `reserve_transfer_assets` with remote asset reserve and local fee reserve. +/// Test `reserve_transfer_assets` with remote asset reserve and (same) remote fee reserve. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Transferring native asset (local reserve) to `OTHER_PARA_ID` (no teleport trust). Using foreign +/// asset (`USDC_RESERVE_PARA_ID` remote reserve) for fees. +/// +/// | chain `A` | chain `C` | chain `B` +/// | Here (source) | USDC_RESERVE_PARA_ID | OTHER_PARA_ID (destination) +/// | | `fees` reserve | +/// | | `assets` reserve | +/// | +/// | 1. `A` executes `InitiateReserveWithdraw(both)` dest `C` +/// | -----------------> `DepositReserveAsset(both)` dest `B` +/// | --------------------------> `DepositAsset(both)` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_works() { // foreign creator in this case child parachain acting as reserve - let reserve_location = - RelayLocation::get().pushed_with_interior(Parachain(RESERVE_PARA_ID)).unwrap(); - let foreign_creator_as_account_id = - SovereignAccountOf::convert_location(&reserve_location).unwrap(); + let usdc_reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) + .unwrap(); + let usdc_chain_sovereign_account = + SovereignAccountOf::convert_location(&usdc_reserve_location).unwrap(); - // foreign parachain with the same consensus currency as asset - let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(RESERVE_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_amount = 142; + let usdc_id_multilocation = + usdc_reserve_location.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); + let usdc_initial_local_amount = 142; - let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); + let assets: MultiAssets = vec![(usdc_id_multilocation, SEND_AMOUNT).into()].into(); let fee_index = 0; - // transfer destination is other parachain => remote reserve location (RESERVE_PARA_ID) + // transfer destination is some other parachainß let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); let balances = - vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + vec![(ALICE, INITIAL_BALANCE), (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); new_test_ext_with_balances(balances).execute_with(|| { - // create sufficient (to be used as fees as well) foreign asset (0 total issuance) + // create sufficient (to be used as fees as well) USDC asset (0 total issuance) assert_ok!(Assets::force_create( RuntimeOrigin::root(), - foreign_asset_id_multilocation, + usdc_id_multilocation, BOB, true, 1 @@ -1093,19 +1155,19 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work // mint it locally. assert_ok!(Assets::mint( RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, + usdc_id_multilocation, ALICE, - foreign_asset_amount + usdc_initial_local_amount )); - assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); let context = UniversalLocation::get(); let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); - expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); + expected_fee_on_reserve.reanchor(&usdc_reserve_location, context).unwrap(); let mut expected_assets = assets.clone(); expected_assets.reanchor(&dest, context).unwrap(); - let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); + let expected_dest_on_reserve = dest.reanchored(&usdc_reserve_location, context).unwrap(); // do the transfer assert_ok!(XcmPallet::limited_reserve_transfer_assets( @@ -1122,24 +1184,21 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work )); // Alice spent (transferred) amount assert_eq!( - Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_amount - SEND_AMOUNT + Assets::balance(usdc_id_multilocation, ALICE), + usdc_initial_local_amount - SEND_AMOUNT ); // Alice's native asset balance is untouched assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // Destination account (parachain account) has expected (same) balances - assert_eq!(Balances::free_balance(foreign_creator_as_account_id.clone()), INITIAL_BALANCE); - assert_eq!( - Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), - 0 - ); + assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); // Verify sent XCM program assert_eq!( sent_xcm(), vec![( // first message sent to reserve chain - Parachain(RESERVE_PARA_ID).into(), + usdc_reserve_location, Xcm(vec![ WithdrawAsset(expected_fee_on_reserve.clone().into()), ClearOrigin, @@ -1200,7 +1259,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() fn execute_withdraw_to_deposit_works() { let balances = vec![ (ALICE, INITIAL_BALANCE), - (ParaId::from(PARA_ID).into_account_truncating(), INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; new_test_ext_with_balances(balances).execute_with(|| { let weight = BaseXcmWeight::get() * 3; From 576c770b7e2f42a3e84447a116d212563975ea1b Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 28 Sep 2023 10:47:52 +0300 Subject: [PATCH 017/124] add test for asset destination-reserve while fee-reserve is remote chain --- polkadot/xcm/pallet-xcm/src/tests.rs | 157 ++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 1 deletion(-) diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 4ac8733b4284..d7aca7b71784 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -1104,7 +1104,162 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works /// | --------------------------------------------------> `DepositAsset(assets)` #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve_works() { - // TODO + // foreign creator in this case child parachain acting as reserve + let fee_reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) + .unwrap(); + let usdc_chain_sovereign_account = + SovereignAccountOf::convert_location(&fee_reserve_location).unwrap(); + let usdc_id_multilocation = + fee_reserve_location.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); + let usdc_initial_local_amount = 42; + + let reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) + .unwrap(); + let foreign_asset_id_multilocation = + reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); + let foreign_asset_initial_amount = 142; + + // transfer destination is asset reserve location + let dest = reserve_location; + let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); + let assets: MultiAssets = vec![ + // native asset to transfer (not used for fees) - destination reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + // USDC for fees (is sufficient on local chain too) - remote reserve + (usdc_id_multilocation, FEE_AMOUNT).into(), + ] + .into(); + let fee_index = 1; + let asset_index = 0; + + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE), + (dest_sovereign_account.clone(), INITIAL_BALANCE), + ]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient foreign asset USDC (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + usdc_id_multilocation, + BOB, + true, + 1 + )); + // USDC should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + usdc_id_multilocation, + ALICE, + usdc_initial_local_amount + )); + // create non-sufficient foreign asset BLA (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + false, + 1 + )); + // foreign asset BLA should have been teleported/reserve-transferred in, but for this test + // we just mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_initial_amount + )); + assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + let context = UniversalLocation::get(); + let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); + expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); + let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + expected_asset.reanchor(&dest, context).unwrap(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + expected_fee.reanchor(&dest, context).unwrap(); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice native asset untouched + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + // Alice spent USDC for fees + assert_eq!( + Assets::balance(usdc_id_multilocation, ALICE), + usdc_initial_local_amount - FEE_AMOUNT + ); + // Alice transferred BLA + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_initial_amount - SEND_AMOUNT + ); + // Verify balances of USDC reserve parachain + assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); + // Verify balances of transferred-asset reserve parachain + assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, dest_sovereign_account), 0); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![ + ( + // first message is to prefund (USDC) fees on `dest` (by going through + // fee remote (USDC) reserve) + fee_reserve_location, + Xcm(vec![ + WithdrawAsset(expected_fee_on_reserve.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee_on_reserve, Unlimited), + DepositReserveAsset { + assets: Wild(AllCounted(1)), + // final destination is `dest` as seen by `reserve` + dest: expected_dest_on_reserve, + // message sent onward to final `dest` to deposit/prefund fees + xcm: Xcm(vec![ + buy_limited_execution(expected_fee.clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary } + ]) + } + ]) + ), + ( + // second message is to transfer/deposit foreign assets on `dest` while paying + // using prefunded (transferred above) fees (USDC) + // (dest is reserve location for `expected_asset`) + dest, + Xcm(vec![ + WithdrawAsset(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ) + ] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with remote asset reserve and (same) remote fee reserve. From 280c4b1216442439d1591e7253a2cda53e280344 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 28 Sep 2023 10:48:21 +0300 Subject: [PATCH 018/124] fix some typos --- .../emulated/assets/asset-hub-westend/src/lib.rs | 4 ++-- .../assets/asset-hub-westend/src/tests/reserve_transfer.rs | 2 +- .../emulated/bridges/bridge-hub-rococo/src/lib.rs | 2 +- polkadot/runtime/parachains/src/paras/mod.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs index 6e0f3434aedf..e0a296df03f3 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs @@ -51,7 +51,7 @@ pub type RelayToSystemParaTest = Test; pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; -/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests +/// Returns a `TestArgs` instance to de used for the Relay Chain across integration tests pub fn relay_test_args(amount: Balance) -> TestArgs { TestArgs { dest: Westend::child_location_of(AssetHubWestend::para_id()), @@ -68,7 +68,7 @@ pub fn relay_test_args(amount: Balance) -> TestArgs { } } -/// Returns a `TestArgs` instance to de used for the System Parachain accross integraton tests +/// Returns a `TestArgs` instance to de used for the System Parachain across integration tests pub fn system_para_test_args( dest: MultiLocation, beneficiary_id: AccountId32, diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs index 51fac43be125..491343692e9f 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -189,7 +189,7 @@ fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() { assert_eq!(receiver_balance_before, receiver_balance_after); } -/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shoudln't work +/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work #[test] fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() { // Init values for System Parachain diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs index 1c73124c5125..f1993c392fd2 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs @@ -45,7 +45,7 @@ pub type RelayToSystemParaTest = Test; pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; -/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests +/// Returns a `TestArgs` instance to de used for the Relay Chain across integration tests pub fn relay_test_args(amount: Balance) -> TestArgs { TestArgs { dest: Rococo::child_location_of(AssetHubRococo::para_id()), diff --git a/polkadot/runtime/parachains/src/paras/mod.rs b/polkadot/runtime/parachains/src/paras/mod.rs index 2f370b5bfe47..828dcf7d6f04 100644 --- a/polkadot/runtime/parachains/src/paras/mod.rs +++ b/polkadot/runtime/parachains/src/paras/mod.rs @@ -2036,7 +2036,7 @@ impl Pallet { } /// Submits a given PVF check statement with corresponding signature as an unsigned transaction - /// into the memory pool. Ultimately, that disseminates the transaction accross the network. + /// into the memory pool. Ultimately, that disseminates the transaction across the network. /// /// This function expects an offchain context and cannot be callable from the on-chain logic. /// From bab8fc24e74e298bca5de80096766ecab9f059ef Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 28 Sep 2023 11:10:20 +0300 Subject: [PATCH 019/124] deduplicate code for do_teleport_assets() --- polkadot/xcm/pallet-xcm/src/lib.rs | 92 ++++++++++++++++-------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 7e1051134281..a094e9781cdc 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1383,6 +1383,41 @@ impl Pallet { ) } + fn do_teleport_assets( + origin: OriginFor, + dest: Box, + beneficiary: Box, + assets: Box, + fee_asset_item: u32, + weight_limit: WeightLimit, + ) -> DispatchResult { + let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; + let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; + let beneficiary: MultiLocation = + (*beneficiary).try_into().map_err(|()| Error::::BadVersion)?; + let assets: MultiAssets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; + + ensure!(assets.len() <= MAX_ASSETS_FOR_TRANSFER, Error::::TooManyAssets); + let value = (origin_location, assets.into_inner()); + ensure!(T::XcmTeleportFilter::contains(&value), Error::::Filtered); + let (origin_location, assets) = value; + for asset in assets.iter() { + let transfer_type = TransferType::determine_for::(asset, &dest)?; + ensure!(matches!(transfer_type, TransferType::Teleport), Error::::Filtered); + } + let fees = assets.get(fee_asset_item as usize).ok_or(Error::::Empty)?.clone(); + + Self::build_and_execute_xcm_transfer_type( + origin_location, + dest, + beneficiary, + assets, + TransferType::Teleport, + fees, + weight_limit, + ) + } + /// Teleport or reserve transfer `fees` - not to be used by itself, it is a helper function for /// prefunding fees for subsequent assets transfer. /// @@ -1426,7 +1461,8 @@ impl Pallet { fees, weight_limit, ), - TransferType::Teleport => todo!(), + TransferType::Teleport => + Self::teleport_asset_message(dest, beneficiary, assets, fees, weight_limit), }?; let weight = T::Weigher::weight(&mut message).map_err(|()| Error::::UnweighableMessage)?; @@ -1519,55 +1555,25 @@ impl Pallet { ])) } - fn do_teleport_assets( - origin: OriginFor, - dest: Box, - beneficiary: Box, - assets: Box, - fee_asset_item: u32, + fn teleport_asset_message( + dest: MultiLocation, + beneficiary: MultiLocation, + assets: Vec, + mut fees: MultiAsset, weight_limit: WeightLimit, - ) -> DispatchResult { - let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; - let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; - let beneficiary: MultiLocation = - (*beneficiary).try_into().map_err(|()| Error::::BadVersion)?; - let assets: MultiAssets = (*assets).try_into().map_err(|()| Error::::BadVersion)?; - - ensure!(assets.len() <= MAX_ASSETS_FOR_TRANSFER, Error::::TooManyAssets); - let value = (origin_location, assets.into_inner()); - ensure!(T::XcmTeleportFilter::contains(&value), Error::::Filtered); - let (origin_location, assets) = value; - for asset in assets.iter() { - ensure!( - ::IsTeleporter::contains(asset, &dest), - Error::::Filtered - ); - } + ) -> Result::RuntimeCall>, Error> { let context = T::UniversalLocation::get(); - let fees = assets - .get(fee_asset_item as usize) - .ok_or(Error::::Empty)? - .clone() - .reanchored(&dest, context) - .map_err(|_| Error::::CannotReanchor)?; + fees.reanchor(&dest, context).map_err(|_| Error::::CannotReanchor)?; let max_assets = assets.len() as u32; - let assets: MultiAssets = assets.into(); - let xcm = Xcm(vec![ + let xcm_on_dest = Xcm(vec![ BuyExecution { fees, weight_limit }, DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, ]); - let mut message = Xcm(vec![ - WithdrawAsset(assets), + Ok(Xcm(vec![ + WithdrawAsset(assets.into()), SetFeesMode { jit_withdraw: true }, - InitiateTeleport { assets: Wild(AllCounted(max_assets)), dest, xcm }, - ]); - let weight = - T::Weigher::weight(&mut message).map_err(|()| Error::::UnweighableMessage)?; - let hash = message.using_encoded(sp_io::hashing::blake2_256); - let outcome = - T::XcmExecutor::execute_xcm_in_credit(origin_location, message, hash, weight, weight); - Self::deposit_event(Event::Attempted { outcome }); - Ok(()) + InitiateTeleport { assets: Wild(AllCounted(max_assets)), dest, xcm: xcm_on_dest }, + ])) } /// Will always make progress, and will do its best not to use much more than `weight_cutoff` From f7a4a2e3cf54ee47a23d09211a7c1dfc446f7106 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 28 Sep 2023 12:20:10 +0300 Subject: [PATCH 020/124] add test for asset local-reserve while teleporting fees --- polkadot/xcm/pallet-xcm/src/mock.rs | 26 +++- polkadot/xcm/pallet-xcm/src/tests.rs | 204 ++++++++++++++++++++++++++- 2 files changed, 221 insertions(+), 9 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 982df882b873..29c34afb0f17 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -285,6 +285,10 @@ pub const USDC_RESERVE_PARA_ID: u32 = 2002; // Inner junction of reserve asset on `USDC_RESERVE_PARA_ID`. pub const USDC_INNER_JUNCTION: Junction = PalletInstance(42); +// This child parachain is a trusted teleporter for say.. USDT (T from Teleport :)). +// We'll use USDT in tests that teleport fees. +pub const USDT_PARA_ID: u32 = 2003; + // This child parachain is not configured as trusted reserve or teleport location for any assets. pub const OTHER_PARA_ID: u32 = 2009; @@ -312,6 +316,17 @@ parameter_types! { interior: X2(Parachain(USDC_RESERVE_PARA_ID), USDC_INNER_JUNCTION), }), }; + pub const UsdtTeleportLocation: MultiLocation = MultiLocation { + parents: 0, + interior: X1(Parachain(USDT_PARA_ID)) + }; + pub const Usdt: MultiAsset = MultiAsset { + fun: Fungible(10), + id: Concrete(MultiLocation { + parents: 0, + interior: X1(Parachain(USDT_PARA_ID)), + }), + }; pub const AnyNetwork: Option = None; pub UniversalLocation: InteriorMultiLocation = Here; pub UnitWeightCost: u64 = 1_000; @@ -362,9 +377,10 @@ type LocalOriginConverter = ( parameter_types! { pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000); pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1); - pub TrustedAssets: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into()); - pub TrustedReserve1: (MultiAssetFilter, MultiLocation) = (vec![ForeignAsset::get()].into(), ForeignReserveLocation::get()); - pub TrustedReserve2: (MultiAssetFilter, MultiLocation) = (vec![Usdc::get()].into(), UsdcReserveLocation::get()); + pub TrustedLocal: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into()); + pub TrustedUsdt: (MultiAssetFilter, MultiLocation) = (vec![Usdt::get()].into(), UsdtTeleportLocation::get()); + pub TrustedForeign: (MultiAssetFilter, MultiLocation) = (vec![ForeignAsset::get()].into(), ForeignReserveLocation::get()); + pub TrustedUsdc: (MultiAssetFilter, MultiLocation) = (vec![Usdc::get()].into(), UsdcReserveLocation::get()); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; } @@ -382,8 +398,8 @@ impl xcm_executor::Config for XcmConfig { type XcmSender = TestSendXcm; type AssetTransactor = AssetTransactors; type OriginConverter = LocalOriginConverter; - type IsReserve = (Case, Case); - type IsTeleporter = Case; + type IsReserve = (Case, Case); + type IsTeleporter = (Case, Case); type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index d7aca7b71784..702d3ac92c18 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -21,7 +21,7 @@ use crate::{ }; use frame_support::{ assert_noop, assert_ok, - traits::{Currency, Hooks}, + traits::{tokens::fungibles::Inspect, Currency, Hooks}, weights::Weight, }; use polkadot_parachain_primitives::primitives::Id as ParaId; @@ -660,6 +660,16 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), 0 ); + // Verify total and active issuance of foreign BLA have decreased (reserve-based + // (local-instance) BLA was burned) + assert_eq!( + Assets::total_issuance(foreign_asset_id_multilocation), + foreign_asset_amount - SEND_AMOUNT + ); + assert_eq!( + Assets::active_issuance(foreign_asset_id_multilocation), + foreign_asset_amount - SEND_AMOUNT + ); // Verify sent XCM program assert_eq!( @@ -799,6 +809,16 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ INITIAL_BALANCE + SEND_AMOUNT ); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); + // Verify total and active issuance of USDC have decreased (reserve-based (local-instance) + // USDC was burned) + assert_eq!( + Assets::total_issuance(usdc_id_multilocation), + usdc_initial_local_amount - FEE_AMOUNT + ); + assert_eq!( + Assets::active_issuance(usdc_id_multilocation), + usdc_initial_local_amount - FEE_AMOUNT + ); // Verify sent XCM program assert_eq!( @@ -916,6 +936,16 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), 0 ); + // Verify total and active issuance of foreign BLA have decreased (reserve-based + // (local-instance) BLA was burned) + assert_eq!( + Assets::total_issuance(foreign_asset_id_multilocation), + foreign_asset_amount - SEND_AMOUNT + ); + assert_eq!( + Assets::active_issuance(foreign_asset_id_multilocation), + foreign_asset_amount - SEND_AMOUNT + ); // Verify sent XCM program assert_eq!( @@ -1043,6 +1073,16 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); // Sovereign account of destination parachain holds `SEND_AMOUNT` in local reserve assert_eq!(Balances::free_balance(dest_sovereign_account), SEND_AMOUNT); + // Verify total and active issuance of USDC have decreased (reserve-based (local-instance) + // USDC was burned) + assert_eq!( + Assets::total_issuance(usdc_id_multilocation), + usdc_initial_local_amount - FEE_AMOUNT + ); + assert_eq!( + Assets::active_issuance(usdc_id_multilocation), + usdc_initial_local_amount - FEE_AMOUNT + ); // Verify sent XCM program assert_eq!( @@ -1218,6 +1258,26 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve // Verify balances of transferred-asset reserve parachain assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), INITIAL_BALANCE); assert_eq!(Assets::balance(foreign_asset_id_multilocation, dest_sovereign_account), 0); + // Verify total and active issuance of USDC have decreased (reserve-based (local-instance) + // USDC was burned) + assert_eq!( + Assets::total_issuance(usdc_id_multilocation), + usdc_initial_local_amount - FEE_AMOUNT + ); + assert_eq!( + Assets::active_issuance(usdc_id_multilocation), + usdc_initial_local_amount - FEE_AMOUNT + ); + // Verify total and active issuance of foreign BLA asset have decreased (reserve-based + // (local-instance) asset was burned) + assert_eq!( + Assets::total_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); + assert_eq!( + Assets::active_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); // Verify sent XCM program assert_eq!( @@ -1347,6 +1407,16 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work // Destination account (parachain account) has expected (same) balances assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), INITIAL_BALANCE); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); + // Verify total and active issuance of USDC have decreased (reserve-based (local-instance) + // USDC was burned) + assert_eq!( + Assets::total_issuance(usdc_id_multilocation), + usdc_initial_local_amount - SEND_AMOUNT + ); + assert_eq!( + Assets::active_issuance(usdc_id_multilocation), + usdc_initial_local_amount - SEND_AMOUNT + ); // Verify sent XCM program assert_eq!( @@ -1381,11 +1451,137 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work /// Test `reserve_transfer_assets` with local asset reserve and teleported fee. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Transferring native asset (local reserve) to `USDT_PARA_ID`. Using teleport-trusted USDT for +/// fees. +/// +/// Here (source) USDT_PARA_ID (destination) +/// | `assets` reserve `fees` teleport-trust +/// | +/// | 1. execute `InitiateTeleport(fees)` +/// | \--> sends `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)` +/// | 2. execute `TransferReserveAsset(assts)` +/// | \-> sends `ReserveAssetDeposited(assts), ClearOrigin, BuyExecution(fees), DepositAsset` +/// \------------------------------------------> #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { - // TODO + let usdt_location = RelayLocation::get().pushed_with_interior(Parachain(USDT_PARA_ID)).unwrap(); + let usdt_chain_sovereign_account = + SovereignAccountOf::convert_location(&usdt_location).unwrap(); + + let usdt_id_multilocation = usdt_location; + let usdt_initial_local_amount = 42; + + // native assets transfer destination is USDT chain (teleport trust only for USDT) + let dest = usdt_location; + let assets: MultiAssets = vec![ + // native asset to transfer (not used for fees) + (MultiLocation::here(), SEND_AMOUNT).into(), + // usdc for fees (is sufficient on local chain too) + (usdt_id_multilocation, FEE_AMOUNT).into(), + ] + .into(); + let fee_index = 1; + let asset_index = 0; + + let balances = + vec![(ALICE, INITIAL_BALANCE), (usdt_chain_sovereign_account.clone(), INITIAL_BALANCE)]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient foreign asset USDT (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + usdt_id_multilocation, + BOB, + true, + 1 + )); + // this asset should have been teleported in, but for this test we just mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + usdt_id_multilocation, + ALICE, + usdt_initial_local_amount + )); + assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + expected_fee.reanchor(&dest, context).unwrap(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + expected_asset.reanchor(&dest, context).unwrap(); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice spent (fees) amount + assert_eq!( + Assets::balance(usdt_id_multilocation, ALICE), + usdt_initial_local_amount - FEE_AMOUNT + ); + // Alice used native asset for transfer + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); + // Sovereign account of dest parachain holds `SEND_AMOUNT` native asset in local reserve + assert_eq!( + Balances::free_balance(usdt_chain_sovereign_account.clone()), + INITIAL_BALANCE + SEND_AMOUNT + ); + assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); + // Verify total and active issuance have decreased + assert_eq!( + Assets::total_issuance(usdt_id_multilocation), + usdt_initial_local_amount - FEE_AMOUNT + ); + assert_eq!( + Assets::active_issuance(usdt_id_multilocation), + usdt_initial_local_amount - FEE_AMOUNT + ); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![ + ( + // first message is to prefund fees on `dest` + dest, + // fees are teleported to destination chain + Xcm(vec![ + ReceiveTeleportedAsset(expected_fee.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee.clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ), + ( + // second message is to transfer/deposit (native) asset on `dest` while paying + // using prefunded (transferred above) fees + dest, + // transfer is through local-reserve transfer because `assets` (native asset) + // have local reserve + Xcm(vec![ + ReserveAssetDeposited(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ) + ] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with destination asset reserve and teleported fee. From f88de5e74dcb0dd8c3fe7e9cbeedb34eb23e7181 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 28 Sep 2023 14:16:57 +0300 Subject: [PATCH 021/124] add test for asset destination-reserve while teleporting fees --- polkadot/xcm/pallet-xcm/src/mock.rs | 4 +- polkadot/xcm/pallet-xcm/src/tests.rs | 317 +++++++++++++++++++++++---- 2 files changed, 272 insertions(+), 49 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 29c34afb0f17..b269fcea394b 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -276,6 +276,7 @@ impl pallet_assets::Config for Test { } // This child parachain acts as trusted reserve for its assets in tests. +// USDT allowed to teleport to/from here. pub const FOREIGN_ASSET_RESERVE_PARA_ID: u32 = 2001; // Inner junction of reserve asset on `FOREIGN_ASSET_RESERVE_PARA_ID`. pub const FOREIGN_ASSET_INNER_JUNCTION: Junction = GeneralIndex(1234567); @@ -379,6 +380,7 @@ parameter_types! { pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1); pub TrustedLocal: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into()); pub TrustedUsdt: (MultiAssetFilter, MultiLocation) = (vec![Usdt::get()].into(), UsdtTeleportLocation::get()); + pub TeleportUsdtToForeign: (MultiAssetFilter, MultiLocation) = (vec![Usdt::get()].into(), ForeignReserveLocation::get()); pub TrustedForeign: (MultiAssetFilter, MultiLocation) = (vec![ForeignAsset::get()].into(), ForeignReserveLocation::get()); pub TrustedUsdc: (MultiAssetFilter, MultiLocation) = (vec![Usdc::get()].into(), UsdcReserveLocation::get()); pub const MaxInstructions: u32 = 100; @@ -399,7 +401,7 @@ impl xcm_executor::Config for XcmConfig { type AssetTransactor = AssetTransactors; type OriginConverter = LocalOriginConverter; type IsReserve = (Case, Case); - type IsTeleporter = (Case, Case); + type IsTeleporter = (Case, Case, Case); type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 702d3ac92c18..1fccafc7ebcf 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -501,6 +501,7 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( /// Transferring native asset (local reserve) to some `OTHER_PARA_ID` (no teleport trust). /// Using native asset for fees as well. /// +/// ```nocompile /// Here (source) OTHER_PARA_ID (destination) /// | `assets` reserve /// | `fees` reserve @@ -508,6 +509,7 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( /// | 1. execute `TransferReserveAsset(assets_and_fees_batched_together)` /// | \--> sends `ReserveAssetDeposited(both), ClearOrigin, BuyExecution(fees), DepositAsset` /// \------------------------------------------> +/// ``` /// /// Asserts that the sender's balance is decreased and the destination SA balance /// is increased. Verifies the correct message is sent and event is emitted. @@ -564,6 +566,7 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv /// `FOREIGN_ASSET_RESERVE_PARA_ID` (no teleport trust). /// Using native asset (local reserve) for fees. /// +/// ```nocompile /// Here (source) FOREIGN_ASSET_RESERVE_PARA_ID (destination) /// | `fees` reserve `assets` reserve /// | @@ -572,6 +575,7 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv /// | 2. execute `InitiateReserveWithdraw(assets)` /// | \--> sends `WithdrawAsset(assets), ClearOrigin, BuyExecution(fees), DepositAsset` /// \------------------------------------------> +/// ``` /// /// Asserts that the sender's balance is decreased and the beneficiary's balance /// is increased. Verifies the correct message is sent and event is emitted. @@ -600,6 +604,18 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ let fee_index = 0; let asset_index = 1; + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + + // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. + assert_eq!(expected_fee.id, MultiLocation::here().into()); + assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); + + // reanchor according to test-case. + expected_fee.reanchor(&dest, context).unwrap(); + expected_asset.reanchor(&dest, context).unwrap(); + let balances = vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; let beneficiary: MultiLocation = @@ -625,12 +641,6 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - expected_fee.reanchor(&dest, context).unwrap(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - expected_asset.reanchor(&dest, context).unwrap(); - // do the transfer assert_ok!(XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), @@ -720,6 +730,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works /// Transferring native asset (local reserve) to `USDC_RESERVE_PARA_ID` (no teleport trust). Using /// foreign asset (`USDC_RESERVE_PARA_ID` reserve) for fees. /// +/// ```nocompile /// Here (source) USDC_RESERVE_PARA_ID (destination) /// | `assets` reserve `fees` reserve /// | @@ -728,6 +739,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works /// | 2. execute `TransferReserveAsset(assts)` /// | \-> sends `ReserveAssetDeposited(assts), ClearOrigin, BuyExecution(fees), DepositAsset` /// \------------------------------------------> +/// ``` #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_works() { let usdc_reserve_location = RelayLocation::get() @@ -752,6 +764,18 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ let fee_index = 1; let asset_index = 0; + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + + // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. + assert_eq!(expected_fee.id, usdc_id_multilocation.into()); + assert_eq!(expected_asset.id, MultiLocation::here().into()); + + // reanchor according to test-case. + expected_fee.reanchor(&dest, context).unwrap(); + expected_asset.reanchor(&dest, context).unwrap(); + let balances = vec![(ALICE, INITIAL_BALANCE), (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE)]; let beneficiary: MultiLocation = @@ -777,12 +801,6 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - expected_fee.reanchor(&dest, context).unwrap(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - expected_asset.reanchor(&dest, context).unwrap(); - // do the transfer assert_ok!(XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), @@ -858,6 +876,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ /// Test `reserve_transfer_assets` with destination asset reserve and destination fee reserve. /// +/// ```nocompile /// Here (source) FOREIGN_ASSET_RESERVE_PARA_ID (destination) /// | `fees` reserve /// | `assets` reserve @@ -865,6 +884,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ /// | 1. execute `InitiateReserveWithdraw(assets_and_fees_batched_together)` /// | \--> sends `WithdrawAsset(batch), ClearOrigin, BuyExecution(fees), DepositAsset` /// \------------------------------------------> +/// ``` #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_reserve_works() { // we'll send just this foreign asset back to its reserve location and use it for fees as well @@ -883,6 +903,9 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); let fee_index = 0; + let mut expected_assets = assets.clone(); + expected_assets.reanchor(&dest, UniversalLocation::get()).unwrap(); + let balances = vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; let beneficiary: MultiLocation = @@ -907,9 +930,6 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - let mut expected_assets = assets.clone(); - expected_assets.reanchor(&dest, UniversalLocation::get()).unwrap(); - // do the transfer assert_ok!(XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), @@ -979,6 +999,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve /// Transferring native asset (local reserve) to `OTHER_PARA_ID` (no teleport trust). Using foreign /// asset (`USDC_RESERVE_PARA_ID` remote reserve) for fees. /// +/// ```nocompile /// | chain `A` | chain `C` | chain `B` /// | Here (source) | USDC_RESERVE_PARA_ID | OTHER_PARA_ID (destination) /// | `assets` reserve | `fees` reserve | @@ -988,6 +1009,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve /// | --------------------------> `DepositAsset(fees)` /// | 2. `A` executes `TransferReserveAsset(assets)` dest `B` /// | --------------------------------------------------> `ReserveAssetDeposited(assets)` +/// ``` #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works() { // foreign creator in this case child parachain acting as reserve @@ -1011,8 +1033,23 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works (usdc_id_multilocation, FEE_AMOUNT).into(), ] .into(); - let fee_index = 1; let asset_index = 0; + let fee_index = 1; + + let context = UniversalLocation::get(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + + // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. + assert_eq!(expected_fee.id, usdc_id_multilocation.into()); + assert_eq!(expected_asset.id, MultiLocation::here().into()); + + // reanchor according to test-case. + let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); + expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); + let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); + expected_fee.reanchor(&dest, context).unwrap(); + expected_asset.reanchor(&dest, context).unwrap(); let balances = vec![(ALICE, INITIAL_BALANCE), (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE)]; @@ -1039,15 +1076,6 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - let context = UniversalLocation::get(); - let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); - expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); - let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - expected_asset.reanchor(&dest, context).unwrap(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - expected_fee.reanchor(&dest, context).unwrap(); - // do the transfer assert_ok!(XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), @@ -1133,6 +1161,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works /// Transferring native asset (local reserve) to `OTHER_PARA_ID` (no teleport trust). Using foreign /// asset (`USDC_RESERVE_PARA_ID` remote reserve) for fees. /// +/// ```nocompile /// | chain `A` | chain `C` | chain `B` /// | Here (source) | USDC_RESERVE_PARA_ID | FOREIGN_ASSET_RESERVE_PARA_ID (destination) /// | | `fees` reserve | `assets` reserve @@ -1142,6 +1171,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works /// | --------------------------> `DepositAsset(fees)` /// | 2. `A` executes `InitiateReserveWithdraw(assets)` dest `B` /// | --------------------------------------------------> `DepositAsset(assets)` +/// ``` #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve_works() { // foreign creator in this case child parachain acting as reserve @@ -1165,14 +1195,29 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve let dest = reserve_location; let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); let assets: MultiAssets = vec![ - // native asset to transfer (not used for fees) - destination reserve + // foreign asset to transfer (not used for fees) - destination reserve (foreign_asset_id_multilocation, SEND_AMOUNT).into(), // USDC for fees (is sufficient on local chain too) - remote reserve (usdc_id_multilocation, FEE_AMOUNT).into(), ] .into(); - let fee_index = 1; let asset_index = 0; + let fee_index = 1; + + let context = UniversalLocation::get(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + + // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. + assert_eq!(expected_fee.id, usdc_id_multilocation.into()); + assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); + + // reanchor according to test-case. + let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); + expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); + let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); + expected_fee.reanchor(&dest, context).unwrap(); + expected_asset.reanchor(&dest, context).unwrap(); let balances = vec![ (ALICE, INITIAL_BALANCE), @@ -1218,15 +1263,6 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - let context = UniversalLocation::get(); - let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); - expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); - let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - expected_asset.reanchor(&dest, context).unwrap(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - expected_fee.reanchor(&dest, context).unwrap(); - // do the transfer assert_ok!(XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), @@ -1327,6 +1363,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve /// Transferring native asset (local reserve) to `OTHER_PARA_ID` (no teleport trust). Using foreign /// asset (`USDC_RESERVE_PARA_ID` remote reserve) for fees. /// +/// ```nocompile /// | chain `A` | chain `C` | chain `B` /// | Here (source) | USDC_RESERVE_PARA_ID | OTHER_PARA_ID (destination) /// | | `fees` reserve | @@ -1335,6 +1372,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve /// | 1. `A` executes `InitiateReserveWithdraw(both)` dest `C` /// | -----------------> `DepositReserveAsset(both)` dest `B` /// | --------------------------> `DepositAsset(both)` +/// ``` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_works() { // foreign creator in this case child parachain acting as reserve @@ -1454,6 +1492,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work /// Transferring native asset (local reserve) to `USDT_PARA_ID`. Using teleport-trusted USDT for /// fees. /// +/// ```nocompile /// Here (source) USDT_PARA_ID (destination) /// | `assets` reserve `fees` teleport-trust /// | @@ -1462,6 +1501,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work /// | 2. execute `TransferReserveAsset(assts)` /// | \-> sends `ReserveAssetDeposited(assts), ClearOrigin, BuyExecution(fees), DepositAsset` /// \------------------------------------------> +/// ``` #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { let usdt_location = RelayLocation::get().pushed_with_interior(Parachain(USDT_PARA_ID)).unwrap(); @@ -1476,12 +1516,24 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { let assets: MultiAssets = vec![ // native asset to transfer (not used for fees) (MultiLocation::here(), SEND_AMOUNT).into(), - // usdc for fees (is sufficient on local chain too) + // USDT for fees (is sufficient on local chain too) (usdt_id_multilocation, FEE_AMOUNT).into(), ] .into(); - let fee_index = 1; let asset_index = 0; + let fee_index = 1; + + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + + // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. + assert_eq!(expected_fee.id, usdt_id_multilocation.into()); + assert_eq!(expected_asset.id, MultiLocation::here().into()); + + // reanchor according to test-case. + expected_fee.reanchor(&dest, context).unwrap(); + expected_asset.reanchor(&dest, context).unwrap(); let balances = vec![(ALICE, INITIAL_BALANCE), (usdt_chain_sovereign_account.clone(), INITIAL_BALANCE)]; @@ -1507,12 +1559,6 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - expected_fee.reanchor(&dest, context).unwrap(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - expected_asset.reanchor(&dest, context).unwrap(); - // do the transfer assert_ok!(XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), @@ -1539,7 +1585,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { INITIAL_BALANCE + SEND_AMOUNT ); assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); - // Verify total and active issuance have decreased + // Verify total and active issuance have decreased (teleported) assert_eq!( Assets::total_issuance(usdt_id_multilocation), usdt_initial_local_amount - FEE_AMOUNT @@ -1586,11 +1632,186 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { /// Test `reserve_transfer_assets` with destination asset reserve and teleported fee. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Transferring native asset (local reserve) to `FOREIGN_ASSET_RESERVE_PARA_ID`. Using +/// teleport-trusted USDT for fees. +/// +/// ```nocompile +/// Here (source) FOREIGN_ASSET_RESERVE_PARA_ID (destination) +/// | `fees` (USDT) teleport-trust +/// | `assets` reserve +/// | +/// | 1. execute `InitiateTeleport(fees)` +/// | \--> sends `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)` +/// | 2. execute `InitiateReserveWithdraw(assets)` +/// | \--> sends `WithdrawAsset(asset), ClearOrigin, BuyExecution(fees), DepositAsset` +/// \------------------------------------------> +/// ``` #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_works() { - // TODO + let usdt_chain = RelayLocation::get().pushed_with_interior(Parachain(USDT_PARA_ID)).unwrap(); + let usdt_chain_sovereign_account = SovereignAccountOf::convert_location(&usdt_chain).unwrap(); + let usdt_id_multilocation = usdt_chain; + let usdt_initial_local_amount = 42; + + let reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) + .unwrap(); + let foreign_asset_id_multilocation = + reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); + let foreign_asset_initial_amount = 142; + + // transfer destination is asset reserve location + let dest = reserve_location; + let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); + let assets: MultiAssets = vec![ + // USDT for fees (is sufficient on local chain too) + (usdt_id_multilocation, FEE_AMOUNT).into(), + // foreign asset to transfer (not used for fees) - destination reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ] + .into(); + let fee_index = 0; + let asset_index = 1; + + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + + // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. + assert_eq!(expected_fee.id, usdt_id_multilocation.into()); + assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); + + // reanchor according to test-case. + expected_fee.reanchor(&dest, context).unwrap(); + expected_asset.reanchor(&dest, context).unwrap(); + + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (usdt_chain_sovereign_account.clone(), INITIAL_BALANCE), + (dest_sovereign_account.clone(), INITIAL_BALANCE), + ]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient foreign asset USDT (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + usdt_id_multilocation, + BOB, + true, + 1 + )); + // USDT should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + usdt_id_multilocation, + ALICE, + usdt_initial_local_amount + )); + // create non-sufficient foreign asset BLA (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + false, + 1 + )); + // foreign asset BLA should have been teleported/reserve-transferred in, but for this test + // we just mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_initial_amount + )); + assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice native asset untouched + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + // Alice spent USDT for fees + assert_eq!( + Assets::balance(usdt_id_multilocation, ALICE), + usdt_initial_local_amount - FEE_AMOUNT + ); + // Alice transferred BLA + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_initial_amount - SEND_AMOUNT + ); + // Verify balances of USDT reserve parachain + assert_eq!(Balances::free_balance(usdt_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); + // Verify balances of transferred-asset reserve parachain + assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, dest_sovereign_account), 0); + // Verify total and active issuance of USDT have decreased (teleported) + assert_eq!( + Assets::total_issuance(usdt_id_multilocation), + usdt_initial_local_amount - FEE_AMOUNT + ); + assert_eq!( + Assets::active_issuance(usdt_id_multilocation), + usdt_initial_local_amount - FEE_AMOUNT + ); + // Verify total and active issuance of foreign BLA asset have decreased (reserve-based + // (local-instance) asset was burned) + assert_eq!( + Assets::total_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); + assert_eq!( + Assets::active_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![ + ( + // first message is to prefund fees on `dest` + dest, + // fees are teleported to destination chain + Xcm(vec![ + ReceiveTeleportedAsset(expected_fee.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee.clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ), + ( + // second message is to transfer/deposit foreign assets on `dest` while paying + // using prefunded (transferred above) fees (USDT) + // (dest is reserve location for `expected_asset`) + dest, + Xcm(vec![ + WithdrawAsset(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ) + ] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with remote asset reserve and teleported fee. From f7abb0ac61f4d3ac5e87ee4cd986f56b3f8a667b Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 28 Sep 2023 15:58:02 +0300 Subject: [PATCH 022/124] fix cases when asset reserve is remote, add test remote-asset and teleported fee --- polkadot/xcm/pallet-xcm/src/lib.rs | 64 +++----- polkadot/xcm/pallet-xcm/src/tests.rs | 230 +++++++++++++++++++++++++-- 2 files changed, 244 insertions(+), 50 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index a094e9781cdc..99d5d80027c6 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1295,7 +1295,7 @@ impl Pallet { if fee_asset_item as usize >= assets.len() { return Err(Error::::Empty.into()) } - let fees = assets.swap_remove(fee_asset_item as usize); + let mut fees = assets.swap_remove(fee_asset_item as usize); let fees_transfer_type = TransferType::determine_for::(&fees, &dest)?; let assets_transfer_type = if assets.is_empty() { // Single asset to transfer (also used for fees). @@ -1328,34 +1328,31 @@ impl Pallet { // BuyExecution on both chains. Split fees, and deposit half at assets-reserve chain // and half at destination. if let TransferType::RemoteReserve(assets_reserve) = assets_transfer_type { - let (fees_for_reserve, fees_for_dest) = Self::equal_split_asset(&fees)?; + // Halve amount of fees, each half will be sent to one chain. + Self::halve_fungible_asset(&mut fees)?; // Halve weight limit again to be used for the two fees transfers. let quarter_weight_limit = Self::halve_weight_limit(&weight_limit); - let context = T::UniversalLocation::get(); - // Send half the `fees` to the Sovereign Account of `dest` on assets-reserve chain. - let assets_reserve_beneficiary = dest - .reanchored(&assets_reserve, context) - .map_err(|_| Error::::CannotReanchor)?; - Self::prefund_transfer_fees( + // Send half the `fees` to `beneficiary` on assets-reserve chain. + Self::build_and_execute_xcm_transfer_type( origin_location, assets_reserve, - assets_reserve_beneficiary, - fees_for_reserve, + beneficiary, + vec![fees.clone()], + TransferType::determine_for::(&fees, &assets_reserve)?, + fees.clone(), quarter_weight_limit.clone(), )?; - Self::prefund_transfer_fees( + // Send the other half of the `fees` to `beneficiary` on dest chain. + Self::build_and_execute_xcm_transfer_type( origin_location, dest, beneficiary, - fees_for_dest, + vec![fees.clone()], + fees_transfer_type, + fees.clone(), quarter_weight_limit, )?; } else { - if let TransferType::RemoteReserve(_fees_reserve) = fees_transfer_type { - // TODO: change beneficiary on `fee_reserve` to be SA-of-Here. - // But beneficiary on `dest` should stay unchanged... - // Or maybe not required, fees can be used from Holding register, we'll see :D - } // execute fees transfer - have to do it separately than assets because of the // different transfer type (different XCM program required) Self::build_and_execute_xcm_transfer_type( @@ -1418,22 +1415,6 @@ impl Pallet { ) } - /// Teleport or reserve transfer `fees` - not to be used by itself, it is a helper function for - /// prefunding fees for subsequent assets transfer. - /// - /// Fees are allowed to be either teleported or reserve transferred. - fn prefund_transfer_fees( - _origin: impl Into, - _dest: MultiLocation, - _beneficiary: MultiLocation, - _asset: MultiAsset, - _weight_limit: WeightLimit, - ) -> DispatchResult { - // let fee_transfer_type = TransferType::determine_for::(&fee_asset, &dest)?; - // Ok(()) - todo!() - } - fn build_and_execute_xcm_transfer_type( origin: impl Into, dest: MultiLocation, @@ -1919,14 +1900,15 @@ impl Pallet { } } - /// Split fungible `asset` in two equal `MultiAsset`s. - fn equal_split_asset(asset: &MultiAsset) -> Result<(MultiAsset, MultiAsset), Error> { - let half_amount = match &asset.fun { - Fungible(amount) => amount.saturating_div(2), - NonFungible(_) => return Err(Error::::InvalidAsset), - }; - let half = MultiAsset { fun: Fungible(half_amount), id: asset.id }; - Ok((half.clone(), half)) + /// Halve `asset`s fungible amount. + pub(crate) fn halve_fungible_asset(asset: &mut MultiAsset) -> Result<(), Error> { + match &mut asset.fun { + Fungible(amount) => { + *amount = amount.saturating_div(2); + Ok(()) + }, + NonFungible(_) => Err(Error::::InvalidAsset), + } } } diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 1fccafc7ebcf..dca80a14e8c9 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -37,7 +37,7 @@ const ALICE: AccountId = AccountId::new([0u8; 32]); const BOB: AccountId = AccountId::new([1u8; 32]); const INITIAL_BALANCE: u128 = 100; const SEND_AMOUNT: u128 = 10; -const FEE_AMOUNT: u128 = 1; +const FEE_AMOUNT: u128 = 2; #[test] fn report_outcome_notify_works() { @@ -1045,9 +1045,9 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works assert_eq!(expected_asset.id, MultiLocation::here().into()); // reanchor according to test-case. - let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); - expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); + let mut expected_fee_on_reserve = expected_fee.clone(); + expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); expected_fee.reanchor(&dest, context).unwrap(); expected_asset.reanchor(&dest, context).unwrap(); @@ -1213,9 +1213,9 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); // reanchor according to test-case. - let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); - expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); + let mut expected_fee_on_reserve = expected_fee.clone(); + expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); expected_fee.reanchor(&dest, context).unwrap(); expected_asset.reanchor(&dest, context).unwrap(); @@ -1632,7 +1632,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { /// Test `reserve_transfer_assets` with destination asset reserve and teleported fee. /// -/// Transferring native asset (local reserve) to `FOREIGN_ASSET_RESERVE_PARA_ID`. Using +/// Transferring foreign asset (destination reserve) to `FOREIGN_ASSET_RESERVE_PARA_ID`. Using /// teleport-trusted USDT for fees. /// /// ```nocompile @@ -1816,11 +1816,223 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor /// Test `reserve_transfer_assets` with remote asset reserve and teleported fee. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to `USDT_PARA_ID`. Using +/// teleport-trusted USDT for fees. +/// +/// ```nocompile +/// | chain `A` | chain `C` | chain `B` +/// | Here (source) | FOREIGN_ASSET_RESERVE_PARA_ID | USDT_PARA_ID (destination) +/// | | `assets` reserve | `fees` (USDT) teleport-trust +/// | +/// | 1. `A` executes `InitiateTeleport(fees)` dest `C` +/// | \----------> `C` executes `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)` +/// | +/// | 2. `A` executes `InitiateTeleport(fees)` dest `B` +/// | \-------------------------------------------------> `B` executes: +/// | `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)` +/// | +/// | 3. `A` executes `InitiateReserveWithdraw(assets)` dest `B` +/// | --------------------------------------------------> `DepositAsset(assets)` +/// ``` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() { - // TODO + let usdt_chain = RelayLocation::get().pushed_with_interior(Parachain(USDT_PARA_ID)).unwrap(); + let usdt_chain_sovereign_account = SovereignAccountOf::convert_location(&usdt_chain).unwrap(); + let usdt_id_multilocation = usdt_chain; + let usdt_initial_local_amount = 42; + + let reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) + .unwrap(); + let foreign_asset_id_multilocation = + reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); + let foreign_asset_initial_amount = 142; + let reserve_sovereign_account = + SovereignAccountOf::convert_location(&reserve_location).unwrap(); + + // transfer destination is USDT chain (foreign asset needs to go through its reserve chain) + let dest = usdt_chain; + let assets: MultiAssets = vec![ + // USDT for fees (is sufficient on local chain too) + (usdt_id_multilocation, FEE_AMOUNT).into(), + // foreign asset to transfer (not used for fees) - remote reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ] + .into(); + let fee_index = 0; + let asset_index = 1; + + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + + // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. + assert_eq!(expected_fee.id, usdt_id_multilocation.into()); + assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); + + // reanchor according to test-case. + let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); + let mut expected_fee_on_reserve = expected_fee.clone(); + let mut expected_asset_on_reserve = expected_asset.clone(); + expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); + expected_asset_on_reserve.reanchor(&reserve_location, context).unwrap(); + expected_fee.reanchor(&dest, context).unwrap(); + expected_asset.reanchor(&dest, context).unwrap(); + + // fees are split between the asset-reserve chain and the destination chain + crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); + crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); + + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (usdt_chain_sovereign_account.clone(), INITIAL_BALANCE), + (reserve_sovereign_account.clone(), INITIAL_BALANCE), + ]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + let expected_beneficiary_on_reserve = beneficiary; + + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient foreign asset USDT (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + usdt_id_multilocation, + BOB, + true, + 1 + )); + // USDT should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + usdt_id_multilocation, + ALICE, + usdt_initial_local_amount + )); + // create non-sufficient foreign asset BLA (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + false, + 1 + )); + // foreign asset BLA should have been teleported/reserve-transferred in, but for this test + // we just mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_initial_amount + )); + assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice native asset untouched + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + // Alice spent USDT for fees + assert_eq!( + Assets::balance(usdt_id_multilocation, ALICE), + usdt_initial_local_amount - FEE_AMOUNT + ); + // Alice transferred BLA + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_initial_amount - SEND_AMOUNT + ); + // Verify balances of USDT reserve parachain + assert_eq!(Balances::free_balance(usdt_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); + // Verify balances of transferred-asset reserve parachain + assert_eq!(Balances::free_balance(reserve_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, reserve_sovereign_account), 0); + // Verify total and active issuance of USDT have decreased (teleported) + assert_eq!( + Assets::total_issuance(usdt_id_multilocation), + usdt_initial_local_amount - FEE_AMOUNT + ); + assert_eq!( + Assets::active_issuance(usdt_id_multilocation), + usdt_initial_local_amount - FEE_AMOUNT + ); + // Verify total and active issuance of foreign BLA asset have decreased (reserve-based + // (local-instance) asset was burned) + assert_eq!( + Assets::total_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); + assert_eq!( + Assets::active_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![ + ( + // first message is to prefund fees on `reserve` + reserve_location, + // fees are teleported to reserve chain + Xcm(vec![ + ReceiveTeleportedAsset(expected_fee_on_reserve.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee_on_reserve.clone(), Unlimited), + DepositAsset { + assets: AllCounted(1).into(), + beneficiary: expected_beneficiary_on_reserve + }, + ]) + ), + ( + // second message is to prefund fees on `dest` + dest, + // fees are teleported to destination chain + Xcm(vec![ + ReceiveTeleportedAsset(expected_fee.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee.clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ), + ( + // third message is to transfer/deposit foreign assets on `dest` by going + // through `reserve` while paying using prefunded (teleported above) fees + reserve_location, + Xcm(vec![ + WithdrawAsset(expected_asset_on_reserve.into()), + ClearOrigin, + buy_limited_execution(expected_fee_on_reserve, Unlimited), + DepositReserveAsset { + assets: Wild(AllCounted(1)), + // final destination is `dest` as seen by `reserve` + dest: expected_dest_on_reserve, + // message sent onward to final `dest` to deposit/prefund fees + xcm: Xcm(vec![ + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary } + ]) + } + ]) + ) + ] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test local execution of XCM From 7b920ec767d3fb3f1c46bc9eb589d90dc4acfcc3 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 28 Sep 2023 17:08:57 +0300 Subject: [PATCH 023/124] add test for transfer asset remote reserve and fee local reserve --- polkadot/xcm/pallet-xcm/src/tests.rs | 212 +++++++++++++++++++++++++-- 1 file changed, 202 insertions(+), 10 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index dca80a14e8c9..4806b1419d36 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -688,9 +688,9 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ ( // first message is to prefund fees on `dest` dest, + // fees are being sent through local-reserve transfer because fee reserve is + // local chain Xcm(vec![ - // fees are being sent through local-reserve transfer because fee reserve - // is local chain ReserveAssetDeposited((Parent, FEE_AMOUNT).into()), ClearOrigin, buy_limited_execution((Parent, FEE_AMOUNT), Unlimited), @@ -718,11 +718,201 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ /// Test `reserve_transfer_assets` with remote asset reserve and local fee reserve. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to `OTHER_PARA_ID`. +/// Using native (local reserve) as fee. +/// +/// ```nocompile +/// | chain `A` | chain `C` | chain `B` +/// | Here (source) | FOREIGN_ASSET_RESERVE_PARA_ID | OTHER_PARA_ID (destination) +/// | `fees` reserve | `assets` reserve | no trust +/// | +/// | 1. `A` executes `TransferReserveAsset(fees)` dest `C` +/// | \----------> `C` executes `WithdrawAsset(fees), .., DepositAsset(fees)` +/// | +/// | 2. `A` executes `TransferReserveAsset(fees)` dest `B` +/// | \-------------------------------------------------> `B` executes: +/// | `WithdrawAsset(fees), .., DepositAsset(fees)` +/// | +/// | 3. `A` executes `InitiateReserveWithdraw(assets)` dest `C` +/// | -----------------> `C` executes `DepositReserveAsset(assets)` dest `B` +/// | --------------------------> `DepositAsset(assets)` +/// | all of which at step 3. being paid with fees prefunded in steps 1 & 2 +/// ``` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works() { - // TODO + let reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) + .unwrap(); + let foreign_asset_id_multilocation = + reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); + let foreign_asset_initial_amount = 142; + let reserve_sovereign_account = + SovereignAccountOf::convert_location(&reserve_location).unwrap(); + + // transfer destination is OTHER_PARA_ID (foreign asset needs to go through its reserve chain) + let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); + let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); + + let assets: MultiAssets = vec![ + // native asset for fees + (MultiLocation::here(), FEE_AMOUNT).into(), + // foreign asset to transfer (not used for fees) - remote reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ] + .into(); + let fee_index = 0; + let asset_index = 1; + + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + + // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. + assert_eq!(expected_fee.id, MultiLocation::here().into()); + assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); + + // reanchor according to test-case. + let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); + let mut expected_fee_on_reserve = expected_fee.clone(); + let mut expected_asset_on_reserve = expected_asset.clone(); + expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); + expected_asset_on_reserve.reanchor(&reserve_location, context).unwrap(); + expected_fee.reanchor(&dest, context).unwrap(); + expected_asset.reanchor(&dest, context).unwrap(); + + // fees are split between the asset-reserve chain and the destination chain + crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); + crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); + + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (dest_sovereign_account.clone(), INITIAL_BALANCE), + (reserve_sovereign_account.clone(), INITIAL_BALANCE), + ]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + let expected_beneficiary_on_reserve = beneficiary; + + new_test_ext_with_balances(balances).execute_with(|| { + // create non-sufficient foreign asset BLA (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + false, + 1 + )); + // foreign asset BLA should have been teleported/reserve-transferred in, but for this test + // we just mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_initial_amount + )); + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_initial_amount + ); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice transferred BLA + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_initial_amount - SEND_AMOUNT + ); + // Alice spent native asset for fees + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - FEE_AMOUNT); + // Half the fee went to reserve chain + assert_eq!( + Balances::free_balance(reserve_sovereign_account.clone()), + INITIAL_BALANCE + FEE_AMOUNT / 2 + ); + // Other half went to dest chain + assert_eq!( + Balances::free_balance(dest_sovereign_account.clone()), + INITIAL_BALANCE + FEE_AMOUNT / 2 + ); + // Verify total and active issuance of foreign BLA asset have decreased (reserve-based + // (local-instance) asset was burned) + assert_eq!( + Assets::total_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); + assert_eq!( + Assets::active_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![ + ( + // first message is to prefund fees on `reserve` + reserve_location, + // fees are being sent through local-reserve transfer because fee reserve is + // local chain + Xcm(vec![ + ReserveAssetDeposited(expected_fee_on_reserve.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee_on_reserve.clone(), Unlimited), + DepositAsset { + assets: AllCounted(1).into(), + beneficiary: expected_beneficiary_on_reserve + }, + ]) + ), + ( + // second message is to prefund fees on `dest` + dest, + // fees are being sent through local-reserve transfer because fee reserve + // is local chain + Xcm(vec![ + ReserveAssetDeposited(expected_fee.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee.clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ), + ( + // third message is to transfer/deposit foreign assets on `dest` by going + // through `reserve` while paying using prefunded (teleported above) fees + reserve_location, + Xcm(vec![ + WithdrawAsset(expected_asset_on_reserve.into()), + ClearOrigin, + buy_limited_execution(expected_fee_on_reserve, Unlimited), + DepositReserveAsset { + assets: Wild(AllCounted(1)), + // final destination is `dest` as seen by `reserve` + dest: expected_dest_on_reserve, + // message sent onward to final `dest` to deposit/prefund fees + xcm: Xcm(vec![ + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary } + ]) + } + ]) + ) + ] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with local asset reserve and destination fee reserve. @@ -1005,7 +1195,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve /// | `assets` reserve | `fees` reserve | /// | /// | 1. `A` executes `InitiateReserveWithdraw(fees)` dest `C` -/// | -----------------> `DepositReserveAsset(fees)` dest `B` +/// | -----------------> `C` executes `DepositReserveAsset(fees)` dest `B` /// | --------------------------> `DepositAsset(fees)` /// | 2. `A` executes `TransferReserveAsset(assets)` dest `B` /// | --------------------------------------------------> `ReserveAssetDeposited(assets)` @@ -1167,7 +1357,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works /// | | `fees` reserve | `assets` reserve /// | /// | 1. `A` executes `InitiateReserveWithdraw(fees)` dest `C` -/// | -----------------> `DepositReserveAsset(fees)` dest `B` +/// | -----------------> `C` executes `DepositReserveAsset(fees)` dest `B` /// | --------------------------> `DepositAsset(fees)` /// | 2. `A` executes `InitiateReserveWithdraw(assets)` dest `B` /// | --------------------------------------------------> `DepositAsset(assets)` @@ -1370,7 +1560,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve /// | | `assets` reserve | /// | /// | 1. `A` executes `InitiateReserveWithdraw(both)` dest `C` -/// | -----------------> `DepositReserveAsset(both)` dest `B` +/// | -----------------> `C` executes `DepositReserveAsset(both)` dest `B` /// | --------------------------> `DepositAsset(both)` /// ``` #[test] @@ -1831,8 +2021,10 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor /// | \-------------------------------------------------> `B` executes: /// | `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)` /// | -/// | 3. `A` executes `InitiateReserveWithdraw(assets)` dest `B` -/// | --------------------------------------------------> `DepositAsset(assets)` +/// | 3. `A` executes `InitiateReserveWithdraw(assets)` dest `C` +/// | -----------------> `C` executes `DepositReserveAsset(assets)` dest `B` +/// | --------------------------> `DepositAsset(assets)` +/// | all of which at step 3. being paid with fees prefunded in steps 1 & 2 /// ``` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() { From 313056631641d06879973fac9a837e319a383afa Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 28 Sep 2023 17:47:13 +0300 Subject: [PATCH 024/124] add test for transfer asset remote reserve and fee destination reserve --- polkadot/xcm/pallet-xcm/src/tests.rs | 259 ++++++++++++++++++++++++--- 1 file changed, 236 insertions(+), 23 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 4806b1419d36..80a08011ab59 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -670,8 +670,8 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), 0 ); - // Verify total and active issuance of foreign BLA have decreased (reserve-based - // (local-instance) BLA was burned) + // Verify total and active issuance of foreign BLA have decreased (burned on + // reserve-withdraw) assert_eq!( Assets::total_issuance(foreign_asset_id_multilocation), foreign_asset_amount - SEND_AMOUNT @@ -846,8 +846,8 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works Balances::free_balance(dest_sovereign_account.clone()), INITIAL_BALANCE + FEE_AMOUNT / 2 ); - // Verify total and active issuance of foreign BLA asset have decreased (reserve-based - // (local-instance) asset was burned) + // Verify total and active issuance of foreign BLA asset have decreased (burned on + // reserve-withdraw) assert_eq!( Assets::total_issuance(foreign_asset_id_multilocation), foreign_asset_initial_amount - SEND_AMOUNT @@ -1017,8 +1017,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ INITIAL_BALANCE + SEND_AMOUNT ); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); - // Verify total and active issuance of USDC have decreased (reserve-based (local-instance) - // USDC was burned) + // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) assert_eq!( Assets::total_issuance(usdc_id_multilocation), usdc_initial_local_amount - FEE_AMOUNT @@ -1146,8 +1145,8 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), 0 ); - // Verify total and active issuance of foreign BLA have decreased (reserve-based - // (local-instance) BLA was burned) + // Verify total and active issuance of foreign BLA have decreased (burned on + // reserve-withdraw) assert_eq!( Assets::total_issuance(foreign_asset_id_multilocation), foreign_asset_amount - SEND_AMOUNT @@ -1177,11 +1176,228 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re /// Test `reserve_transfer_assets` with remote asset reserve and destination fee reserve. /// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the correct message is sent and event is emitted. +/// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to +/// `USDC_RESERVE_PARA_ID`. Using USDC (destination reserve) as fee. +/// +/// ```nocompile +/// | chain `A` | chain `C` | chain `B` +/// | Here (source) | FOREIGN_ASSET_RESERVE_PARA_ID | USDC_RESERVE_PARA_ID (destination) +/// | | `assets` reserve | `fees` reserve +/// +/// 1. `A` executes `InitiateReserveWithdraw(fees)` dest `B` +/// ---------------------------------------------------> `B` executes: +/// `WithdrawAsset(fees), ClearOrigin` +/// `BuyExecution(fees)` +/// `DepositReserveAsset(fees)` dest `C` +/// `C` executes `DepositAsset(fees)` <---------------------------- +/// +/// 2. `A` executes `InitiateReserveWithdraw(fees)` dest `B` +/// ---------------------------------------------------> `B` executes: +/// `WithdrawAsset(fees), .., DepositAsset(fees)` +/// +/// 3. `A` executes `InitiateReserveWithdraw(assets)` dest `C` +/// --------------> `C` executes `DepositReserveAsset(assets)` dest `B` +/// ----------------------------> `B` executes: +/// WithdrawAsset(assets), .., DepositAsset(assets)` +/// +/// all of which at step 3. being paid with fees prefunded in steps 1 & 2 +/// ``` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve_works() { - // TODO + let usdc_chain = RelayLocation::get() + .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) + .unwrap(); + let usdc_id_multilocation = usdc_chain.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); + let usdc_initial_local_amount = 42; + + let reserve_location = RelayLocation::get() + .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) + .unwrap(); + let foreign_asset_id_multilocation = + reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); + let foreign_asset_initial_amount = 142; + + // transfer destination is USDC chain (foreign asset needs to go through its reserve chain) + let dest = usdc_chain; + let assets: MultiAssets = vec![ + // foreign asset to transfer (not used for fees) - remote reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + // USDC for fees (is sufficient on local chain too) + (usdc_id_multilocation, FEE_AMOUNT).into(), + ] + .into(); + let asset_index = 0; + let fee_index = 1; + + let context = UniversalLocation::get(); + let mut expected_fee = assets.get(fee_index).unwrap().clone(); + let mut expected_asset = assets.get(asset_index).unwrap().clone(); + + // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. + assert_eq!(expected_fee.id, usdc_id_multilocation.into()); + assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); + + // reanchor according to test-case. + let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); + let expected_reserve_on_dest = reserve_location.reanchored(&dest, context).unwrap(); + let mut expected_fee_on_reserve = expected_fee.clone(); + let mut expected_asset_on_reserve = expected_asset.clone(); + expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); + expected_asset_on_reserve.reanchor(&reserve_location, context).unwrap(); + expected_fee.reanchor(&dest, context).unwrap(); + expected_asset.reanchor(&dest, context).unwrap(); + + // fees are split between the asset-reserve chain and the destination chain + crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); + crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); + + let balances = vec![(ALICE, INITIAL_BALANCE)]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient foreign asset USDC (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + usdc_id_multilocation, + BOB, + true, + 1 + )); + // USDC should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + usdc_id_multilocation, + ALICE, + usdc_initial_local_amount + )); + // create non-sufficient foreign asset BLA (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + false, + 1 + )); + // foreign asset BLA should have been teleported/reserve-transferred in, but for this test + // we just mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + foreign_asset_initial_amount + )); + assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + // do the transfer + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + )); + assert!(matches!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + )); + // Alice native asset untouched + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + // Alice spent USDC for fees + assert_eq!( + Assets::balance(usdc_id_multilocation, ALICE), + usdc_initial_local_amount - FEE_AMOUNT + ); + // Alice transferred BLA + assert_eq!( + Assets::balance(foreign_asset_id_multilocation, ALICE), + foreign_asset_initial_amount - SEND_AMOUNT + ); + // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) + assert_eq!( + Assets::total_issuance(usdc_id_multilocation), + usdc_initial_local_amount - FEE_AMOUNT + ); + assert_eq!( + Assets::active_issuance(usdc_id_multilocation), + usdc_initial_local_amount - FEE_AMOUNT + ); + // Verify total and active issuance of foreign BLA asset have decreased (burned on + // reserve-withdraw) + assert_eq!( + Assets::total_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); + assert_eq!( + Assets::active_issuance(foreign_asset_id_multilocation), + foreign_asset_initial_amount - SEND_AMOUNT + ); + + // Verify sent XCM program + assert_eq!( + sent_xcm(), + vec![ + ( + // first message is to prefund fees on `reserve`, but we need to go through + // `fee_reserve == dest` to get them there + dest, + // fees are reserve-withdrawn on `dest` chain then reserve-deposited to + // `asset_reserve` chain + Xcm(vec![ + WithdrawAsset(expected_fee.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee.clone(), Unlimited), + DepositReserveAsset { + assets: Wild(AllCounted(1)), + // final fees destination is `asset_reserve` as seen by `dest` + dest: expected_reserve_on_dest, + // message sent onward to final `dest` to deposit/prefund fees + xcm: Xcm(vec![ + buy_limited_execution(expected_fee_on_reserve.clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary } + ]) + } + ]) + ), + ( + // second message is to prefund fees on `dest` + dest, + // fees are reserve-withdrawn on destination chain + Xcm(vec![ + WithdrawAsset(expected_fee.clone().into()), + ClearOrigin, + buy_limited_execution(expected_fee.clone(), Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary }, + ]) + ), + ( + // third message is to transfer/deposit foreign assets on `dest` by going + // through `reserve` while paying using prefunded (teleported above) fees + reserve_location, + Xcm(vec![ + WithdrawAsset(expected_asset_on_reserve.into()), + ClearOrigin, + buy_limited_execution(expected_fee_on_reserve, Unlimited), + DepositReserveAsset { + assets: Wild(AllCounted(1)), + // final destination is `dest` as seen by `reserve` + dest: expected_dest_on_reserve, + // message sent onward to final `dest` to deposit/prefund fees + xcm: Xcm(vec![ + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(1).into(), beneficiary } + ]) + } + ]) + ) + ] + ); + let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); + let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); + }); } /// Test `reserve_transfer_assets` with local asset reserve and remote fee reserve. @@ -1291,8 +1507,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); // Sovereign account of destination parachain holds `SEND_AMOUNT` in local reserve assert_eq!(Balances::free_balance(dest_sovereign_account), SEND_AMOUNT); - // Verify total and active issuance of USDC have decreased (reserve-based (local-instance) - // USDC was burned) + // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) assert_eq!( Assets::total_issuance(usdc_id_multilocation), usdc_initial_local_amount - FEE_AMOUNT @@ -1484,8 +1699,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve // Verify balances of transferred-asset reserve parachain assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), INITIAL_BALANCE); assert_eq!(Assets::balance(foreign_asset_id_multilocation, dest_sovereign_account), 0); - // Verify total and active issuance of USDC have decreased (reserve-based (local-instance) - // USDC was burned) + // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) assert_eq!( Assets::total_issuance(usdc_id_multilocation), usdc_initial_local_amount - FEE_AMOUNT @@ -1494,8 +1708,8 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve Assets::active_issuance(usdc_id_multilocation), usdc_initial_local_amount - FEE_AMOUNT ); - // Verify total and active issuance of foreign BLA asset have decreased (reserve-based - // (local-instance) asset was burned) + // Verify total and active issuance of foreign BLA asset have decreased (burned on + // reserve-withdraw) assert_eq!( Assets::total_issuance(foreign_asset_id_multilocation), foreign_asset_initial_amount - SEND_AMOUNT @@ -1635,8 +1849,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work // Destination account (parachain account) has expected (same) balances assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), INITIAL_BALANCE); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); - // Verify total and active issuance of USDC have decreased (reserve-based (local-instance) - // USDC was burned) + // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) assert_eq!( Assets::total_issuance(usdc_id_multilocation), usdc_initial_local_amount - SEND_AMOUNT @@ -1959,8 +2172,8 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor Assets::active_issuance(usdt_id_multilocation), usdt_initial_local_amount - FEE_AMOUNT ); - // Verify total and active issuance of foreign BLA asset have decreased (reserve-based - // (local-instance) asset was burned) + // Verify total and active issuance of foreign BLA asset have decreased (burned on + // reserve-withdraw) assert_eq!( Assets::total_issuance(foreign_asset_id_multilocation), foreign_asset_initial_amount - SEND_AMOUNT @@ -2160,8 +2373,8 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() Assets::active_issuance(usdt_id_multilocation), usdt_initial_local_amount - FEE_AMOUNT ); - // Verify total and active issuance of foreign BLA asset have decreased (reserve-based - // (local-instance) asset was burned) + // Verify total and active issuance of foreign BLA asset have decreased (burned on + // reserve-withdraw) assert_eq!( Assets::total_issuance(foreign_asset_id_multilocation), foreign_asset_initial_amount - SEND_AMOUNT From 1b17e844391a1ead91870e5357e96ca235f77951 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 29 Sep 2023 09:40:36 +0300 Subject: [PATCH 025/124] disallow teleportable assets in reserve-transfer, add regression test --- polkadot/xcm/pallet-xcm/src/lib.rs | 3 +- polkadot/xcm/pallet-xcm/src/tests.rs | 73 +++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 99d5d80027c6..832e630e637d 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1298,7 +1298,8 @@ impl Pallet { let mut fees = assets.swap_remove(fee_asset_item as usize); let fees_transfer_type = TransferType::determine_for::(&fees, &dest)?; let assets_transfer_type = if assets.is_empty() { - // Single asset to transfer (also used for fees). + // Single asset to transfer (one used for fees where transfer type is determined above). + ensure!(fees_transfer_type != TransferType::Teleport, Error::::Filtered); fees_transfer_type } else { // Find reserve for non-fee assets. diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 80a08011ab59..c6899f129668 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -25,7 +25,10 @@ use frame_support::{ weights::Weight, }; use polkadot_parachain_primitives::primitives::Id as ParaId; -use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash}; +use sp_runtime::{ + traits::{AccountIdConversion, BlakeTwo256, Hash}, + DispatchError, ModuleError, +}; use xcm::{latest::QueryResponseInfo, prelude::*}; use xcm_builder::AllowKnownQueryResponses; use xcm_executor::{ @@ -2217,6 +2220,74 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor }); } +/// Test `reserve_transfer_assets` single asset which is also teleportable - should fail. +/// +/// Attempting to reserve-transfer teleport-trusted USDT to `USDT_PARA_ID` should fail. +#[test] +fn reserve_transfer_assets_with_teleportable_asset_fails() { + let usdt_chain = RelayLocation::get().pushed_with_interior(Parachain(USDT_PARA_ID)).unwrap(); + let usdt_chain_sovereign_account = SovereignAccountOf::convert_location(&usdt_chain).unwrap(); + let usdt_id_multilocation = usdt_chain; + let usdt_initial_local_amount = 42; + + // transfer destination is USDT chain (foreign asset needs to go through its reserve chain) + let dest = usdt_chain; + let assets: MultiAssets = vec![(usdt_id_multilocation, FEE_AMOUNT).into()].into(); + let fee_index = 0; + + let balances = vec![(ALICE, INITIAL_BALANCE)]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient foreign asset USDT (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + usdt_id_multilocation, + BOB, + true, + 1 + )); + // USDT should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + usdt_id_multilocation, + ALICE, + usdt_initial_local_amount + )); + assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + // do the transfer + let res = XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + ); + assert_eq!( + res, + Err(DispatchError::Module(ModuleError { + index: 4, + error: [2, 0, 0, 0], + message: Some("Filtered") + })) + ); + // Alice native asset is still same + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + // Alice USDT balance is still same + assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); + // No USDT moved to sovereign account of reserve parachain + assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); + // Verify total and active issuance of USDT are still the same + assert_eq!(Assets::total_issuance(usdt_id_multilocation), usdt_initial_local_amount); + assert_eq!(Assets::active_issuance(usdt_id_multilocation), usdt_initial_local_amount); + }); +} + /// Test `reserve_transfer_assets` with remote asset reserve and teleported fee. /// /// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to `USDT_PARA_ID`. Using From 84e213a68db0fe7d0f2bf0cc99dfd3bc47c429f9 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 29 Sep 2023 17:16:34 +0300 Subject: [PATCH 026/124] asset-hubs: fix emulated tests and deduplicate code --- .../src/tests/reserve_transfer.rs | 258 ++++++------------ cumulus/xcm/xcm-emulator/src/lib.rs | 10 +- 2 files changed, 92 insertions(+), 176 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs index 491343692e9f..d0af568929cf 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -15,37 +15,6 @@ use crate::*; -fn relay_origin_assertions(t: RelayToSystemParaTest) { - type RuntimeEvent = ::RuntimeEvent; - - Westend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(629_384_000, 6_196))); - - assert_expected_events!( - Westend, - vec![ - // Amount to reserve transfer is transferred to System Parachain's Sovereign account - RuntimeEvent::Balances(pallet_balances::Event::Transfer { from, to, amount }) => { - from: *from == t.sender.account_id, - to: *to == Westend::sovereign_account_id_of( - t.args.dest - ), - amount: *amount == t.args.amount, - }, - ] - ); -} - -fn system_para_dest_assertions_incomplete(_t: RelayToSystemParaTest) { - AssetHubWestend::assert_dmp_queue_incomplete( - Some(Weight::from_parts(1_000_000_000, 0)), - Some(Error::UntrustedReserveLocation), - ); -} - -fn system_para_to_relay_assertions(_t: SystemParaToRelayTest) { - AssetHubWestend::assert_xcm_pallet_attempted_error(Some(XcmError::Barrier)) -} - fn system_para_to_para_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -97,48 +66,6 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { ); } -fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult { - ::XcmPallet::limited_reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - t.args.weight_limit, - ) -} - -fn relay_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult { - ::XcmPallet::reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - ) -} - -fn system_para_limited_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - t.args.weight_limit, - ) -} - -fn system_para_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult { - ::PolkadotXcm::reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - ) -} - fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, @@ -160,123 +87,112 @@ fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> Dispa ) } +fn do_reserve_transfer_native_asset_from_relay_to_system_para_fails(limited: bool) { + let signed_origin = ::RuntimeOrigin::signed(WestendSender::get().into()); + let destination = Westend::child_location_of(AssetHubWestend::para_id()); + let beneficiary: MultiLocation = + AccountId32Junction { network: None, id: AssetHubWestendReceiver::get().into() }.into(); + let amount_to_send: Balance = WESTEND_ED * 1000; + let assets: MultiAssets = (Here, amount_to_send).into(); + let fee_asset_item = 0; + + // this should fail + Westend::execute_with(|| { + let result = if limited { + ::XcmPallet::reserve_transfer_assets( + signed_origin, + bx!(destination.into()), + bx!(beneficiary.into()), + bx!(assets.into()), + fee_asset_item, + ) + } else { + ::XcmPallet::limited_reserve_transfer_assets( + signed_origin, + bx!(destination.into()), + bx!(beneficiary.into()), + bx!(assets.into()), + fee_asset_item, + WeightLimit::Unlimited, + ) + }; + assert_err!( + result, + DispatchError::Module(sp_runtime::ModuleError { + index: 99, + error: [2, 0, 0, 0], + message: Some("Filtered") + }) + ); + }); +} + /// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't /// work #[test] fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() { - // Init values for Relay Chain - let amount_to_send: Balance = WESTEND_ED * 1000; - let test_args = TestContext { - sender: WestendSender::get(), - receiver: AssetHubWestendReceiver::get(), - args: relay_test_args(amount_to_send), - }; - - let mut test = RelayToSystemParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(relay_origin_assertions); - test.set_assertion::(system_para_dest_assertions_incomplete); - test.set_dispatchable::(relay_limited_reserve_transfer_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - assert_eq!(sender_balance_before - amount_to_send, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); + do_reserve_transfer_native_asset_from_relay_to_system_para_fails(true); } -/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work +/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work #[test] -fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() { +fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { + do_reserve_transfer_native_asset_from_relay_to_system_para_fails(false); +} + +fn do_reserve_transfer_native_asset_from_system_para_to_relay_fails(limited: bool) { // Init values for System Parachain + let signed_origin = + ::RuntimeOrigin::signed(AssetHubWestendSender::get().into()); let destination = AssetHubWestend::parent_location(); let beneficiary_id = WestendReceiver::get(); + let beneficiary: MultiLocation = + AccountId32Junction { network: None, id: beneficiary_id.into() }.into(); let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000; - let assets = (Parent, amount_to_send).into(); - - let test_args = TestContext { - sender: AssetHubWestendSender::get(), - receiver: WestendReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), - }; - - let mut test = SystemParaToRelayTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(system_para_to_relay_assertions); - test.set_dispatchable::(system_para_limited_reserve_transfer_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - assert_eq!(sender_balance_before, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); + let assets: MultiAssets = (Parent, amount_to_send).into(); + let fee_asset_item = 0; + + // this should fail + AssetHubWestend::execute_with(|| { + let result = if limited { + ::PolkadotXcm::reserve_transfer_assets( + signed_origin, + bx!(destination.into()), + bx!(beneficiary.into()), + bx!(assets.into()), + fee_asset_item, + ) + } else { + ::PolkadotXcm::limited_reserve_transfer_assets( + signed_origin, + bx!(destination.into()), + bx!(beneficiary.into()), + bx!(assets.into()), + fee_asset_item, + WeightLimit::Unlimited, + ) + }; + assert_err!( + result, + DispatchError::Module(sp_runtime::ModuleError { + index: 31, + error: [2, 0, 0, 0], + message: Some("Filtered") + }) + ); + }); } -/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work +/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work #[test] -fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { - // Init values for Relay Chain - let amount_to_send: Balance = WESTEND_ED * 1000; - let test_args = TestContext { - sender: WestendSender::get(), - receiver: AssetHubWestendReceiver::get(), - args: relay_test_args(amount_to_send), - }; - - let mut test = RelayToSystemParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(relay_origin_assertions); - test.set_assertion::(system_para_dest_assertions_incomplete); - test.set_dispatchable::(relay_reserve_transfer_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - assert_eq!(sender_balance_before - amount_to_send, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); +fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() { + do_reserve_transfer_native_asset_from_system_para_to_relay_fails(true); } /// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work #[test] fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { - // Init values for System Parachain - let destination = AssetHubWestend::parent_location(); - let beneficiary_id = WestendReceiver::get(); - let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000; - let assets = (Parent, amount_to_send).into(); - - let test_args = TestContext { - sender: AssetHubWestendSender::get(), - receiver: WestendReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), - }; - - let mut test = SystemParaToRelayTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(system_para_to_relay_assertions); - test.set_dispatchable::(system_para_reserve_transfer_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - assert_eq!(sender_balance_before, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); + do_reserve_transfer_native_asset_from_system_para_to_relay_fails(false); } /// Limited Reserve Transfers of native asset from System Parachain to Parachain should work diff --git a/cumulus/xcm/xcm-emulator/src/lib.rs b/cumulus/xcm/xcm-emulator/src/lib.rs index 9fda0632bae4..ce1b6329fb2c 100644 --- a/cumulus/xcm/xcm-emulator/src/lib.rs +++ b/cumulus/xcm/xcm-emulator/src/lib.rs @@ -1332,14 +1332,14 @@ pub struct TestContext { pub args: T, } -/// Struct that help with tests where either dispatchables or assertions need +/// Struct that helps with tests where either dispatchables or assertions need /// to be reused. The struct keeps the test's arguments of your choice in the generic `Args`. /// These arguments can be easily reused and shared between the assertions functions /// and dispatchables functions, which are also stored in `Test`. /// `Origin` corresponds to the chain where the XCM interaction starts with an initial execution. -/// `Destination` corresponds to the last chain where an effect of the intial execution is expected -/// happen. `Hops` refer all the ordered intermediary chains an initial XCM execution can provoke -/// some effect. +/// `Destination` corresponds to the last chain where an effect of the initial execution is expected +/// to happen. `Hops` refer to all the ordered intermediary chains an initial XCM execution can +/// provoke some effect on. #[derive(Clone)] pub struct Test where @@ -1393,7 +1393,7 @@ where let chain_name = std::any::type_name::(); self.hops_assertion.insert(chain_name.to_string(), assertion); } - /// Stores an assertion in a particular Chain + /// Stores a dispatchable in a particular Chain pub fn set_dispatchable(&mut self, dispatchable: fn(Self) -> DispatchResult) { let chain_name = std::any::type_name::(); self.hops_dispatchable.insert(chain_name.to_string(), dispatchable); From ce00c285ba34192084bb3f4d5c67a7afff95906f Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 29 Sep 2023 17:40:06 +0300 Subject: [PATCH 027/124] asset-hubs: use non-system para IDs in tests where non-system paras are intended --- .../assets/asset-hub-kusama/tests/tests.rs | 4 ++-- .../assets/asset-hub-polkadot/tests/tests.rs | 4 ++-- .../assets/asset-hub-westend/tests/tests.rs | 4 ++-- .../runtimes/assets/test-utils/src/test_cases.rs | 15 ++++++++------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs index b8e59966b641..cdd4290770fd 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs @@ -629,8 +629,8 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p ); #[test] -fn reserve_transfer_native_asset_works() { - asset_test_utils::test_cases::reserve_transfer_native_asset_works::< +fn reserve_transfer_native_asset_to_non_teleport_para_works() { + asset_test_utils::test_cases::reserve_transfer_native_asset_to_non_teleport_para_works::< Runtime, AllPalletsWithoutSystem, XcmConfig, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs index b232a1703302..b7e44646ece7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs @@ -654,8 +654,8 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p ); #[test] -fn reserve_transfer_native_asset_works() { - asset_test_utils::test_cases::reserve_transfer_native_asset_works::< +fn reserve_transfer_native_asset_to_non_teleport_para_works() { + asset_test_utils::test_cases::reserve_transfer_native_asset_to_non_teleport_para_works::< Runtime, AllPalletsWithoutSystem, XcmConfig, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index 66ae2fe09aa4..5502ebc1e47f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -662,8 +662,8 @@ fn plain_receive_teleported_asset_works() { } #[test] -fn reserve_transfer_native_asset_works() { - asset_test_utils::test_cases::reserve_transfer_native_asset_works::< +fn reserve_transfer_native_asset_to_non_teleport_para_works() { + asset_test_utils::test_cases::reserve_transfer_native_asset_to_non_teleport_para_works::< Runtime, AllPalletsWithoutSystem, XcmConfig, diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 4b5350f0e2aa..9ac68e2fbddf 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -201,10 +201,10 @@ pub fn teleports_for_native_asset_works< ); } - // 3. try to teleport assets away to other parachain (1234): should not work as we don't - // trust `IsTeleporter` for `(relay-native-asset, para(1234))` pair + // 3. try to teleport assets away to other parachain (2345): should not work as we don't + // trust `IsTeleporter` for `(relay-native-asset, para(2345))` pair { - let other_para_id = 1234; + let other_para_id = 2345; let dest = MultiLocation::new(1, X1(Parachain(other_para_id))); let dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id))) .appended_with(AccountId32 { @@ -1335,8 +1335,9 @@ macro_rules! include_create_and_manage_foreign_assets_for_local_consensus_parach } ); -/// Test-case makes sure that `Runtime` can reserve-transfer asset to other parachains -pub fn reserve_transfer_native_asset_works< +/// Test-case makes sure that `Runtime` can reserve-transfer asset to other parachains (where +/// teleport is not trusted) +pub fn reserve_transfer_native_asset_to_non_teleport_para_works< Runtime, AllPalletsWithoutSystem, XcmConfig, @@ -1395,9 +1396,9 @@ pub fn reserve_transfer_native_asset_works< AccountId::from(alice).into(), ); - // reserve-transfer native asset with local reserve to remote parachain (1234) + // reserve-transfer native asset with local reserve to remote parachain (2345) - let other_para_id = 1234; + let other_para_id = 2345; let native_asset = MultiLocation::parent(); let dest = MultiLocation::new(1, X1(Parachain(other_para_id))); let dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id))) From 1dfcd01b73d42991ea81fb196f291f24f6628e2b Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 29 Sep 2023 20:41:30 +0300 Subject: [PATCH 028/124] pallet-xcm: refactor newly added tests --- polkadot/xcm/pallet-xcm/src/tests.rs | 1444 ++++++++++---------------- 1 file changed, 530 insertions(+), 914 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index c6899f129668..3b343e6a3977 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -454,8 +454,69 @@ fn limited_teleport_assets_works() { // // TODO: also add negative tests for testing various error conditions. -// Helper function to deduplicate testing different reserve-transfer types. -// Currently hardcoded for AssetsReserve=Local and FeeReserve=Local. +fn set_up_foreign_asset( + reserve_para_id: u32, + inner_junction: Option, + initial_amount: u128, + is_sufficient: bool, +) -> (MultiLocation, AccountId, MultiLocation) { + let reserve_location = + RelayLocation::get().pushed_with_interior(Parachain(reserve_para_id)).unwrap(); + let reserve_sovereign_account = + SovereignAccountOf::convert_location(&reserve_location).unwrap(); + + let foreign_asset_id_multilocation = if let Some(junction) = inner_junction { + reserve_location.pushed_with_interior(junction).unwrap() + } else { + reserve_location + }; + + // create sufficient (to be used as fees as well) foreign asset (0 total issuance) + assert_ok!(Assets::force_create( + RuntimeOrigin::root(), + foreign_asset_id_multilocation, + BOB, + is_sufficient, + 1 + )); + // this asset should have been teleported/reserve-transferred in, but for this test we just + // mint it locally. + assert_ok!(Assets::mint( + RuntimeOrigin::signed(BOB), + foreign_asset_id_multilocation, + ALICE, + initial_amount + )); + + (reserve_location, reserve_sovereign_account, foreign_asset_id_multilocation) +} + +// Helper function that provides correct `fee_index` after `sort()` done by +// `vec![MultiAsset, MultiAsset].into()`. +fn into_multiassets_checked( + fee_asset: MultiAsset, + transfer_asset: MultiAsset, +) -> (MultiAssets, usize, MultiAsset, MultiAsset) { + let assets: MultiAssets = vec![fee_asset.clone(), transfer_asset.clone()].into(); + let fee_index = if assets.get(0).unwrap().eq(&fee_asset) { 0 } else { 1 }; + (assets, fee_index, fee_asset, transfer_asset) +} + +/// Helper function to test `reserve_transfer_assets` with local asset reserve and local fee +/// reserve. +/// +/// Transferring native asset (local reserve) to some `OTHER_PARA_ID` (no teleport trust). +/// Using native asset for fees as well. +/// +/// ```nocompile +/// Here (source) OTHER_PARA_ID (destination) +/// | `assets` reserve +/// | `fees` reserve +/// | +/// | 1. execute `TransferReserveAsset(assets_and_fees_batched_together)` +/// | \--> sends `ReserveAssetDeposited(both), ClearOrigin, BuyExecution(fees), DepositAsset` +/// \------------------------------------------> +/// ``` fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( expected_beneficiary: MultiLocation, call: Call, @@ -513,9 +574,6 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( /// | \--> sends `ReserveAssetDeposited(both), ClearOrigin, BuyExecution(fees), DepositAsset` /// \------------------------------------------> /// ``` -/// -/// Asserts that the sender's balance is decreased and the destination SA balance -/// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works() { let beneficiary: MultiLocation = @@ -538,9 +596,6 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works( /// Test `limited_reserve_transfer_assets` with local asset reserve and local fee reserve. /// /// Same as test above but with limited weight. -/// -/// Asserts that the sender's balance is decreased and the destination SA balance -/// is increased. Verifies the correct message is sent and event is emitted. #[test] fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works() { let beneficiary: MultiLocation = @@ -584,64 +639,37 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_works() { - // foreign creator in this case child parachain acting as reserve - let reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) - .unwrap(); - let foreign_creator_as_account_id = - SovereignAccountOf::convert_location(&reserve_location).unwrap(); - - let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_amount = 142; - - // transfer destination is reserve location (no teleport trust) - let dest = reserve_location; - let assets: MultiAssets = vec![ - // native asset for fee - (MultiLocation::here(), FEE_AMOUNT).into(), - // foreign asset to transfer - (foreign_asset_id_multilocation, SEND_AMOUNT).into(), - ] - .into(); - let fee_index = 0; - let asset_index = 1; - - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - - // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. - assert_eq!(expected_fee.id, MultiLocation::here().into()); - assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); - - // reanchor according to test-case. - expected_fee.reanchor(&dest, context).unwrap(); - expected_asset.reanchor(&dest, context).unwrap(); - - let balances = - vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - new_test_ext_with_balances(balances).execute_with(|| { - // create non-sufficient foreign asset (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - foreign_asset_id_multilocation, - BOB, - false, - 1 - )); - // this asset should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, - ALICE, - foreign_asset_amount - )); - assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + // create non-sufficient foreign asset BLA (0 total issuance) + let foreign_initial_amount = 142; + let (reserve_location, reserve_sovereign_account, foreign_asset_id_multilocation) = + set_up_foreign_asset( + FOREIGN_ASSET_RESERVE_PARA_ID, + Some(FOREIGN_ASSET_INNER_JUNCTION), + foreign_initial_amount, + false, + ); + + // transfer destination is reserve location (no teleport trust) + let dest = reserve_location; + + let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + // native asset for fee - local reserve + (MultiLocation::here(), FEE_AMOUNT).into(), + // foreign asset to transfer - destination reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ); + + // reanchor according to test-case + let context = UniversalLocation::get(); + let expected_fee = fee_asset.reanchored(&dest, context).unwrap(); + let expected_asset = xfer_asset.reanchored(&dest, context).unwrap(); + + // balances checks before + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // do the transfer @@ -657,32 +685,22 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) )); + // Alice spent (transferred) amount assert_eq!( Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_amount - SEND_AMOUNT + foreign_initial_amount - SEND_AMOUNT ); // Alice used native asset for fees assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - FEE_AMOUNT); // Destination account (parachain account) added native reserve used as fee to balances - assert_eq!( - Balances::free_balance(foreign_creator_as_account_id.clone()), - INITIAL_BALANCE + FEE_AMOUNT - ); - assert_eq!( - Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), - 0 - ); + assert_eq!(Balances::free_balance(reserve_sovereign_account.clone()), FEE_AMOUNT); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, reserve_sovereign_account), 0); // Verify total and active issuance of foreign BLA have decreased (burned on // reserve-withdraw) - assert_eq!( - Assets::total_issuance(foreign_asset_id_multilocation), - foreign_asset_amount - SEND_AMOUNT - ); - assert_eq!( - Assets::active_issuance(foreign_asset_id_multilocation), - foreign_asset_amount - SEND_AMOUNT - ); + let expected_issuance = foreign_initial_amount - SEND_AMOUNT; + assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_issuance); + assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_issuance); // Verify sent XCM program assert_eq!( @@ -743,80 +761,48 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ /// ``` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works() { - let reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) - .unwrap(); - let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_initial_amount = 142; - let reserve_sovereign_account = - SovereignAccountOf::convert_location(&reserve_location).unwrap(); - - // transfer destination is OTHER_PARA_ID (foreign asset needs to go through its reserve chain) - let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); - let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); - - let assets: MultiAssets = vec![ - // native asset for fees - (MultiLocation::here(), FEE_AMOUNT).into(), - // foreign asset to transfer (not used for fees) - remote reserve - (foreign_asset_id_multilocation, SEND_AMOUNT).into(), - ] - .into(); - let fee_index = 0; - let asset_index = 1; - - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - - // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. - assert_eq!(expected_fee.id, MultiLocation::here().into()); - assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); - - // reanchor according to test-case. - let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); - let mut expected_fee_on_reserve = expected_fee.clone(); - let mut expected_asset_on_reserve = expected_asset.clone(); - expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); - expected_asset_on_reserve.reanchor(&reserve_location, context).unwrap(); - expected_fee.reanchor(&dest, context).unwrap(); - expected_asset.reanchor(&dest, context).unwrap(); - - // fees are split between the asset-reserve chain and the destination chain - crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); - crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); - - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (dest_sovereign_account.clone(), INITIAL_BALANCE), - (reserve_sovereign_account.clone(), INITIAL_BALANCE), - ]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); let expected_beneficiary_on_reserve = beneficiary; - new_test_ext_with_balances(balances).execute_with(|| { // create non-sufficient foreign asset BLA (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - foreign_asset_id_multilocation, - BOB, - false, - 1 - )); - // foreign asset BLA should have been teleported/reserve-transferred in, but for this test - // we just mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, - ALICE, - foreign_asset_initial_amount - )); - assert_eq!( - Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_initial_amount - ); + let foreign_initial_amount = 142; + let (reserve_location, reserve_sovereign_account, foreign_asset_id_multilocation) = + set_up_foreign_asset( + FOREIGN_ASSET_RESERVE_PARA_ID, + Some(FOREIGN_ASSET_INNER_JUNCTION), + foreign_initial_amount, + false, + ); + + // transfer destination is OTHER_PARA_ID (foreign asset needs to go through its reserve + // chain) + let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); + let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); + + let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + // native asset for fee - local reserve + (MultiLocation::here(), FEE_AMOUNT).into(), + // foreign asset to transfer - remote reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ); + + // reanchor according to test-case + let context = UniversalLocation::get(); + let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); + let mut expected_fee_on_reserve = + fee_asset.clone().reanchored(&reserve_location, context).unwrap(); + let expected_asset_on_reserve = + xfer_asset.clone().reanchored(&reserve_location, context).unwrap(); + let mut expected_fee = fee_asset.reanchored(&dest, context).unwrap(); + + // fees are split between the asset-reserve chain and the destination chain + crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); + crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); + + // balances checks before + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // do the transfer @@ -832,33 +818,23 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) )); + // Alice transferred BLA assert_eq!( Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_initial_amount - SEND_AMOUNT + foreign_initial_amount - SEND_AMOUNT ); // Alice spent native asset for fees assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - FEE_AMOUNT); // Half the fee went to reserve chain - assert_eq!( - Balances::free_balance(reserve_sovereign_account.clone()), - INITIAL_BALANCE + FEE_AMOUNT / 2 - ); + assert_eq!(Balances::free_balance(reserve_sovereign_account.clone()), FEE_AMOUNT / 2); // Other half went to dest chain - assert_eq!( - Balances::free_balance(dest_sovereign_account.clone()), - INITIAL_BALANCE + FEE_AMOUNT / 2 - ); + assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), FEE_AMOUNT / 2); // Verify total and active issuance of foreign BLA asset have decreased (burned on // reserve-withdraw) - assert_eq!( - Assets::total_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); - assert_eq!( - Assets::active_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); + let expected_issuance = foreign_initial_amount - SEND_AMOUNT; + assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_issuance); + assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_issuance); // Verify sent XCM program assert_eq!( @@ -935,62 +911,36 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works /// ``` #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_works() { - let usdc_reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) - .unwrap(); - let usdc_chain_sovereign_account = - SovereignAccountOf::convert_location(&usdc_reserve_location).unwrap(); - - let usdc_id_multilocation = - usdc_reserve_location.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); - let usdc_initial_local_amount = 142; - - // native assets transfer destination is same as fee reserve location (no teleport trust) - let dest = usdc_reserve_location; - let assets: MultiAssets = vec![ - // native asset to transfer (not used for fees) - (MultiLocation::here(), SEND_AMOUNT).into(), - // usdc for fees (is sufficient on local chain too) - (usdc_id_multilocation, FEE_AMOUNT).into(), - ] - .into(); - let fee_index = 1; - let asset_index = 0; - - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - - // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. - assert_eq!(expected_fee.id, usdc_id_multilocation.into()); - assert_eq!(expected_asset.id, MultiLocation::here().into()); - - // reanchor according to test-case. - expected_fee.reanchor(&dest, context).unwrap(); - expected_asset.reanchor(&dest, context).unwrap(); - - let balances = - vec![(ALICE, INITIAL_BALANCE), (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE)]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDC (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - usdc_id_multilocation, - BOB, - true, - 1 - )); - // this asset should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - usdc_id_multilocation, - ALICE, - usdc_initial_local_amount - )); + let usdc_initial_local_amount = 142; + let (usdc_reserve_location, usdc_chain_sovereign_account, usdc_id_multilocation) = + set_up_foreign_asset( + USDC_RESERVE_PARA_ID, + Some(USDC_INNER_JUNCTION), + usdc_initial_local_amount, + true, + ); + + // native assets transfer to fee reserve location (no teleport trust) + let dest = usdc_reserve_location; + + let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + // usdc for fees (is sufficient on local chain too) - destination reserve + (usdc_id_multilocation, FEE_AMOUNT).into(), + // native asset to transfer (not used for fees) - local reserve + (MultiLocation::here(), SEND_AMOUNT).into(), + ); + + // reanchor according to test-case + let context = UniversalLocation::get(); + let expected_fee = fee_asset.reanchored(&dest, context).unwrap(); + let expected_asset = xfer_asset.reanchored(&dest, context).unwrap(); + + // balances checks before assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); @@ -1007,6 +957,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) )); + // Alice spent (fees) amount assert_eq!( Assets::balance(usdc_id_multilocation, ALICE), @@ -1015,20 +966,12 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ // Alice used native asset for transfer assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); // Sovereign account of dest parachain holds `SEND_AMOUNT` native asset in local reserve - assert_eq!( - Balances::free_balance(usdc_chain_sovereign_account.clone()), - INITIAL_BALANCE + SEND_AMOUNT - ); + assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), SEND_AMOUNT); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) - assert_eq!( - Assets::total_issuance(usdc_id_multilocation), - usdc_initial_local_amount - FEE_AMOUNT - ); - assert_eq!( - Assets::active_issuance(usdc_id_multilocation), - usdc_initial_local_amount - FEE_AMOUNT - ); + let expected_issuance = usdc_initial_local_amount - FEE_AMOUNT; + assert_eq!(Assets::total_issuance(usdc_id_multilocation), expected_issuance); + assert_eq!(Assets::active_issuance(usdc_id_multilocation), expected_issuance); // Verify sent XCM program assert_eq!( @@ -1079,47 +1022,32 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ /// ``` #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_reserve_works() { - // we'll send just this foreign asset back to its reserve location and use it for fees as well - let reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) - .unwrap(); - let foreign_creator_as_account_id = - SovereignAccountOf::convert_location(&reserve_location).unwrap(); - - let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_amount = 142; - - // transfer destination is reserve location - let dest = reserve_location; - let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); - let fee_index = 0; - - let mut expected_assets = assets.clone(); - expected_assets.reanchor(&dest, UniversalLocation::get()).unwrap(); - - let balances = - vec![(ALICE, INITIAL_BALANCE), (foreign_creator_as_account_id.clone(), INITIAL_BALANCE)]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); new_test_ext_with_balances(balances).execute_with(|| { - // create sufficient (to be used as fees as well) foreign asset (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - foreign_asset_id_multilocation, - BOB, - true, - 1 - )); - // this asset should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, - ALICE, - foreign_asset_amount - )); - assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_asset_amount); + // we'll send just this foreign asset back to its reserve location and use it for fees as + // well + let foreign_initial_amount = 142; + let (reserve_location, reserve_sovereign_account, foreign_asset_id_multilocation) = + set_up_foreign_asset( + FOREIGN_ASSET_RESERVE_PARA_ID, + Some(FOREIGN_ASSET_INNER_JUNCTION), + foreign_initial_amount, + true, + ); + + // transfer destination is reserve location + let dest = reserve_location; + let assets: MultiAssets = vec![(foreign_asset_id_multilocation, SEND_AMOUNT).into()].into(); + let fee_index = 0; + + // reanchor according to test-case + let mut expected_assets = assets.clone(); + expected_assets.reanchor(&dest, UniversalLocation::get()).unwrap(); + + // balances checks before + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // do the transfer @@ -1135,29 +1063,22 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) )); + // Alice spent (transferred) amount assert_eq!( Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_amount - SEND_AMOUNT + foreign_initial_amount - SEND_AMOUNT ); // Alice's native asset balance is untouched assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - // Destination account (parachain account) has expected (same) balances - assert_eq!(Balances::free_balance(foreign_creator_as_account_id.clone()), INITIAL_BALANCE); - assert_eq!( - Assets::balance(foreign_asset_id_multilocation, foreign_creator_as_account_id), - 0 - ); + // Reserve sovereign account has same balances + assert_eq!(Balances::free_balance(reserve_sovereign_account.clone()), 0); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, reserve_sovereign_account), 0); // Verify total and active issuance of foreign BLA have decreased (burned on // reserve-withdraw) - assert_eq!( - Assets::total_issuance(foreign_asset_id_multilocation), - foreign_asset_amount - SEND_AMOUNT - ); - assert_eq!( - Assets::active_issuance(foreign_asset_id_multilocation), - foreign_asset_amount - SEND_AMOUNT - ); + let expected_issuance = foreign_initial_amount - SEND_AMOUNT; + assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_issuance); + assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_issuance); // Verify sent XCM program assert_eq!( @@ -1207,91 +1128,56 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re /// ``` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve_works() { - let usdc_chain = RelayLocation::get() - .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) - .unwrap(); - let usdc_id_multilocation = usdc_chain.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); - let usdc_initial_local_amount = 42; - - let reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) - .unwrap(); - let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_initial_amount = 142; - - // transfer destination is USDC chain (foreign asset needs to go through its reserve chain) - let dest = usdc_chain; - let assets: MultiAssets = vec![ - // foreign asset to transfer (not used for fees) - remote reserve - (foreign_asset_id_multilocation, SEND_AMOUNT).into(), - // USDC for fees (is sufficient on local chain too) - (usdc_id_multilocation, FEE_AMOUNT).into(), - ] - .into(); - let asset_index = 0; - let fee_index = 1; - - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - - // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. - assert_eq!(expected_fee.id, usdc_id_multilocation.into()); - assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); - - // reanchor according to test-case. - let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); - let expected_reserve_on_dest = reserve_location.reanchored(&dest, context).unwrap(); - let mut expected_fee_on_reserve = expected_fee.clone(); - let mut expected_asset_on_reserve = expected_asset.clone(); - expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); - expected_asset_on_reserve.reanchor(&reserve_location, context).unwrap(); - expected_fee.reanchor(&dest, context).unwrap(); - expected_asset.reanchor(&dest, context).unwrap(); - - // fees are split between the asset-reserve chain and the destination chain - crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); - crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); - let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDC (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - usdc_id_multilocation, - BOB, + let usdc_initial_local_amount = 42; + let (usdc_chain, _, usdc_id_multilocation) = set_up_foreign_asset( + USDC_RESERVE_PARA_ID, + Some(USDC_INNER_JUNCTION), + usdc_initial_local_amount, true, - 1 - )); - // USDC should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - usdc_id_multilocation, - ALICE, - usdc_initial_local_amount - )); + ); + // create non-sufficient foreign asset BLA (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - foreign_asset_id_multilocation, - BOB, + let foreign_initial_amount = 142; + let (reserve_location, _, foreign_asset_id_multilocation) = set_up_foreign_asset( + FOREIGN_ASSET_RESERVE_PARA_ID, + Some(FOREIGN_ASSET_INNER_JUNCTION), + foreign_initial_amount, false, - 1 - )); - // foreign asset BLA should have been teleported/reserve-transferred in, but for this test - // we just mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, - ALICE, - foreign_asset_initial_amount - )); + ); + + // transfer destination is USDC chain (foreign asset BLA needs to go through its separate + // reserve chain) + let dest = usdc_chain; + + let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + // USDC for fees (is sufficient on local chain too) - destination reserve + (usdc_id_multilocation, FEE_AMOUNT).into(), + // foreign asset to transfer (not used for fees) - remote reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ); + + // reanchor according to test-case + let context = UniversalLocation::get(); + let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); + let expected_reserve_on_dest = reserve_location.reanchored(&dest, context).unwrap(); + let mut expected_fee_on_reserve = + fee_asset.clone().reanchored(&reserve_location, context).unwrap(); + let expected_asset_on_reserve = + xfer_asset.clone().reanchored(&reserve_location, context).unwrap(); + let mut expected_fee = fee_asset.reanchored(&dest, context).unwrap(); + + // fees are split between the asset-reserve chain and the destination chain + crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); + crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); + + // balances checks before assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // do the transfer @@ -1307,6 +1193,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) )); + // Alice native asset untouched assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // Alice spent USDC for fees @@ -1317,27 +1204,17 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve // Alice transferred BLA assert_eq!( Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_initial_amount - SEND_AMOUNT + foreign_initial_amount - SEND_AMOUNT ); // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) - assert_eq!( - Assets::total_issuance(usdc_id_multilocation), - usdc_initial_local_amount - FEE_AMOUNT - ); - assert_eq!( - Assets::active_issuance(usdc_id_multilocation), - usdc_initial_local_amount - FEE_AMOUNT - ); + let expected_usdc_issuance = usdc_initial_local_amount - FEE_AMOUNT; + assert_eq!(Assets::total_issuance(usdc_id_multilocation), expected_usdc_issuance); + assert_eq!(Assets::active_issuance(usdc_id_multilocation), expected_usdc_issuance); // Verify total and active issuance of foreign BLA asset have decreased (burned on // reserve-withdraw) - assert_eq!( - Assets::total_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); - assert_eq!( - Assets::active_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); + let expected_bla_issuance = foreign_initial_amount - SEND_AMOUNT; + assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_bla_issuance); + assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_bla_issuance); // Verify sent XCM program assert_eq!( @@ -1421,67 +1298,40 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve /// ``` #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works() { - // foreign creator in this case child parachain acting as reserve - let fee_reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) - .unwrap(); - let usdc_chain_sovereign_account = - SovereignAccountOf::convert_location(&fee_reserve_location).unwrap(); - - let usdc_id_multilocation = - fee_reserve_location.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); - let usdc_initial_local_amount = 142; - - // transfer destination is some other parachain != fee reserve location (no teleport trust) - let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); - let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); - let assets: MultiAssets = vec![ - // native asset to transfer (not used for fees) - local reserve - (MultiLocation::here(), SEND_AMOUNT).into(), - // USDC for fees (is sufficient on local chain too) - remote reserve - (usdc_id_multilocation, FEE_AMOUNT).into(), - ] - .into(); - let asset_index = 0; - let fee_index = 1; - - let context = UniversalLocation::get(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - - // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. - assert_eq!(expected_fee.id, usdc_id_multilocation.into()); - assert_eq!(expected_asset.id, MultiLocation::here().into()); - - // reanchor according to test-case. - let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); - let mut expected_fee_on_reserve = expected_fee.clone(); - expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); - expected_fee.reanchor(&dest, context).unwrap(); - expected_asset.reanchor(&dest, context).unwrap(); - - let balances = - vec![(ALICE, INITIAL_BALANCE), (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE)]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDC (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - usdc_id_multilocation, - BOB, - true, - 1 - )); - // USDC should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - usdc_id_multilocation, - ALICE, - usdc_initial_local_amount - )); + let usdc_initial_local_amount = 142; + let (fee_reserve_location, usdc_chain_sovereign_account, usdc_id_multilocation) = + set_up_foreign_asset( + USDC_RESERVE_PARA_ID, + Some(USDC_INNER_JUNCTION), + usdc_initial_local_amount, + true, + ); + + // transfer destination is some other parachain != fee reserve location (no teleport trust) + let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); + let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); + + let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + // USDC for fees (is sufficient on local chain too) - remote reserve + (usdc_id_multilocation, FEE_AMOUNT).into(), + // native asset to transfer (not used for fees) - local reserve + (MultiLocation::here(), SEND_AMOUNT).into(), + ); + + // reanchor according to test-case + let context = UniversalLocation::get(); + let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); + let expected_fee_on_reserve = + fee_asset.clone().reanchored(&fee_reserve_location, context).unwrap(); + let expected_fee = fee_asset.reanchored(&dest, context).unwrap(); + let expected_asset = xfer_asset.reanchored(&dest, context).unwrap(); + + // balances checks before assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); @@ -1506,19 +1356,14 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works // Alice used native asset for transfer assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); // Sovereign account of reserve parachain is unchanged - assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), 0); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); // Sovereign account of destination parachain holds `SEND_AMOUNT` in local reserve assert_eq!(Balances::free_balance(dest_sovereign_account), SEND_AMOUNT); // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) - assert_eq!( - Assets::total_issuance(usdc_id_multilocation), - usdc_initial_local_amount - FEE_AMOUNT - ); - assert_eq!( - Assets::active_issuance(usdc_id_multilocation), - usdc_initial_local_amount - FEE_AMOUNT - ); + let expected_usdc_issuance = usdc_initial_local_amount - FEE_AMOUNT; + assert_eq!(Assets::total_issuance(usdc_id_multilocation), expected_usdc_issuance); + assert_eq!(Assets::active_issuance(usdc_id_multilocation), expected_usdc_issuance); // Verify sent XCM program assert_eq!( @@ -1582,92 +1427,50 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works /// ``` #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve_works() { - // foreign creator in this case child parachain acting as reserve - let fee_reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) - .unwrap(); - let usdc_chain_sovereign_account = - SovereignAccountOf::convert_location(&fee_reserve_location).unwrap(); - let usdc_id_multilocation = - fee_reserve_location.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); - let usdc_initial_local_amount = 42; - - let reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) - .unwrap(); - let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_initial_amount = 142; - - // transfer destination is asset reserve location - let dest = reserve_location; - let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); - let assets: MultiAssets = vec![ - // foreign asset to transfer (not used for fees) - destination reserve - (foreign_asset_id_multilocation, SEND_AMOUNT).into(), - // USDC for fees (is sufficient on local chain too) - remote reserve - (usdc_id_multilocation, FEE_AMOUNT).into(), - ] - .into(); - let asset_index = 0; - let fee_index = 1; - - let context = UniversalLocation::get(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - - // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. - assert_eq!(expected_fee.id, usdc_id_multilocation.into()); - assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); - - // reanchor according to test-case. - let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); - let mut expected_fee_on_reserve = expected_fee.clone(); - expected_fee_on_reserve.reanchor(&fee_reserve_location, context).unwrap(); - expected_fee.reanchor(&dest, context).unwrap(); - expected_asset.reanchor(&dest, context).unwrap(); - - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE), - (dest_sovereign_account.clone(), INITIAL_BALANCE), - ]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDC (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - usdc_id_multilocation, - BOB, - true, - 1 - )); - // USDC should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - usdc_id_multilocation, - ALICE, - usdc_initial_local_amount - )); + let usdc_initial_local_amount = 42; + let (fee_reserve_location, usdc_chain_sovereign_account, usdc_id_multilocation) = + set_up_foreign_asset( + USDC_RESERVE_PARA_ID, + Some(USDC_INNER_JUNCTION), + usdc_initial_local_amount, + true, + ); + // create non-sufficient foreign asset BLA (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - foreign_asset_id_multilocation, - BOB, - false, - 1 - )); - // foreign asset BLA should have been teleported/reserve-transferred in, but for this test - // we just mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, - ALICE, - foreign_asset_initial_amount - )); + let foreign_initial_amount = 142; + let (reserve_location, foreign_sovereign_account, foreign_asset_id_multilocation) = + set_up_foreign_asset( + FOREIGN_ASSET_RESERVE_PARA_ID, + Some(FOREIGN_ASSET_INNER_JUNCTION), + foreign_initial_amount, + false, + ); + + // transfer destination is asset reserve location + let dest = reserve_location; + let dest_sovereign_account = foreign_sovereign_account; + + let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + // USDC for fees (is sufficient on local chain too) - remote reserve + (usdc_id_multilocation, FEE_AMOUNT).into(), + // foreign asset to transfer (not used for fees) - destination reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ); + + // reanchor according to test-case + let context = UniversalLocation::get(); + let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); + let expected_fee_on_reserve = + fee_asset.clone().reanchored(&fee_reserve_location, context).unwrap(); + let expected_fee = fee_asset.reanchored(&dest, context).unwrap(); + let expected_asset = xfer_asset.reanchored(&dest, context).unwrap(); + + // balances checks before assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); @@ -1694,33 +1497,23 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve // Alice transferred BLA assert_eq!( Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_initial_amount - SEND_AMOUNT + foreign_initial_amount - SEND_AMOUNT ); // Verify balances of USDC reserve parachain - assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), 0); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); // Verify balances of transferred-asset reserve parachain - assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), 0); assert_eq!(Assets::balance(foreign_asset_id_multilocation, dest_sovereign_account), 0); // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) - assert_eq!( - Assets::total_issuance(usdc_id_multilocation), - usdc_initial_local_amount - FEE_AMOUNT - ); - assert_eq!( - Assets::active_issuance(usdc_id_multilocation), - usdc_initial_local_amount - FEE_AMOUNT - ); + let expected_usdc_issuance = usdc_initial_local_amount - FEE_AMOUNT; + assert_eq!(Assets::total_issuance(usdc_id_multilocation), expected_usdc_issuance); + assert_eq!(Assets::active_issuance(usdc_id_multilocation), expected_usdc_issuance); // Verify total and active issuance of foreign BLA asset have decreased (burned on // reserve-withdraw) - assert_eq!( - Assets::total_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); - assert_eq!( - Assets::active_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); + let expected_bla_issuance = foreign_initial_amount - SEND_AMOUNT; + assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_bla_issuance); + assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_bla_issuance); // Verify sent XCM program assert_eq!( @@ -1782,52 +1575,37 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve /// ``` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_works() { - // foreign creator in this case child parachain acting as reserve - let usdc_reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(USDC_RESERVE_PARA_ID)) - .unwrap(); - let usdc_chain_sovereign_account = - SovereignAccountOf::convert_location(&usdc_reserve_location).unwrap(); - - let usdc_id_multilocation = - usdc_reserve_location.pushed_with_interior(USDC_INNER_JUNCTION).unwrap(); - let usdc_initial_local_amount = 142; - - let assets: MultiAssets = vec![(usdc_id_multilocation, SEND_AMOUNT).into()].into(); - let fee_index = 0; - // transfer destination is some other parachainß - let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); - - let balances = - vec![(ALICE, INITIAL_BALANCE), (usdc_chain_sovereign_account.clone(), INITIAL_BALANCE)]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); new_test_ext_with_balances(balances).execute_with(|| { - // create sufficient (to be used as fees as well) USDC asset (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - usdc_id_multilocation, - BOB, - true, - 1 - )); - // this asset should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - usdc_id_multilocation, - ALICE, - usdc_initial_local_amount - )); - assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - + // create sufficient foreign asset USDC (0 total issuance) + let usdc_initial_local_amount = 142; + let (usdc_chain, usdc_chain_sovereign_account, usdc_id_multilocation) = + set_up_foreign_asset( + USDC_RESERVE_PARA_ID, + Some(USDC_INNER_JUNCTION), + usdc_initial_local_amount, + true, + ); + + // transfer destination is some other parachain + let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); + + let assets: MultiAssets = vec![(usdc_id_multilocation, SEND_AMOUNT).into()].into(); + let fee_index = 0; + + // reanchor according to test-case let context = UniversalLocation::get(); - let mut expected_fee_on_reserve = assets.get(fee_index).unwrap().clone(); - expected_fee_on_reserve.reanchor(&usdc_reserve_location, context).unwrap(); + let expected_dest_on_reserve = dest.reanchored(&usdc_chain, context).unwrap(); + let expected_fee_on_reserve = + assets.get(fee_index).unwrap().clone().reanchored(&usdc_chain, context).unwrap(); let mut expected_assets = assets.clone(); expected_assets.reanchor(&dest, context).unwrap(); - let expected_dest_on_reserve = dest.reanchored(&usdc_reserve_location, context).unwrap(); + + // balances checks before + assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // do the transfer assert_ok!(XcmPallet::limited_reserve_transfer_assets( @@ -1842,6 +1620,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) )); + // Alice spent (transferred) amount assert_eq!( Assets::balance(usdc_id_multilocation, ALICE), @@ -1850,24 +1629,19 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work // Alice's native asset balance is untouched assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // Destination account (parachain account) has expected (same) balances - assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), 0); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) - assert_eq!( - Assets::total_issuance(usdc_id_multilocation), - usdc_initial_local_amount - SEND_AMOUNT - ); - assert_eq!( - Assets::active_issuance(usdc_id_multilocation), - usdc_initial_local_amount - SEND_AMOUNT - ); + let expected_usdc_issuance = usdc_initial_local_amount - SEND_AMOUNT; + assert_eq!(Assets::total_issuance(usdc_id_multilocation), expected_usdc_issuance); + assert_eq!(Assets::active_issuance(usdc_id_multilocation), expected_usdc_issuance); // Verify sent XCM program assert_eq!( sent_xcm(), vec![( // first message sent to reserve chain - usdc_reserve_location, + usdc_chain, Xcm(vec![ WithdrawAsset(expected_fee_on_reserve.clone().into()), ClearOrigin, @@ -1910,58 +1684,31 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work /// ``` #[test] fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { - let usdt_location = RelayLocation::get().pushed_with_interior(Parachain(USDT_PARA_ID)).unwrap(); - let usdt_chain_sovereign_account = - SovereignAccountOf::convert_location(&usdt_location).unwrap(); - - let usdt_id_multilocation = usdt_location; - let usdt_initial_local_amount = 42; - - // native assets transfer destination is USDT chain (teleport trust only for USDT) - let dest = usdt_location; - let assets: MultiAssets = vec![ - // native asset to transfer (not used for fees) - (MultiLocation::here(), SEND_AMOUNT).into(), - // USDT for fees (is sufficient on local chain too) - (usdt_id_multilocation, FEE_AMOUNT).into(), - ] - .into(); - let asset_index = 0; - let fee_index = 1; - - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - - // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. - assert_eq!(expected_fee.id, usdt_id_multilocation.into()); - assert_eq!(expected_asset.id, MultiLocation::here().into()); - - // reanchor according to test-case. - expected_fee.reanchor(&dest, context).unwrap(); - expected_asset.reanchor(&dest, context).unwrap(); - - let balances = - vec![(ALICE, INITIAL_BALANCE), (usdt_chain_sovereign_account.clone(), INITIAL_BALANCE)]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDT (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - usdt_id_multilocation, - BOB, - true, - 1 - )); - // this asset should have been teleported in, but for this test we just mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - usdt_id_multilocation, - ALICE, - usdt_initial_local_amount - )); + let usdt_initial_local_amount = 42; + let (usdt_chain, usdt_chain_sovereign_account, usdt_id_multilocation) = + set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, true); + + // native assets transfer destination is USDT chain (teleport trust only for USDT) + let dest = usdt_chain; + + let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + // USDT for fees (is sufficient on local chain too) - teleported + (usdt_id_multilocation, FEE_AMOUNT).into(), + // native asset to transfer (not used for fees) - local reserve + (MultiLocation::here(), SEND_AMOUNT).into(), + ); + + // reanchor according to test-case + let context = UniversalLocation::get(); + let expected_fee = fee_asset.reanchored(&dest, context).unwrap(); + let expected_asset = xfer_asset.reanchored(&dest, context).unwrap(); + + // balances checks before assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); @@ -1986,20 +1733,12 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { // Alice used native asset for transfer assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); // Sovereign account of dest parachain holds `SEND_AMOUNT` native asset in local reserve - assert_eq!( - Balances::free_balance(usdt_chain_sovereign_account.clone()), - INITIAL_BALANCE + SEND_AMOUNT - ); + assert_eq!(Balances::free_balance(usdt_chain_sovereign_account.clone()), SEND_AMOUNT); assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); // Verify total and active issuance have decreased (teleported) - assert_eq!( - Assets::total_issuance(usdt_id_multilocation), - usdt_initial_local_amount - FEE_AMOUNT - ); - assert_eq!( - Assets::active_issuance(usdt_id_multilocation), - usdt_initial_local_amount - FEE_AMOUNT - ); + let expected_usdt_issuance = usdt_initial_local_amount - FEE_AMOUNT; + assert_eq!(Assets::total_issuance(usdt_id_multilocation), expected_usdt_issuance); + assert_eq!(Assets::active_issuance(usdt_id_multilocation), expected_usdt_issuance); // Verify sent XCM program assert_eq!( @@ -2054,84 +1793,42 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { /// ``` #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_works() { - let usdt_chain = RelayLocation::get().pushed_with_interior(Parachain(USDT_PARA_ID)).unwrap(); - let usdt_chain_sovereign_account = SovereignAccountOf::convert_location(&usdt_chain).unwrap(); - let usdt_id_multilocation = usdt_chain; - let usdt_initial_local_amount = 42; - - let reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) - .unwrap(); - let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_initial_amount = 142; - - // transfer destination is asset reserve location - let dest = reserve_location; - let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); - let assets: MultiAssets = vec![ - // USDT for fees (is sufficient on local chain too) - (usdt_id_multilocation, FEE_AMOUNT).into(), - // foreign asset to transfer (not used for fees) - destination reserve - (foreign_asset_id_multilocation, SEND_AMOUNT).into(), - ] - .into(); - let fee_index = 0; - let asset_index = 1; - - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - - // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. - assert_eq!(expected_fee.id, usdt_id_multilocation.into()); - assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); - - // reanchor according to test-case. - expected_fee.reanchor(&dest, context).unwrap(); - expected_asset.reanchor(&dest, context).unwrap(); - - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (usdt_chain_sovereign_account.clone(), INITIAL_BALANCE), - (dest_sovereign_account.clone(), INITIAL_BALANCE), - ]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDT (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - usdt_id_multilocation, - BOB, - true, - 1 - )); - // USDT should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - usdt_id_multilocation, - ALICE, - usdt_initial_local_amount - )); + let usdt_initial_local_amount = 42; + let (_, usdt_chain_sovereign_account, usdt_id_multilocation) = + set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, true); + // create non-sufficient foreign asset BLA (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - foreign_asset_id_multilocation, - BOB, - false, - 1 - )); - // foreign asset BLA should have been teleported/reserve-transferred in, but for this test - // we just mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, - ALICE, - foreign_asset_initial_amount - )); + let foreign_initial_amount = 142; + let (reserve_location, foreign_sovereign_account, foreign_asset_id_multilocation) = + set_up_foreign_asset( + FOREIGN_ASSET_RESERVE_PARA_ID, + Some(FOREIGN_ASSET_INNER_JUNCTION), + foreign_initial_amount, + false, + ); + + // transfer destination is asset reserve location + let dest = reserve_location; + let dest_sovereign_account = foreign_sovereign_account; + + let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + // USDT for fees (is sufficient on local chain too) - teleported + (usdt_id_multilocation, FEE_AMOUNT).into(), + // foreign asset to transfer (not used for fees) - destination reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ); + + // reanchor according to test-case + let context = UniversalLocation::get(); + let expected_fee = fee_asset.reanchored(&dest, context).unwrap(); + let expected_asset = xfer_asset.reanchored(&dest, context).unwrap(); + + // balances checks before assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); @@ -2158,33 +1855,23 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor // Alice transferred BLA assert_eq!( Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_initial_amount - SEND_AMOUNT + foreign_initial_amount - SEND_AMOUNT ); // Verify balances of USDT reserve parachain - assert_eq!(Balances::free_balance(usdt_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Balances::free_balance(usdt_chain_sovereign_account.clone()), 0); assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); // Verify balances of transferred-asset reserve parachain - assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), 0); assert_eq!(Assets::balance(foreign_asset_id_multilocation, dest_sovereign_account), 0); // Verify total and active issuance of USDT have decreased (teleported) - assert_eq!( - Assets::total_issuance(usdt_id_multilocation), - usdt_initial_local_amount - FEE_AMOUNT - ); - assert_eq!( - Assets::active_issuance(usdt_id_multilocation), - usdt_initial_local_amount - FEE_AMOUNT - ); + let expected_usdt_issuance = usdt_initial_local_amount - FEE_AMOUNT; + assert_eq!(Assets::total_issuance(usdt_id_multilocation), expected_usdt_issuance); + assert_eq!(Assets::active_issuance(usdt_id_multilocation), expected_usdt_issuance); // Verify total and active issuance of foreign BLA asset have decreased (burned on // reserve-withdraw) - assert_eq!( - Assets::total_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); - assert_eq!( - Assets::active_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); + let expected_bla_issuance = foreign_initial_amount - SEND_AMOUNT; + assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_bla_issuance); + assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_bla_issuance); // Verify sent XCM program assert_eq!( @@ -2220,74 +1907,6 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor }); } -/// Test `reserve_transfer_assets` single asset which is also teleportable - should fail. -/// -/// Attempting to reserve-transfer teleport-trusted USDT to `USDT_PARA_ID` should fail. -#[test] -fn reserve_transfer_assets_with_teleportable_asset_fails() { - let usdt_chain = RelayLocation::get().pushed_with_interior(Parachain(USDT_PARA_ID)).unwrap(); - let usdt_chain_sovereign_account = SovereignAccountOf::convert_location(&usdt_chain).unwrap(); - let usdt_id_multilocation = usdt_chain; - let usdt_initial_local_amount = 42; - - // transfer destination is USDT chain (foreign asset needs to go through its reserve chain) - let dest = usdt_chain; - let assets: MultiAssets = vec![(usdt_id_multilocation, FEE_AMOUNT).into()].into(); - let fee_index = 0; - - let balances = vec![(ALICE, INITIAL_BALANCE)]; - let beneficiary: MultiLocation = - Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - - new_test_ext_with_balances(balances).execute_with(|| { - // create sufficient foreign asset USDT (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - usdt_id_multilocation, - BOB, - true, - 1 - )); - // USDT should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - usdt_id_multilocation, - ALICE, - usdt_initial_local_amount - )); - assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - - // do the transfer - let res = XcmPallet::limited_reserve_transfer_assets( - RuntimeOrigin::signed(ALICE), - Box::new(dest.into()), - Box::new(beneficiary.into()), - Box::new(assets.into()), - fee_index as u32, - Unlimited, - ); - assert_eq!( - res, - Err(DispatchError::Module(ModuleError { - index: 4, - error: [2, 0, 0, 0], - message: Some("Filtered") - })) - ); - // Alice native asset is still same - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - // Alice USDT balance is still same - assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); - // No USDT moved to sovereign account of reserve parachain - assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); - // Verify total and active issuance of USDT are still the same - assert_eq!(Assets::total_issuance(usdt_id_multilocation), usdt_initial_local_amount); - assert_eq!(Assets::active_issuance(usdt_id_multilocation), usdt_initial_local_amount); - }); -} - /// Test `reserve_transfer_assets` with remote asset reserve and teleported fee. /// /// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to `USDT_PARA_ID`. Using @@ -2312,95 +1931,50 @@ fn reserve_transfer_assets_with_teleportable_asset_fails() { /// ``` #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() { - let usdt_chain = RelayLocation::get().pushed_with_interior(Parachain(USDT_PARA_ID)).unwrap(); - let usdt_chain_sovereign_account = SovereignAccountOf::convert_location(&usdt_chain).unwrap(); - let usdt_id_multilocation = usdt_chain; - let usdt_initial_local_amount = 42; - - let reserve_location = RelayLocation::get() - .pushed_with_interior(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) - .unwrap(); - let foreign_asset_id_multilocation = - reserve_location.pushed_with_interior(FOREIGN_ASSET_INNER_JUNCTION).unwrap(); - let foreign_asset_initial_amount = 142; - let reserve_sovereign_account = - SovereignAccountOf::convert_location(&reserve_location).unwrap(); - - // transfer destination is USDT chain (foreign asset needs to go through its reserve chain) - let dest = usdt_chain; - let assets: MultiAssets = vec![ - // USDT for fees (is sufficient on local chain too) - (usdt_id_multilocation, FEE_AMOUNT).into(), - // foreign asset to transfer (not used for fees) - remote reserve - (foreign_asset_id_multilocation, SEND_AMOUNT).into(), - ] - .into(); - let fee_index = 0; - let asset_index = 1; - - let context = UniversalLocation::get(); - let mut expected_fee = assets.get(fee_index).unwrap().clone(); - let mut expected_asset = assets.get(asset_index).unwrap().clone(); - - // sanity check indices are still ok after sort() done by `vec![MultiAsset].into()`. - assert_eq!(expected_fee.id, usdt_id_multilocation.into()); - assert_eq!(expected_asset.id, foreign_asset_id_multilocation.into()); - - // reanchor according to test-case. - let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); - let mut expected_fee_on_reserve = expected_fee.clone(); - let mut expected_asset_on_reserve = expected_asset.clone(); - expected_fee_on_reserve.reanchor(&reserve_location, context).unwrap(); - expected_asset_on_reserve.reanchor(&reserve_location, context).unwrap(); - expected_fee.reanchor(&dest, context).unwrap(); - expected_asset.reanchor(&dest, context).unwrap(); - - // fees are split between the asset-reserve chain and the destination chain - crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); - crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); - - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (usdt_chain_sovereign_account.clone(), INITIAL_BALANCE), - (reserve_sovereign_account.clone(), INITIAL_BALANCE), - ]; + let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); let expected_beneficiary_on_reserve = beneficiary; - new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDT (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - usdt_id_multilocation, - BOB, - true, - 1 - )); - // USDT should have been teleported/reserve-transferred in, but for this test we just - // mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - usdt_id_multilocation, - ALICE, - usdt_initial_local_amount - )); + let usdt_initial_local_amount = 42; + let (usdt_chain, usdt_chain_sovereign_account, usdt_id_multilocation) = + set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, true); + // create non-sufficient foreign asset BLA (0 total issuance) - assert_ok!(Assets::force_create( - RuntimeOrigin::root(), - foreign_asset_id_multilocation, - BOB, - false, - 1 - )); - // foreign asset BLA should have been teleported/reserve-transferred in, but for this test - // we just mint it locally. - assert_ok!(Assets::mint( - RuntimeOrigin::signed(BOB), - foreign_asset_id_multilocation, - ALICE, - foreign_asset_initial_amount - )); + let foreign_initial_amount = 142; + let (reserve_location, reserve_sovereign_account, foreign_asset_id_multilocation) = + set_up_foreign_asset( + FOREIGN_ASSET_RESERVE_PARA_ID, + Some(FOREIGN_ASSET_INNER_JUNCTION), + foreign_initial_amount, + false, + ); + + // transfer destination is USDT chain (foreign asset needs to go through its reserve chain) + let dest = usdt_chain; + + let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + // USDT for fees (is sufficient on local chain too) - teleported + (usdt_id_multilocation, FEE_AMOUNT).into(), + // foreign asset to transfer (not used for fees) - remote reserve + (foreign_asset_id_multilocation, SEND_AMOUNT).into(), + ); + + // reanchor according to test-case + let context = UniversalLocation::get(); + let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); + let mut expected_fee_on_reserve = + fee_asset.clone().reanchored(&reserve_location, context).unwrap(); + let expected_asset_on_reserve = + xfer_asset.clone().reanchored(&reserve_location, context).unwrap(); + let mut expected_fee = fee_asset.reanchored(&dest, context).unwrap(); + + // fees are split between the asset-reserve chain and the destination chain + crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); + crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); + + // balances checks before assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); @@ -2427,33 +2001,23 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() // Alice transferred BLA assert_eq!( Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_asset_initial_amount - SEND_AMOUNT + foreign_initial_amount - SEND_AMOUNT ); // Verify balances of USDT reserve parachain - assert_eq!(Balances::free_balance(usdt_chain_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Balances::free_balance(usdt_chain_sovereign_account.clone()), 0); assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); // Verify balances of transferred-asset reserve parachain - assert_eq!(Balances::free_balance(reserve_sovereign_account.clone()), INITIAL_BALANCE); + assert_eq!(Balances::free_balance(reserve_sovereign_account.clone()), 0); assert_eq!(Assets::balance(foreign_asset_id_multilocation, reserve_sovereign_account), 0); // Verify total and active issuance of USDT have decreased (teleported) - assert_eq!( - Assets::total_issuance(usdt_id_multilocation), - usdt_initial_local_amount - FEE_AMOUNT - ); - assert_eq!( - Assets::active_issuance(usdt_id_multilocation), - usdt_initial_local_amount - FEE_AMOUNT - ); + let expected_usdt_issuance = usdt_initial_local_amount - FEE_AMOUNT; + assert_eq!(Assets::total_issuance(usdt_id_multilocation), expected_usdt_issuance); + assert_eq!(Assets::active_issuance(usdt_id_multilocation), expected_usdt_issuance); // Verify total and active issuance of foreign BLA asset have decreased (burned on // reserve-withdraw) - assert_eq!( - Assets::total_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); - assert_eq!( - Assets::active_issuance(foreign_asset_id_multilocation), - foreign_asset_initial_amount - SEND_AMOUNT - ); + let expected_bla_issuance = foreign_initial_amount - SEND_AMOUNT; + assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_bla_issuance); + assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_bla_issuance); // Verify sent XCM program assert_eq!( @@ -2511,6 +2075,58 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() }); } +/// Test `reserve_transfer_assets` single asset which is teleportable - should fail. +/// +/// Attempting to reserve-transfer teleport-trusted USDT to `USDT_PARA_ID` should fail. +#[test] +fn reserve_transfer_assets_with_teleportable_asset_fails() { + let balances = vec![(ALICE, INITIAL_BALANCE)]; + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + new_test_ext_with_balances(balances).execute_with(|| { + // create sufficient foreign asset USDT (0 total issuance) + let usdt_initial_local_amount = 42; + let (usdt_chain, usdt_chain_sovereign_account, usdt_id_multilocation) = + set_up_foreign_asset(USDT_PARA_ID, None, usdt_initial_local_amount, true); + + // transfer destination is USDT chain (foreign asset needs to go through its reserve chain) + let dest = usdt_chain; + let assets: MultiAssets = vec![(usdt_id_multilocation, FEE_AMOUNT).into()].into(); + let fee_index = 0; + + // balances checks before + assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + + // do the transfer + let res = XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(dest.into()), + Box::new(beneficiary.into()), + Box::new(assets.into()), + fee_index as u32, + Unlimited, + ); + assert_eq!( + res, + Err(DispatchError::Module(ModuleError { + index: 4, + error: [2, 0, 0, 0], + message: Some("Filtered") + })) + ); + // Alice native asset is still same + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + // Alice USDT balance is still same + assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); + // No USDT moved to sovereign account of reserve parachain + assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); + // Verify total and active issuance of USDT are still the same + assert_eq!(Assets::total_issuance(usdt_id_multilocation), usdt_initial_local_amount); + assert_eq!(Assets::active_issuance(usdt_id_multilocation), usdt_initial_local_amount); + }); +} + /// Test local execution of XCM /// /// Asserts that the sender's balance is decreased and the beneficiary's balance From 022ef71466df90c27802ef5109d07ccf4291b345 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 10 Oct 2023 17:33:43 +0300 Subject: [PATCH 029/124] pallet-xcm: fix benchmarks --- polkadot/runtime/westend/src/xcm_config.rs | 16 ++++++++++++- polkadot/xcm/pallet-xcm/src/benchmarking.rs | 26 ++++++++++----------- polkadot/xcm/pallet-xcm/src/lib.rs | 14 +++++++++++ polkadot/xcm/pallet-xcm/src/mock.rs | 25 ++++++++++++++++++-- 4 files changed, 64 insertions(+), 17 deletions(-) diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 66a2e2230ccd..53a242952cd5 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -194,6 +194,16 @@ parameter_types! { #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parachain(1000).into()); + // Relay/native token can be teleported to/from AH. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + AssetHub::get(), + )); + // We can reserve transfer native token to some random parachain. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + Parachain(4321).into(), + )); } /// Type to convert the `GeneralAdmin` origin to a Plurality `MultiLocation` value. @@ -256,7 +266,11 @@ impl pallet_xcm::Config for Runtime { type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = crate::weights::pallet_xcm::WeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index aca4bd1fb3fa..f567691b5092 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -40,43 +40,41 @@ benchmarks! { }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_msg)) teleport_assets { - let asset: MultiAsset = (Here, 10).into(); + let (assets, destination) = T::TeleportableAssets::get().ok_or( + BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), + )?; let send_origin = T::ExecuteXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone()) .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; - if !T::XcmTeleportFilter::contains(&(origin_location, vec![asset.clone()])) { + if !T::XcmTeleportFilter::contains(&(origin_location, assets.clone().into_inner())) { return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) } let recipient = [0u8; 32]; - let versioned_dest: VersionedMultiLocation = T::ReachableDest::get().ok_or( - BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), - )? - .into(); + let versioned_dest: VersionedMultiLocation = destination.into(); let versioned_beneficiary: VersionedMultiLocation = AccountId32 { network: None, id: recipient.into() }.into(); - let versioned_assets: VersionedMultiAssets = asset.into(); + let versioned_assets: VersionedMultiAssets = assets.into(); }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) reserve_transfer_assets { - let asset: MultiAsset = (Here, 10).into(); + let (assets, destination) = T::ReserveTransferableAssets::get().ok_or( + BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), + )?; let send_origin = T::ExecuteXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone()) .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; - if !T::XcmReserveTransferFilter::contains(&(origin_location, vec![asset.clone()])) { + if !T::XcmReserveTransferFilter::contains(&(origin_location, assets.clone().into_inner())) { return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) } let recipient = [0u8; 32]; - let versioned_dest: VersionedMultiLocation = T::ReachableDest::get().ok_or( - BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), - )? - .into(); + let versioned_dest: VersionedMultiLocation = destination.into(); let versioned_beneficiary: VersionedMultiLocation = AccountId32 { network: None, id: recipient.into() }.into(); - let versioned_assets: VersionedMultiAssets = asset.into(); + let versioned_assets: VersionedMultiAssets = assets.into(); }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) execute { diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 832e630e637d..d7ea85aefc52 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -265,6 +265,20 @@ pub mod pallet { /// If `None`, the benchmarks that depend on a reachable destination will be skipped. #[cfg(feature = "runtime-benchmarks")] type ReachableDest: Get>; + + /// A `(MultiAssets, MultiLocation)` pair representing assets and the destination they can + /// be teleported to. Used only in benchmarks. + /// + /// If `None`, the benchmarks that depend on `TeleportableAssets` will be skipped. + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets: Get>; + + /// A `(MultiAssets, MultiLocation)` pair representing assets and the destination they can + /// be reserve-transferred to. Used only in benchmarks. + /// + /// If `None`, the benchmarks that depend on `ReserveTransferableAssets` will be skipped. + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets: Get>; } #[pallet::event] diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index b269fcea394b..56b97bef4fba 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -252,6 +252,15 @@ impl pallet_balances::Config for Test { type MaxFreezes = ConstU32<0>; } +/// Simple conversion of `u32` into an `AssetId` for use in benchmarking. +pub struct XcmBenchmarkHelper; +#[cfg(feature = "runtime-benchmarks")] +impl pallet_assets::BenchmarkHelper for XcmBenchmarkHelper { + fn create_asset_id_parameter(id: u32) -> MultiLocation { + MultiLocation { parents: 1, interior: X1(Parachain(id)) } + } +} + impl pallet_assets::Config for Test { type RuntimeEvent = RuntimeEvent; type Balance = Balance; @@ -272,7 +281,7 @@ impl pallet_assets::Config for Test { type Extra = (); type RemoveItemsLimit = ConstU32<5>; #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type BenchmarkHelper = XcmBenchmarkHelper; } // This child parachain acts as trusted reserve for its assets in tests. @@ -431,6 +440,14 @@ parameter_types! { #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parachain(1000).into()); + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + vec![Usdt::get()].into(), + UsdtTeleportLocation::get(), + )); + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + vec![ForeignAsset::get()].into(), + ForeignReserveLocation::get(), + )); } impl pallet_xcm::Config for Test { @@ -448,6 +465,7 @@ impl pallet_xcm::Config for Test { type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; type AdvertisedXcmVersion = AdvertisedXcmVersion; + type AdminOrigin = EnsureRoot; type TrustedLockers = (); type SovereignAccountOf = AccountId32Aliases<(), AccountId32>; type Currency = Balances; @@ -458,7 +476,10 @@ impl pallet_xcm::Config for Test { type WeightInfo = TestWeightInfo; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl origin::Config for Test {} From 9827c3b6201c9b40763e8dcc16cb6775763ae289 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 10 Oct 2023 18:15:24 +0300 Subject: [PATCH 030/124] fix pallet-xcm benchmarks for all runtimes --- .../runtime/src/xcm_config.rs | 15 +++++++++++++-- .../assets/asset-hub-kusama/src/xcm_config.rs | 18 ++++++++++++++++-- .../asset-hub-polkadot/src/xcm_config.rs | 18 ++++++++++++++++-- .../assets/asset-hub-westend/src/xcm_config.rs | 18 ++++++++++++++++-- .../bridge-hub-kusama/src/xcm_config.rs | 15 +++++++++++++-- .../bridge-hub-polkadot/src/xcm_config.rs | 15 +++++++++++++-- .../bridge-hub-rococo/src/xcm_config.rs | 15 +++++++++++++-- .../collectives-polkadot/src/xcm_config.rs | 15 +++++++++++++-- .../contracts-rococo/src/xcm_config.rs | 18 ++++++++++++++++-- .../runtimes/testing/penpal/src/xcm_config.rs | 15 +++++++++++++-- .../testing/rococo-parachain/src/lib.rs | 18 ++++++++++++++++-- polkadot/runtime/rococo/src/xcm_config.rs | 18 ++++++++++++++++-- .../runtime/test-runtime/src/xcm_config.rs | 8 +++++++- polkadot/xcm/xcm-builder/src/tests/pay/mock.rs | 8 +++++++- polkadot/xcm/xcm-builder/tests/mock/mod.rs | 8 +++++++- .../xcm/xcm-simulator/example/src/parachain.rs | 8 +++++++- .../xcm-simulator/example/src/relay_chain.rs | 8 +++++++- .../xcm/xcm-simulator/fuzzer/src/parachain.rs | 8 +++++++- .../xcm-simulator/fuzzer/src/relay_chain.rs | 8 +++++++- 19 files changed, 223 insertions(+), 31 deletions(-) diff --git a/cumulus/parachain-template/runtime/src/xcm_config.rs b/cumulus/parachain-template/runtime/src/xcm_config.rs index 353f68d22e35..0b82dba25f28 100644 --- a/cumulus/parachain-template/runtime/src/xcm_config.rs +++ b/cumulus/parachain-template/runtime/src/xcm_config.rs @@ -153,6 +153,13 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Teleports are disabled + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; + // We can reserve transfer relay/native token between us and Relay. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); } impl pallet_xcm::Config for Runtime { @@ -180,11 +187,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = pallet_xcm::TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index 0c197598f889..d173dd8f338b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -540,6 +540,16 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported between AH and Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // We can reserve transfer some local token to Relay. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + Parent.into(), + )); } impl pallet_xcm::Config for Runtime { @@ -571,11 +581,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index 65cf62a610f4..6195de606e51 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -464,6 +464,16 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported between AH and Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // We can reserve transfer some local token to Relay. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + Parent.into(), + )); } impl pallet_xcm::Config for Runtime { @@ -495,11 +505,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index a0921c50dc59..dab9a1e5773e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -550,6 +550,16 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported between AH and Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // We can reserve transfer some local token to Relay. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + Parent.into(), + )); } impl pallet_xcm::Config for Runtime { @@ -577,11 +587,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs index 696462be9c45..0fc4b6aab181 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs @@ -229,6 +229,13 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported between BH and Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // Reserve transfers are disabled on BH. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { @@ -259,11 +266,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs index 0965600c2468..22b138dfc8a0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs @@ -233,6 +233,13 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported between BH and Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // Reserve transfers are disabled on BH. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { @@ -263,11 +270,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index e3d8645d49e7..989fd61111b1 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -276,6 +276,13 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported between BH and Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // Reserve transfers are disabled on BH. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { @@ -305,11 +312,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs index f802073bfbbb..b828df5f0feb 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs @@ -288,6 +288,13 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported between BH and Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // Reserve transfers are disabled on Collectives. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } /// Type to convert the Fellows origin to a Plurality `MultiLocation` value. @@ -317,11 +324,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs index 7433b8e94d6c..ddb91a3448fb 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs @@ -188,6 +188,16 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported to Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // Act as reserve for native token when sending to random parachain. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parachain(4321).into(), + )); } impl pallet_xcm::Config for Runtime { @@ -216,11 +226,15 @@ impl pallet_xcm::Config for Runtime { type MaxLockers = ConstU32<8>; // FIXME: Replace with benchmarked weight info type WeightInfo = pallet_xcm::TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index f2ffc451b10e..3bcc20784b0f 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -315,6 +315,13 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported to Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // Disable reserve transfers benchmarks for penpal. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { @@ -342,11 +349,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = pallet_xcm::TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 50c5a445c25f..e8a579430fd2 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -467,6 +467,16 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported to/from Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // We can reserve transfer some AH local token to/from AH. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(SystemAssetHubLocation::get()) }.into(), + SystemAssetHubLocation::get(), + )); } impl pallet_xcm::Config for Runtime { @@ -490,11 +500,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = pallet_xcm::TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index b84d2335a699..9c1b878d841c 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -206,7 +206,17 @@ parameter_types! { #[cfg(feature = "runtime-benchmarks")] parameter_types! { - pub ReachableDest: Option = Some(Parachain(1000).into()); + pub ReachableDest: Option = Some(AssetHub::get()); + // Relay/native token can be teleported to/from AH. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + AssetHub::get(), + )); + // We can reserve transfer native token to some random parachain. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + Parachain(4321).into(), + )); } /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior @@ -262,7 +272,11 @@ impl pallet_xcm::Config for Runtime { type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = crate::weights::pallet_xcm::WeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } diff --git a/polkadot/runtime/test-runtime/src/xcm_config.rs b/polkadot/runtime/test-runtime/src/xcm_config.rs index 2113bbae66ad..02a89a0c80f3 100644 --- a/polkadot/runtime/test-runtime/src/xcm_config.rs +++ b/polkadot/runtime/test-runtime/src/xcm_config.rs @@ -126,6 +126,8 @@ impl xcm_executor::Config for XcmConfig { #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(xcm::latest::Junctions::Here.into()); + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for crate::Runtime { @@ -153,7 +155,11 @@ impl pallet_xcm::Config for crate::Runtime { type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index 5b6fa3ee5a0b..9bb32cb798d7 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -248,6 +248,8 @@ type SovereignAccountOf = ( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parachain(1000).into()); + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Test { @@ -273,9 +275,13 @@ impl pallet_xcm::Config for Test { type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } pub const UNITS: Balance = 1_000_000_000_000; diff --git a/polkadot/xcm/xcm-builder/tests/mock/mod.rs b/polkadot/xcm/xcm-builder/tests/mock/mod.rs index 363748940ca6..0dd9436684e1 100644 --- a/polkadot/xcm/xcm-builder/tests/mock/mod.rs +++ b/polkadot/xcm/xcm-builder/tests/mock/mod.rs @@ -212,6 +212,8 @@ pub type LocalOriginToLocation = SignedToAccountId32 = Some(Here.into()); + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { @@ -238,9 +240,13 @@ impl pallet_xcm::Config for Runtime { type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl origin::Config for Runtime {} diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain.rs b/polkadot/xcm/xcm-simulator/example/src/parachain.rs index bc7cba313828..dac27cc27b8a 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/parachain.rs @@ -401,6 +401,8 @@ pub type LocalOriginToLocation = SignedToAccountId32 = Some(Parent.into()); + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } pub struct TrustedLockerCase(PhantomData); @@ -442,9 +444,13 @@ impl pallet_xcm::Config for Runtime { type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } type Block = frame_system::mocking::MockBlock; diff --git a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs index 4e9195a8454f..9fbe30319ae8 100644 --- a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs @@ -201,6 +201,8 @@ pub type LocalOriginToLocation = SignedToAccountId32 = Some(Parachain(1).into()); + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { @@ -227,9 +229,13 @@ impl pallet_xcm::Config for Runtime { type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } parameter_types! { diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index 95f875eca06e..339b68d75c0f 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -315,6 +315,8 @@ pub type LocalOriginToLocation = SignedToAccountId32 = Some(Parent.into()); + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { @@ -340,9 +342,13 @@ impl pallet_xcm::Config for Runtime { type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } type Block = frame_system::mocking::MockBlock; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs index a29ead9e6c3b..fe3950471ec1 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs @@ -165,6 +165,8 @@ pub type LocalOriginToLocation = SignedToAccountId32 = Some(Parachain(1).into()); + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { @@ -191,9 +193,13 @@ impl pallet_xcm::Config for Runtime { type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; - type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } parameter_types! { From 23588a8e3966c63b1945bffb077e6a4efc0f6bd1 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 11 Oct 2023 11:55:34 +0300 Subject: [PATCH 031/124] address review comments --- .../runtimes/assets/test-utils/src/test_cases.rs | 12 ++++++++---- polkadot/xcm/pallet-xcm/src/mock.rs | 1 + polkadot/xcm/src/v3/junction.rs | 8 -------- polkadot/xcm/src/v3/multilocation.rs | 2 +- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 9ac68e2fbddf..133132507a38 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -158,12 +158,13 @@ pub fn teleports_for_native_asset_works< // 2. try to teleport asset back to the relaychain { let dest = MultiLocation::parent(); - let dest_beneficiary = MultiLocation::parent() + let mut dest_beneficiary = MultiLocation::parent() .appended_with(AccountId32 { network: None, id: sp_runtime::AccountId32::new([3; 32]).into(), }) .unwrap(); + dest_beneficiary.reanchor(&dest, Here.into()).unwrap(); let target_account_balance_before_teleport = >::free_balance(&target_account); @@ -206,12 +207,13 @@ pub fn teleports_for_native_asset_works< { let other_para_id = 2345; let dest = MultiLocation::new(1, X1(Parachain(other_para_id))); - let dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id))) + let mut dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id))) .appended_with(AccountId32 { network: None, id: sp_runtime::AccountId32::new([3; 32]).into(), }) .unwrap(); + dest_beneficiary.reanchor(&dest, Here.into()).unwrap(); let target_account_balance_before_teleport = >::free_balance(&target_account); @@ -513,12 +515,13 @@ pub fn teleports_for_foreign_assets_works< // 2. try to teleport asset back to source parachain (foreign_para_id) { let dest = MultiLocation::new(1, X1(Parachain(foreign_para_id))); - let dest_beneficiary = MultiLocation::new(1, X1(Parachain(foreign_para_id))) + let mut dest_beneficiary = MultiLocation::new(1, X1(Parachain(foreign_para_id))) .appended_with(AccountId32 { network: None, id: sp_runtime::AccountId32::new([3; 32]).into(), }) .unwrap(); + dest_beneficiary.reanchor(&dest, Here.into()).unwrap(); let target_account_balance_before_teleport = >::balance( @@ -1401,12 +1404,13 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< let other_para_id = 2345; let native_asset = MultiLocation::parent(); let dest = MultiLocation::new(1, X1(Parachain(other_para_id))); - let dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id))) + let mut dest_beneficiary = MultiLocation::new(1, X1(Parachain(other_para_id))) .appended_with(AccountId32 { network: None, id: sp_runtime::AccountId32::new([3; 32]).into(), }) .unwrap(); + dest_beneficiary.reanchor(&dest, Here.into()).unwrap(); let reserve_account = LocationToAccountId::convert_location(&dest) .expect("Sovereign account for reserves"); diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 56b97bef4fba..f95d80244533 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -252,6 +252,7 @@ impl pallet_balances::Config for Test { type MaxFreezes = ConstU32<0>; } +#[cfg(feature = "runtime-benchmarks")] /// Simple conversion of `u32` into an `AssetId` for use in benchmarking. pub struct XcmBenchmarkHelper; #[cfg(feature = "runtime-benchmarks")] diff --git a/polkadot/xcm/src/v3/junction.rs b/polkadot/xcm/src/v3/junction.rs index cd6d4f85dc26..b5dd5bc7c88f 100644 --- a/polkadot/xcm/src/v3/junction.rs +++ b/polkadot/xcm/src/v3/junction.rs @@ -437,14 +437,6 @@ impl Junction { _ => {}, } } - - /// Specifies whether junction identifies a chain. - pub fn is_chain_identifier(&self) -> bool { - match self { - Junction::Parachain(_) | Junction::GlobalConsensus(_) => true, - _ => false, - } - } } #[cfg(test)] diff --git a/polkadot/xcm/src/v3/multilocation.rs b/polkadot/xcm/src/v3/multilocation.rs index 0f226a1f1565..f948340abcb5 100644 --- a/polkadot/xcm/src/v3/multilocation.rs +++ b/polkadot/xcm/src/v3/multilocation.rs @@ -449,7 +449,7 @@ impl MultiLocation { pub fn chain_location(mut self) -> MultiLocation { // start popping junctions until we reach chain identifier while let Some(j) = self.last() { - if j.is_chain_identifier() { + if matches!(j, Junction::Parachain(_) | Junction::GlobalConsensus(_)) { // return chain subsection return self } else { From 931e09371562d6ffaa2cb7fb09b9a43ea5901e0a Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 11 Oct 2023 12:35:19 +0300 Subject: [PATCH 032/124] expose TransferType through XcmExecutor::traits::AssetTransferSupport instead of pallet_xcm --- Cargo.lock | 1 + polkadot/xcm/pallet-xcm/src/lib.rs | 77 +++++-------------- polkadot/xcm/xcm-executor/Cargo.toml | 2 + polkadot/xcm/xcm-executor/src/lib.rs | 4 +- .../xcm-executor/src/traits/asset_transfer.rs | 61 ++++++++++++++- polkadot/xcm/xcm-executor/src/traits/mod.rs | 2 +- 6 files changed, 82 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 30bd4a043b80..6bdb96373676 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17718,6 +17718,7 @@ dependencies = [ "impl-trait-for-tuples", "log", "parity-scale-codec", + "scale-info", "sp-arithmetic", "sp-core", "sp-io", diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index d7ea85aefc52..f25c3964cee1 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -41,7 +41,9 @@ use sp_runtime::{ }; use sp_std::{boxed::Box, marker::PhantomData, prelude::*, result::Result, vec}; use xcm::{latest::QueryResponseInfo, prelude::*}; -use xcm_executor::traits::{AssetTransferFilter, ConvertOrigin, Properties}; +use xcm_executor::traits::{ + AssetTransferError, AssetTransferSupport, ConvertOrigin, Properties, TransferType, +}; use frame_support::{ dispatch::GetDispatchInfo, pallet_prelude::*, traits::WithdrawReasons, PalletId, @@ -206,7 +208,7 @@ pub mod pallet { type XcmExecuteFilter: Contains<(MultiLocation, Xcm<::RuntimeCall>)>; /// Something to execute an XCM message. - type XcmExecutor: ExecuteXcm<::RuntimeCall> + AssetTransferFilter; + type XcmExecutor: ExecuteXcm<::RuntimeCall> + AssetTransferSupport; /// Our XCM filter which messages to be teleported using the dedicated extrinsic must pass. type XcmTeleportFilter: Contains<(MultiLocation, Vec)>; @@ -443,7 +445,7 @@ pub mod pallet { /// The location is invalid since it already has a subscription from us. AlreadySubscribed, /// Invalid asset for the operation. - InvalidAsset, + InvalidAsset(AssetTransferError), /// The owner does not own (all) of the asset that they wish to do the operation on. LowBalance, /// The asset owner has too many locks on the asset. @@ -456,8 +458,6 @@ pub mod pallet { LockNotFound, /// The unlock operation cannot succeed because there are still consumers of the lock. InUse, - /// Reserve chain could not be determined for assets to be transferred. - UnknownReserve, /// Too many assets with different reserve locations have been attempted for transfer. TooManyReserves, } @@ -1211,54 +1211,6 @@ impl QueryHandler for Pallet { } } -#[derive(Copy, Clone, PartialEq, Debug)] -enum TransferType { - Teleport, - LocalReserve, - DestinationReserve, - RemoteReserve(MultiLocation), -} - -impl TransferType { - /// Determine transfer type to be used for transferring `asset` from local chain to `dest`. - pub fn determine_for( - asset: &MultiAsset, - dest: &MultiLocation, - ) -> Result> { - if ::IsTeleporter::contains(asset, dest) { - // we trust destination for teleporting asset - return Ok(TransferType::Teleport) - } else if ::IsReserve::contains(asset, dest) { - // we trust destination as asset reserve location - return Ok(TransferType::DestinationReserve) - } - - // try to determine reserve location based on asset id/location - let asset_location = match asset.id { - Concrete(location) => Ok(location.chain_location()), - _ => Err(Error::::InvalidAsset), - }?; - if asset_location == MultiLocation::here() || - ::IsTeleporter::contains( - asset, - &asset_location, - ) { - // local asset, or remote location that allows local teleports => local reserve - Ok(TransferType::LocalReserve) - } else if ::IsReserve::contains( - asset, - &asset_location, - ) { - // remote location that is recognized as reserve location for asset - Ok(TransferType::RemoteReserve(asset_location)) - } else { - // remote location that is not configured either as teleporter or reserve => cannot - // determine asset reserve - Err(Error::::UnknownReserve) - } - } -} - impl Pallet { /// Validate `assets` to be reserve-transferred and return their reserve location. fn validate_assets_and_find_reserve( @@ -1270,9 +1222,11 @@ impl Pallet { // Ensure fungible asset. ensure!( matches!(asset.fun, Fungibility::Fungible(x) if !x.is_zero()), - Error::::InvalidAsset + Error::::InvalidAsset(AssetTransferError::NotFungible) ); - let transfer_type = TransferType::determine_for::(&asset, dest)?; + let transfer_type = + ::determine_for(&asset, dest) + .map_err(Error::::InvalidAsset)?; // Ensure asset is not teleportable to `dest`. ensure!(transfer_type != TransferType::Teleport, Error::::Filtered); if let Some(reserve) = reserve.as_ref() { @@ -1310,7 +1264,9 @@ impl Pallet { return Err(Error::::Empty.into()) } let mut fees = assets.swap_remove(fee_asset_item as usize); - let fees_transfer_type = TransferType::determine_for::(&fees, &dest)?; + let fees_transfer_type = + ::determine_for(&fees, &dest) + .map_err(Error::::InvalidAsset)?; let assets_transfer_type = if assets.is_empty() { // Single asset to transfer (one used for fees where transfer type is determined above). ensure!(fees_transfer_type != TransferType::Teleport, Error::::Filtered); @@ -1353,7 +1309,8 @@ impl Pallet { assets_reserve, beneficiary, vec![fees.clone()], - TransferType::determine_for::(&fees, &assets_reserve)?, + ::determine_for(&fees, &assets_reserve) + .map_err(Error::::InvalidAsset)?, fees.clone(), quarter_weight_limit.clone(), )?; @@ -1414,7 +1371,9 @@ impl Pallet { ensure!(T::XcmTeleportFilter::contains(&value), Error::::Filtered); let (origin_location, assets) = value; for asset in assets.iter() { - let transfer_type = TransferType::determine_for::(asset, &dest)?; + let transfer_type = + ::determine_for(asset, &dest) + .map_err(Error::::InvalidAsset)?; ensure!(matches!(transfer_type, TransferType::Teleport), Error::::Filtered); } let fees = assets.get(fee_asset_item as usize).ok_or(Error::::Empty)?.clone(); @@ -1922,7 +1881,7 @@ impl Pallet { *amount = amount.saturating_div(2); Ok(()) }, - NonFungible(_) => Err(Error::::InvalidAsset), + NonFungible(_) => Err(Error::::InvalidAsset(AssetTransferError::NotFungible)), } } } diff --git a/polkadot/xcm/xcm-executor/Cargo.toml b/polkadot/xcm/xcm-executor/Cargo.toml index 902f55901d6c..c6f3a11fbe22 100644 --- a/polkadot/xcm/xcm-executor/Cargo.toml +++ b/polkadot/xcm/xcm-executor/Cargo.toml @@ -10,6 +10,7 @@ version = "1.0.0" impl-trait-for-tuples = "0.2.2" environmental = { version = "1.1.4", default-features = false } parity-scale-codec = { version = "3.6.1", default-features = false, features = ["derive"] } +scale-info = { version = "2.5.0", default-features = false, features = ["derive", "serde"] } xcm = { package = "staging-xcm", path = "..", default-features = false } sp-std = { path = "../../../substrate/primitives/std", default-features = false } sp-io = { path = "../../../substrate/primitives/io", default-features = false } @@ -33,6 +34,7 @@ std = [ "frame-support/std", "log/std", "parity-scale-codec/std", + "scale-info/std", "sp-arithmetic/std", "sp-core/std", "sp-io/std", diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index a5575b6952f1..bd6b1d79a11e 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -38,7 +38,7 @@ use traits::{ mod assets; pub use assets::Assets; mod config; -use crate::traits::AssetTransferFilter; +use crate::traits::AssetTransferSupport; pub use config::Config; /// A struct to specify how fees are being paid. @@ -255,7 +255,7 @@ impl ExecuteXcm for XcmExecutor AssetTransferFilter for XcmExecutor { +impl AssetTransferSupport for XcmExecutor { type IsReserve = Config::IsReserve; type IsTeleporter = Config::IsTeleporter; } diff --git a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs index c8fdc582bf11..c75c48ead6ef 100644 --- a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs +++ b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs @@ -14,11 +14,36 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use frame_support::traits::ContainsPair; +use frame_support::traits::{ContainsPair, PalletError}; +use scale_info::TypeInfo; +use sp_runtime::codec::{Decode, Encode}; use xcm::prelude::*; -/// A trait for identifying asset transfer type. -pub trait AssetTransferFilter { +#[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] +pub enum Error { + /// Invalid non-concrete asset. + NotConcrete, + /// Invalid non-fungible asset. + NotFungible, + /// Reserve chain could not be determined for assets. + UnknownReserve, +} + +impl PalletError for Error { + const MAX_ENCODED_SIZE: usize = 1; +} + +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum TransferType { + Teleport, + LocalReserve, + DestinationReserve, + RemoteReserve(MultiLocation), +} + +/// A trait for identifying asset transfer type based on `IsTeleporter` and `IsReserve` +/// configurations. +pub trait AssetTransferSupport { /// Combinations of (Asset, Location) pairs which we trust as reserves. Meaning /// reserve-based-transfers are to be used for assets matching this filter. type IsReserve: ContainsPair; @@ -26,4 +51,34 @@ pub trait AssetTransferFilter { /// Combinations of (Asset, Location) pairs which we trust as teleporters. Meaning teleports are /// to be used for assets matching this filter. type IsTeleporter: ContainsPair; + + /// Determine transfer type to be used for transferring `asset` from local chain to `dest`. + fn determine_for(asset: &MultiAsset, dest: &MultiLocation) -> Result { + if Self::IsTeleporter::contains(asset, dest) { + // we trust destination for teleporting asset + return Ok(TransferType::Teleport) + } else if Self::IsReserve::contains(asset, dest) { + // we trust destination as asset reserve location + return Ok(TransferType::DestinationReserve) + } + + // try to determine reserve location based on asset id/location + let asset_location = match asset.id { + Concrete(location) => Ok(location.chain_location()), + _ => Err(Error::NotConcrete), + }?; + if asset_location == MultiLocation::here() || + Self::IsTeleporter::contains(asset, &asset_location) + { + // if local asset, or remote location that allows local teleports => local reserve + Ok(TransferType::LocalReserve) + } else if Self::IsReserve::contains(asset, &asset_location) { + // remote location that is recognized as reserve location for asset + Ok(TransferType::RemoteReserve(asset_location)) + } else { + // remote location that is not configured either as teleporter or reserve => cannot + // determine asset reserve + Err(Error::UnknownReserve) + } + } } diff --git a/polkadot/xcm/xcm-executor/src/traits/mod.rs b/polkadot/xcm/xcm-executor/src/traits/mod.rs index 201634c7bcbb..1723da0c3f40 100644 --- a/polkadot/xcm/xcm-executor/src/traits/mod.rs +++ b/polkadot/xcm/xcm-executor/src/traits/mod.rs @@ -25,7 +25,7 @@ pub use asset_exchange::AssetExchange; mod asset_lock; pub use asset_lock::{AssetLock, Enact, LockError}; mod asset_transfer; -pub use asset_transfer::AssetTransferFilter; +pub use asset_transfer::{AssetTransferSupport, Error as AssetTransferError, TransferType}; mod export; pub use export::{export_xcm, validate_export, ExportXcm}; mod fee_manager; From 09badd6b0a93a43dd248179c02b50a19e805a8b5 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 13 Oct 2023 14:09:54 +0300 Subject: [PATCH 033/124] allow transfer for non-fungible assets too --- polkadot/xcm/pallet-xcm/src/lib.rs | 19 +++++++++---------- polkadot/xcm/pallet-xcm/src/tests.rs | 12 ++++++------ .../xcm-executor/src/traits/asset_transfer.rs | 9 +++++++-- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index f25c3964cee1..75ec7b041fed 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1219,11 +1219,10 @@ impl Pallet { ) -> Result> { let mut reserve = None; for asset in assets.iter() { - // Ensure fungible asset. - ensure!( - matches!(asset.fun, Fungibility::Fungible(x) if !x.is_zero()), - Error::::InvalidAsset(AssetTransferError::NotFungible) - ); + if let Fungible(x) = asset.fun { + // If fungible asset, ensure non-zero amount. + ensure!(!x.is_zero(), Error::::Empty); + } let transfer_type = ::determine_for(&asset, dest) .map_err(Error::::InvalidAsset)?; @@ -1300,7 +1299,7 @@ impl Pallet { // and half at destination. if let TransferType::RemoteReserve(assets_reserve) = assets_transfer_type { // Halve amount of fees, each half will be sent to one chain. - Self::halve_fungible_asset(&mut fees)?; + Self::halve_fees(&mut fees)?; // Halve weight limit again to be used for the two fees transfers. let quarter_weight_limit = Self::halve_weight_limit(&weight_limit); // Send half the `fees` to `beneficiary` on assets-reserve chain. @@ -1874,14 +1873,14 @@ impl Pallet { } } - /// Halve `asset`s fungible amount. - pub(crate) fn halve_fungible_asset(asset: &mut MultiAsset) -> Result<(), Error> { - match &mut asset.fun { + /// Halve `fees` fungible amount. + pub(crate) fn halve_fees(fees: &mut MultiAsset) -> Result<(), Error> { + match &mut fees.fun { Fungible(amount) => { *amount = amount.saturating_div(2); Ok(()) }, - NonFungible(_) => Err(Error::::InvalidAsset(AssetTransferError::NotFungible)), + NonFungible(_) => Err(Error::::FeesNotMet), } } } diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests.rs index 3b343e6a3977..5c8a176c47ae 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests.rs @@ -798,8 +798,8 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works let mut expected_fee = fee_asset.reanchored(&dest, context).unwrap(); // fees are split between the asset-reserve chain and the destination chain - crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); - crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); + crate::Pallet::::halve_fees(&mut expected_fee_on_reserve).unwrap(); + crate::Pallet::::halve_fees(&mut expected_fee).unwrap(); // balances checks before assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); @@ -1172,8 +1172,8 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve let mut expected_fee = fee_asset.reanchored(&dest, context).unwrap(); // fees are split between the asset-reserve chain and the destination chain - crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); - crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); + crate::Pallet::::halve_fees(&mut expected_fee_on_reserve).unwrap(); + crate::Pallet::::halve_fees(&mut expected_fee).unwrap(); // balances checks before assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); @@ -1971,8 +1971,8 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() let mut expected_fee = fee_asset.reanchored(&dest, context).unwrap(); // fees are split between the asset-reserve chain and the destination chain - crate::Pallet::::halve_fungible_asset(&mut expected_fee_on_reserve).unwrap(); - crate::Pallet::::halve_fungible_asset(&mut expected_fee).unwrap(); + crate::Pallet::::halve_fees(&mut expected_fee_on_reserve).unwrap(); + crate::Pallet::::halve_fees(&mut expected_fee).unwrap(); // balances checks before assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); diff --git a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs index c75c48ead6ef..7d6609a24226 100644 --- a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs +++ b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs @@ -19,12 +19,11 @@ use scale_info::TypeInfo; use sp_runtime::codec::{Decode, Encode}; use xcm::prelude::*; +/// Errors related to determining asset transfer support. #[derive(Copy, Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo)] pub enum Error { /// Invalid non-concrete asset. NotConcrete, - /// Invalid non-fungible asset. - NotFungible, /// Reserve chain could not be determined for assets. UnknownReserve, } @@ -33,11 +32,17 @@ impl PalletError for Error { const MAX_ENCODED_SIZE: usize = 1; } +/// Specify which type of asset transfer is required for a particular `(origin, asset, dest)` +/// combination. #[derive(Copy, Clone, PartialEq, Debug)] pub enum TransferType { + /// should teleport `asset` to `dest` Teleport, + /// should reserve-transfer `asset` to `dest`, using local chain as reserve LocalReserve, + /// should reserve-transfer `asset` to `dest`, using `dest` as reserve DestinationReserve, + /// should reserve-transfer `asset` to `dest`, using remote chain `MultiLocation` as reserve RemoteReserve(MultiLocation), } From f8e8b4abe3b516ba8beb80ed8f8b6304b51ac4e8 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 20 Oct 2023 12:10:28 +0300 Subject: [PATCH 034/124] fix merge damage --- .../src/tests/reserve_transfer.rs | 323 +++--------------- .../src/tests/reserve_transfer.rs | 216 +----------- .../assets/asset-hub-rococo/tests/tests.rs | 6 - .../assets/test-utils/src/test_cases.rs | 8 - 4 files changed, 68 insertions(+), 485 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index fb25607c635e..073c93ec254a 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -15,38 +15,6 @@ use crate::*; use asset_hub_rococo_runtime::xcm_config::XcmConfig as AssetHubRococoXcmConfig; -use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig; - -fn relay_origin_assertions(t: RelayToSystemParaTest) { - type RuntimeEvent = ::RuntimeEvent; - - Rococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(630_092_000, 6_196))); - - assert_expected_events!( - Rococo, - vec![ - // Amount to reserve transfer is transferred to System Parachain's Sovereign account - RuntimeEvent::Balances(pallet_balances::Event::Transfer { from, to, amount }) => { - from: *from == t.sender.account_id, - to: *to == Rococo::sovereign_account_id_of( - t.args.dest - ), - amount: *amount == t.args.amount, - }, - ] - ); -} - -fn system_para_dest_assertions_incomplete(_t: RelayToSystemParaTest) { - AssetHubRococo::assert_dmp_queue_incomplete( - Some(Weight::from_parts(1_000_000_000, 0)), - Some(Error::UntrustedReserveLocation), - ); -} - -fn system_para_to_relay_assertions(_t: SystemParaToRelayTest) { - AssetHubRococo::assert_xcm_pallet_attempted_error(Some(XcmError::Barrier)) -} fn system_para_to_para_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -99,48 +67,6 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { ); } -fn relay_limited_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult { - ::XcmPallet::limited_reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - t.args.weight_limit, - ) -} - -fn relay_reserve_transfer_assets(t: RelayToSystemParaTest) -> DispatchResult { - ::XcmPallet::reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - ) -} - -fn system_para_limited_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult { - ::PolkadotXcm::limited_reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - t.args.weight_limit, - ) -} - -fn system_para_reserve_transfer_assets(t: SystemParaToRelayTest) -> DispatchResult { - ::PolkadotXcm::reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - ) -} - fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, @@ -152,145 +78,74 @@ fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) ) } -fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { - ::PolkadotXcm::reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - ) -} - /// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't /// work #[test] fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() { - // Init values for Relay Chain + let signed_origin = ::RuntimeOrigin::signed(RococoSender::get().into()); + let destination = Rococo::child_location_of(AssetHubRococo::para_id()); + let beneficiary: MultiLocation = + AccountId32Junction { network: None, id: AssetHubRococoReceiver::get().into() }.into(); let amount_to_send: Balance = ROCOCO_ED * 1000; - let test_args = TestContext { - sender: RococoSender::get(), - receiver: AssetHubRococoReceiver::get(), - args: relay_test_args(amount_to_send), - }; - - let mut test = RelayToSystemParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(relay_origin_assertions); - test.set_assertion::(system_para_dest_assertions_incomplete); - test.set_dispatchable::(relay_limited_reserve_transfer_assets); - test.assert(); - - let delivery_fees = Rococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + let assets: MultiAssets = (Here, amount_to_send).into(); + let fee_asset_item = 0; + + // this should fail + Rococo::execute_with(|| { + let result = ::XcmPallet::limited_reserve_transfer_assets( + signed_origin, + bx!(destination.into()), + bx!(beneficiary.into()), + bx!(assets.into()), + fee_asset_item, + WeightLimit::Unlimited, + ); + assert_err!( + result, + DispatchError::Module(sp_runtime::ModuleError { + index: 99, + error: [2, 0, 0, 0], + message: Some("Filtered") + }) + ); }); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); } -/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shoudln't work +/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work #[test] fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() { // Init values for System Parachain + let signed_origin = + ::RuntimeOrigin::signed(AssetHubRococoSender::get().into()); let destination = AssetHubRococo::parent_location(); let beneficiary_id = RococoReceiver::get(); + let beneficiary: MultiLocation = + AccountId32Junction { network: None, id: beneficiary_id.into() }.into(); let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000; - let assets = (Parent, amount_to_send).into(); - - let test_args = TestContext { - sender: AssetHubRococoSender::get(), - receiver: RococoReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), - }; - - let mut test = SystemParaToRelayTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(system_para_to_relay_assertions); - test.set_dispatchable::(system_para_limited_reserve_transfer_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - assert_eq!(sender_balance_before, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); -} - -/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work -#[test] -fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { - // Init values for Relay Chain - let amount_to_send: Balance = ROCOCO_ED * 1000; - let test_args = TestContext { - sender: RococoSender::get(), - receiver: AssetHubRococoReceiver::get(), - args: relay_test_args(amount_to_send), - }; - - let mut test = RelayToSystemParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - test.set_assertion::(relay_origin_assertions); - test.set_assertion::(system_para_dest_assertions_incomplete); - test.set_dispatchable::(relay_reserve_transfer_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - let delivery_fees = Rococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + let assets: MultiAssets = (Parent, amount_to_send).into(); + let fee_asset_item = 0; + + // this should fail + AssetHubRococo::execute_with(|| { + let result = + ::PolkadotXcm::limited_reserve_transfer_assets( + signed_origin, + bx!(destination.into()), + bx!(beneficiary.into()), + bx!(assets.into()), + fee_asset_item, + WeightLimit::Unlimited, + ); + assert_err!( + result, + DispatchError::Module(sp_runtime::ModuleError { + index: 31, + error: [2, 0, 0, 0], + message: Some("Filtered") + }) + ); }); - - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); -} - -/// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work -#[test] -fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { - // Init values for System Parachain - let destination = AssetHubRococo::parent_location(); - let beneficiary_id = RococoReceiver::get(); - let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000; - let assets = (Parent, amount_to_send).into(); - - let test_args = TestContext { - sender: AssetHubRococoSender::get(), - receiver: RococoReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), - }; - - let mut test = SystemParaToRelayTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(system_para_to_relay_assertions); - test.set_dispatchable::(system_para_reserve_transfer_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - assert_eq!(sender_balance_before, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); } /// Limited Reserve Transfers of native asset from System Parachain to Parachain should work @@ -331,44 +186,6 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { // transfers } -/// Reserve Transfers of native asset from System Parachain to Parachain should work -#[test] -fn reserve_transfer_native_asset_from_system_para_to_para() { - // Init values for System Parachain - let destination = AssetHubRococo::sibling_location_of(PenpalRococoA::para_id()); - let beneficiary_id = PenpalRococoAReceiver::get(); - let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000; - let assets = (Parent, amount_to_send).into(); - - let test_args = TestContext { - sender: AssetHubRococoSender::get(), - receiver: PenpalRococoAReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), - }; - - let mut test = SystemParaToParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - - test.set_assertion::(system_para_to_para_assertions); - // TODO: Add assertion for Penpal runtime. Right now message is failing with - // `UntrustedReserveLocation` - test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - - let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve - // transfers -} - /// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work #[test] fn limited_reserve_transfer_asset_from_system_para_to_para() { @@ -404,39 +221,3 @@ fn limited_reserve_transfer_asset_from_system_para_to_para() { .set_dispatchable::(system_para_to_para_limited_reserve_transfer_assets); system_para_test.assert(); } - -/// Reserve Transfers of a local asset from System Parachain to Parachain should work -#[test] -fn reserve_transfer_asset_from_system_para_to_para() { - // Force create asset from Relay Chain and mint assets for System Parachain's sender account - AssetHubRococo::force_create_and_mint_asset( - ASSET_ID, - ASSET_MIN_BALANCE, - true, - AssetHubRococoSender::get(), - Some(Weight::from_parts(1_019_445_000, 200_000)), - ASSET_MIN_BALANCE * 1000000, - ); - - // Init values for System Parachain - let destination = AssetHubRococo::sibling_location_of(PenpalRococoA::para_id()); - let beneficiary_id = PenpalRococoAReceiver::get(); - let amount_to_send = ASSET_MIN_BALANCE * 1000; - let assets = - (X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send) - .into(); - - let system_para_test_args = TestContext { - sender: AssetHubRococoSender::get(), - receiver: PenpalRococoAReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), - }; - - let mut system_para_test = SystemParaToParaTest::new(system_para_test_args); - - system_para_test.set_assertion::(system_para_to_para_assets_assertions); - // TODO: Add assertions when Penpal is able to manage assets - system_para_test - .set_dispatchable::(system_para_to_para_reserve_transfer_assets); - system_para_test.assert(); -} diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs index 701106fcb72c..c7a25dde78d3 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -15,7 +15,6 @@ use crate::*; use asset_hub_westend_runtime::xcm_config::XcmConfig; -use westend_runtime::xcm_config::XcmConfig as WestendXcmConfig; fn system_para_to_para_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -79,17 +78,10 @@ fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) ) } -fn system_para_to_para_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { - ::PolkadotXcm::reserve_transfer_assets( - t.signed_origin, - bx!(t.args.dest.into()), - bx!(t.args.beneficiary.into()), - bx!(t.args.assets.into()), - t.args.fee_asset_item, - ) -} - -fn do_reserve_transfer_native_asset_from_relay_to_system_para_fails(limited: bool) { +/// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't +/// work +#[test] +fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() { let signed_origin = ::RuntimeOrigin::signed(WestendSender::get().into()); let destination = Westend::child_location_of(AssetHubWestend::para_id()); let beneficiary: MultiLocation = @@ -100,24 +92,14 @@ fn do_reserve_transfer_native_asset_from_relay_to_system_para_fails(limited: boo // this should fail Westend::execute_with(|| { - let result = if limited { - ::XcmPallet::reserve_transfer_assets( - signed_origin, - bx!(destination.into()), - bx!(beneficiary.into()), - bx!(assets.into()), - fee_asset_item, - ) - } else { - ::XcmPallet::limited_reserve_transfer_assets( - signed_origin, - bx!(destination.into()), - bx!(beneficiary.into()), - bx!(assets.into()), - fee_asset_item, - WeightLimit::Unlimited, - ) - }; + let result = ::XcmPallet::limited_reserve_transfer_assets( + signed_origin, + bx!(destination.into()), + bx!(beneficiary.into()), + bx!(assets.into()), + fee_asset_item, + WeightLimit::Unlimited, + ); assert_err!( result, DispatchError::Module(sp_runtime::ModuleError { @@ -129,48 +111,9 @@ fn do_reserve_transfer_native_asset_from_relay_to_system_para_fails(limited: boo }); } -/// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't -/// work -#[test] -fn limited_reserve_transfer_native_asset_from_relay_to_system_para_fails() { - // Init values for Relay Chain - let amount_to_send: Balance = WESTEND_ED * 1000; - let test_args = TestContext { - sender: WestendSender::get(), - receiver: AssetHubWestendReceiver::get(), - args: relay_test_args(amount_to_send), - }; - - let mut test = RelayToSystemParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(relay_origin_assertions); - test.set_assertion::(system_para_dest_assertions); - test.set_dispatchable::(relay_limited_reserve_transfer_assets); - test.assert(); - - let delivery_fees = Westend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); -} - -/// Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't work +/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work #[test] -fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { - do_reserve_transfer_native_asset_from_relay_to_system_para_fails(false); -} - -fn do_reserve_transfer_native_asset_from_system_para_to_relay_fails(limited: bool) { +fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() { // Init values for System Parachain let signed_origin = ::RuntimeOrigin::signed(AssetHubWestendSender::get().into()); @@ -184,15 +127,7 @@ fn do_reserve_transfer_native_asset_from_system_para_to_relay_fails(limited: boo // this should fail AssetHubWestend::execute_with(|| { - let result = if limited { - ::PolkadotXcm::reserve_transfer_assets( - signed_origin, - bx!(destination.into()), - bx!(beneficiary.into()), - bx!(assets.into()), - fee_asset_item, - ) - } else { + let result = ::PolkadotXcm::limited_reserve_transfer_assets( signed_origin, bx!(destination.into()), @@ -200,8 +135,7 @@ fn do_reserve_transfer_native_asset_from_system_para_to_relay_fails(limited: boo bx!(assets.into()), fee_asset_item, WeightLimit::Unlimited, - ) - }; + ); assert_err!( result, DispatchError::Module(sp_runtime::ModuleError { @@ -213,46 +147,6 @@ fn do_reserve_transfer_native_asset_from_system_para_to_relay_fails(limited: boo }); } -/// Limited Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work -#[test] -fn reserve_transfer_native_asset_from_relay_to_system_para_fails() { - // Init values for Relay Chain - let amount_to_send: Balance = WESTEND_ED * 1000; - let test_args = TestContext { - sender: WestendSender::get(), - receiver: AssetHubWestendReceiver::get(), - args: relay_test_args(amount_to_send), - }; - - let mut test = RelayToSystemParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - let receiver_balance_before = test.receiver.balance; - - test.set_assertion::(relay_origin_assertions); - test.set_assertion::(system_para_dest_assertions); - test.set_dispatchable::(relay_reserve_transfer_assets); - test.assert(); - - let delivery_fees = Westend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) - }); - - let sender_balance_after = test.sender.balance; - let receiver_balance_after = test.receiver.balance; - - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - assert_eq!(receiver_balance_before, receiver_balance_after); -} - -/// Reserve Transfers of native asset from System Parachain to Relay Chain shouldn't work -#[test] -fn reserve_transfer_native_asset_from_system_para_to_relay_fails() { - do_reserve_transfer_native_asset_from_system_para_to_relay_fails(false); -} - /// Limited Reserve Transfers of native asset from System Parachain to Parachain should work #[test] fn limited_reserve_transfer_native_asset_from_system_para_to_para() { @@ -295,48 +189,6 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { // transfers } -/// Reserve Transfers of native asset from System Parachain to Parachain should work -#[test] -fn reserve_transfer_native_asset_from_system_para_to_para() { - // Init values for System Parachain - let destination = AssetHubWestend::sibling_location_of(PenpalWestendA::para_id()); - let beneficiary_id = PenpalWestendAReceiver::get(); - let amount_to_send: Balance = ASSET_HUB_WESTEND_ED * 1000; - let assets = (Parent, amount_to_send).into(); - - let test_args = TestContext { - sender: AssetHubWestendSender::get(), - receiver: PenpalWestendAReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), - }; - - let mut test = SystemParaToParaTest::new(test_args); - - let sender_balance_before = test.sender.balance; - - test.set_assertion::(system_para_to_para_assertions); - // TODO: Add assertion for Penpal runtime. Right now message is failing with - // `UntrustedReserveLocation` - test.set_dispatchable::(system_para_to_para_reserve_transfer_assets); - test.assert(); - - let sender_balance_after = test.sender.balance; - - let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::<::XcmSender>( - test.args.assets.clone(), - 0, - test.args.weight_limit, - test.args.beneficiary, - test.args.dest, - ) - }); - - assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve - // transfers -} - /// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work #[test] fn limited_reserve_transfer_asset_from_system_para_to_para() { @@ -372,39 +224,3 @@ fn limited_reserve_transfer_asset_from_system_para_to_para() { .set_dispatchable::(system_para_to_para_limited_reserve_transfer_assets); system_para_test.assert(); } - -/// Reserve Transfers of a local asset from System Parachain to Parachain should work -#[test] -fn reserve_transfer_asset_from_system_para_to_para() { - // Force create asset from Relay Chain and mint assets for System Parachain's sender account - AssetHubWestend::force_create_and_mint_asset( - ASSET_ID, - ASSET_MIN_BALANCE, - true, - AssetHubWestendSender::get(), - Some(Weight::from_parts(1_019_445_000, 200_000)), - ASSET_MIN_BALANCE * 1000000, - ); - - // Init values for System Parachain - let destination = AssetHubWestend::sibling_location_of(PenpalWestendA::para_id()); - let beneficiary_id = PenpalWestendAReceiver::get(); - let amount_to_send = ASSET_MIN_BALANCE * 1000; - let assets = - (X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send) - .into(); - - let system_para_test_args = TestContext { - sender: AssetHubWestendSender::get(), - receiver: PenpalWestendAReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), - }; - - let mut system_para_test = SystemParaToParaTest::new(system_para_test_args); - - system_para_test.set_assertion::(system_para_to_para_assets_assertions); - // TODO: Add assertions when Penpal is able to manage assets - system_para_test - .set_dispatchable::(system_para_to_para_reserve_transfer_assets); - system_para_test.assert(); -} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs index 7f48d5762883..19087387c092 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs @@ -527,12 +527,6 @@ asset_test_utils::include_teleports_for_native_asset_works!( _ => None, } }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), 1000 ); diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 12228d8fe5c3..79c8abceeb04 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -261,14 +261,6 @@ pub fn teleports_for_native_asset_works< },),) ); - let delivery_fees = - xcm_helpers::transfer_assets_delivery_fees::( - (native_asset_id, native_asset_to_teleport_away.into()).into(), - 0, - Unlimited, - dest_beneficiary, - dest, - ); // check balances assert_eq!( From 71bd4b305ebb648fc44b0c2c52ce70e2eb0bfea2 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 23 Oct 2023 12:22:48 +0300 Subject: [PATCH 035/124] fmt --- cumulus/pallets/xcmp-queue/src/bridging.rs | 4 +++- cumulus/pallets/xcmp-queue/src/tests.rs | 22 ++++++++++++------- .../assets/test-utils/src/test_cases.rs | 1 - .../procedural/src/pallet/expand/warnings.rs | 8 ++----- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/cumulus/pallets/xcmp-queue/src/bridging.rs b/cumulus/pallets/xcmp-queue/src/bridging.rs index 0fc3f1f39ea3..53238fe2bf7a 100644 --- a/cumulus/pallets/xcmp-queue/src/bridging.rs +++ b/cumulus/pallets/xcmp-queue/src/bridging.rs @@ -55,7 +55,9 @@ impl, Runtime: crate::Config> let sibling_bridge_hub_id: ParaId = SiblingBridgeHubParaId::get(); // let's find the channel's state with the sibling parachain, - let Some((outbound_state, queued_pages)) = pallet::Pallet::::outbound_channel_state(sibling_bridge_hub_id) else { + let Some((outbound_state, queued_pages)) = + pallet::Pallet::::outbound_channel_state(sibling_bridge_hub_id) + else { return false }; // suspended channel => it is congested diff --git a/cumulus/pallets/xcmp-queue/src/tests.rs b/cumulus/pallets/xcmp-queue/src/tests.rs index cf6d947609d2..bab7e92ca2de 100644 --- a/cumulus/pallets/xcmp-queue/src/tests.rs +++ b/cumulus/pallets/xcmp-queue/src/tests.rs @@ -410,9 +410,11 @@ fn verify_fee_factor_increase_and_decrease() { assert_eq!(DeliveryFeeFactor::::get(sibling_para_id), initial); // Sending the message right now is cheap - let (_, delivery_fees) = validate_send::(destination, xcm.clone()) - .expect("message can be sent; qed"); - let Fungible(delivery_fee_amount) = delivery_fees.inner()[0].fun else { unreachable!("asset is fungible; qed"); }; + let (_, delivery_fees) = + validate_send::(destination, xcm.clone()).expect("message can be sent; qed"); + let Fungible(delivery_fee_amount) = delivery_fees.inner()[0].fun else { + unreachable!("asset is fungible; qed"); + }; assert_eq!(delivery_fee_amount, 402_000_000); let smaller_xcm = Xcm(vec![ClearOrigin; 30]); @@ -422,19 +424,23 @@ fn verify_fee_factor_increase_and_decrease() { assert_ok!(send_xcm::(destination, xcm.clone())); // Size 520 assert_eq!(DeliveryFeeFactor::::get(sibling_para_id), FixedU128::from_float(1.05)); - for _ in 0..12 { // We finish at size 929 + for _ in 0..12 { + // We finish at size 929 assert_ok!(send_xcm::(destination, smaller_xcm.clone())); } assert!(DeliveryFeeFactor::::get(sibling_para_id) > FixedU128::from_float(1.88)); // Sending the message right now is expensive - let (_, delivery_fees) = validate_send::(destination, xcm.clone()) - .expect("message can be sent; qed"); - let Fungible(delivery_fee_amount) = delivery_fees.inner()[0].fun else { unreachable!("asset is fungible; qed"); }; + let (_, delivery_fees) = + validate_send::(destination, xcm.clone()).expect("message can be sent; qed"); + let Fungible(delivery_fee_amount) = delivery_fees.inner()[0].fun else { + unreachable!("asset is fungible; qed"); + }; assert_eq!(delivery_fee_amount, 758_030_955); // Fee factor only decreases in `take_outbound_messages` - for _ in 0..5 { // We take 5 100 byte pages + for _ in 0..5 { + // We take 5 100 byte pages XcmpQueue::take_outbound_messages(1); } assert!(DeliveryFeeFactor::::get(sibling_para_id) < FixedU128::from_float(1.72)); diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 79c8abceeb04..af9fc4475cf9 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -261,7 +261,6 @@ pub fn teleports_for_native_asset_works< },),) ); - // check balances assert_eq!( >::free_balance(&target_account), diff --git a/substrate/frame/support/procedural/src/pallet/expand/warnings.rs b/substrate/frame/support/procedural/src/pallet/expand/warnings.rs index 6ce2097c2684..030e3ddaf323 100644 --- a/substrate/frame/support/procedural/src/pallet/expand/warnings.rs +++ b/substrate/frame/support/procedural/src/pallet/expand/warnings.rs @@ -33,9 +33,7 @@ pub(crate) fn weight_witness_warning( if dev_mode { return } - let CallWeightDef::Immediate(w) = &method.weight else { - return - }; + let CallWeightDef::Immediate(w) = &method.weight else { return }; let partial_warning = Warning::new_deprecated("UncheckedWeightWitness") .old("not check weight witness data") @@ -66,9 +64,7 @@ pub(crate) fn weight_constant_warning( if dev_mode { return } - let syn::Expr::Lit(lit) = weight else { - return - }; + let syn::Expr::Lit(lit) = weight else { return }; let warning = Warning::new_deprecated("ConstantWeight") .index(warnings.len()) From 4ab90f7ffc993aeb21eb5a749bb81547703cd901 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 23 Oct 2023 12:43:50 +0300 Subject: [PATCH 036/124] pallet-xcm: split asset transfer tests to own file --- .../{tests.rs => tests/assets_transfer.rs} | 941 +---------------- polkadot/xcm/pallet-xcm/src/tests/mod.rs | 951 ++++++++++++++++++ 2 files changed, 962 insertions(+), 930 deletions(-) rename polkadot/xcm/pallet-xcm/src/{tests.rs => tests/assets_transfer.rs} (72%) create mode 100644 polkadot/xcm/pallet-xcm/src/tests/mod.rs diff --git a/polkadot/xcm/pallet-xcm/src/tests.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs similarity index 72% rename from polkadot/xcm/pallet-xcm/src/tests.rs rename to polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index 3fb4922635f6..586fa1671b95 100644 --- a/polkadot/xcm/pallet-xcm/src/tests.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -14,341 +14,21 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +#![cfg(test)] + use crate::{ - mock::*, AssetTraps, CurrentMigration, Error, LatestVersionedMultiLocation, Queries, - QueryStatus, VersionDiscoveryQueue, VersionMigrationStage, VersionNotifiers, - VersionNotifyTargets, + mock::*, + tests::{ALICE, BOB, FEE_AMOUNT, INITIAL_BALANCE, SEND_AMOUNT}, }; use frame_support::{ - assert_noop, assert_ok, - traits::{tokens::fungibles::Inspect, Currency, Hooks}, + assert_ok, + traits::{tokens::fungibles::Inspect, Currency}, weights::Weight, }; use polkadot_parachain_primitives::primitives::Id as ParaId; -use sp_runtime::{ - traits::{AccountIdConversion, BlakeTwo256, Hash}, - DispatchError, ModuleError, -}; -use xcm::{latest::QueryResponseInfo, prelude::*}; -use xcm_builder::AllowKnownQueryResponses; -use xcm_executor::{ - traits::{ConvertLocation, Properties, QueryHandler, QueryResponseStatus, ShouldExecute}, - XcmExecutor, -}; - -const ALICE: AccountId = AccountId::new([0u8; 32]); -const BOB: AccountId = AccountId::new([1u8; 32]); -const INITIAL_BALANCE: u128 = 100; -const SEND_AMOUNT: u128 = 10; -const FEE_AMOUNT: u128 = 2; - -#[test] -fn report_outcome_notify_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into(); - let mut message = - Xcm(vec![TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }]); - let call = pallet_test_notifier::Call::notification_received { - query_id: 0, - response: Default::default(), - }; - let notify = RuntimeCall::TestNotifier(call); - new_test_ext_with_balances(balances).execute_with(|| { - XcmPallet::report_outcome_notify( - &mut message, - Parachain(OTHER_PARA_ID).into_location(), - notify, - 100, - ) - .unwrap(); - assert_eq!( - message, - Xcm(vec![ - SetAppendix(Xcm(vec![ReportError(QueryResponseInfo { - destination: Parent.into(), - query_id: 0, - max_weight: Weight::from_parts(1_000_000, 1_000_000), - })])), - TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }, - ]) - ); - let querier: MultiLocation = Here.into(); - let status = QueryStatus::Pending { - responder: MultiLocation::from(Parachain(OTHER_PARA_ID)).into(), - maybe_notify: Some((5, 2)), - timeout: 100, - maybe_match_querier: Some(querier.into()), - }; - assert_eq!(crate::Queries::::iter().collect::>(), vec![(0, status)]); - - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::from_parts(1_000_000, 1_000_000), - querier: Some(querier), - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm( - Parachain(OTHER_PARA_ID), - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_events(2), - vec![ - RuntimeEvent::TestNotifier(pallet_test_notifier::Event::ResponseReceived( - Parachain(OTHER_PARA_ID).into(), - 0, - Response::ExecutionResult(None), - )), - RuntimeEvent::XcmPallet(crate::Event::Notified { - query_id: 0, - pallet_index: 5, - call_index: 2 - }), - ] - ); - assert_eq!(crate::Queries::::iter().collect::>(), vec![]); - }); -} - -#[test] -fn report_outcome_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into(); - let mut message = - Xcm(vec![TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }]); - new_test_ext_with_balances(balances).execute_with(|| { - XcmPallet::report_outcome(&mut message, Parachain(OTHER_PARA_ID).into_location(), 100) - .unwrap(); - assert_eq!( - message, - Xcm(vec![ - SetAppendix(Xcm(vec![ReportError(QueryResponseInfo { - destination: Parent.into(), - query_id: 0, - max_weight: Weight::zero(), - })])), - TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }, - ]) - ); - let querier: MultiLocation = Here.into(); - let status = QueryStatus::Pending { - responder: MultiLocation::from(Parachain(OTHER_PARA_ID)).into(), - maybe_notify: None, - timeout: 100, - maybe_match_querier: Some(querier.into()), - }; - assert_eq!(crate::Queries::::iter().collect::>(), vec![(0, status)]); - - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::zero(), - querier: Some(querier), - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm( - Parachain(OTHER_PARA_ID), - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::ResponseReady { - query_id: 0, - response: Response::ExecutionResult(None), - }) - ); - - let response = - QueryResponseStatus::Ready { response: Response::ExecutionResult(None), at: 1 }; - assert_eq!(XcmPallet::take_response(0), response); - }); -} - -#[test] -fn custom_querier_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - new_test_ext_with_balances(balances).execute_with(|| { - let querier: MultiLocation = - (Parent, AccountId32 { network: None, id: ALICE.into() }).into(); - - let r = TestNotifier::prepare_new_query(RuntimeOrigin::signed(ALICE), querier); - assert_eq!(r, Ok(())); - let status = QueryStatus::Pending { - responder: MultiLocation::from(AccountId32 { network: None, id: ALICE.into() }).into(), - maybe_notify: None, - timeout: 100, - maybe_match_querier: Some(querier.into()), - }; - assert_eq!(crate::Queries::::iter().collect::>(), vec![(0, status)]); - - // Supplying no querier when one is expected will fail - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::zero(), - querier: None, - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm_in_credit( - AccountId32 { network: None, id: ALICE.into() }, - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - Weight::from_parts(1_000, 1_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::InvalidQuerier { - origin: AccountId32 { network: None, id: ALICE.into() }.into(), - query_id: 0, - expected_querier: querier, - maybe_actual_querier: None, - }), - ); - - // Supplying the wrong querier will also fail - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::zero(), - querier: Some(MultiLocation::here()), - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm_in_credit( - AccountId32 { network: None, id: ALICE.into() }, - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - Weight::from_parts(1_000, 1_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::InvalidQuerier { - origin: AccountId32 { network: None, id: ALICE.into() }.into(), - query_id: 0, - expected_querier: querier, - maybe_actual_querier: Some(MultiLocation::here()), - }), - ); - - // Multiple failures should not have changed the query state - let message = Xcm(vec![QueryResponse { - query_id: 0, - response: Response::ExecutionResult(None), - max_weight: Weight::zero(), - querier: Some(querier), - }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm( - AccountId32 { network: None, id: ALICE.into() }, - message, - hash, - Weight::from_parts(1_000_000_000, 1_000_000_000), - ); - assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::ResponseReady { - query_id: 0, - response: Response::ExecutionResult(None), - }) - ); - - let response = - QueryResponseStatus::Ready { response: Response::ExecutionResult(None), at: 1 }; - assert_eq!(XcmPallet::take_response(0), response); - }); -} - -/// Test sending an `XCM` message (`XCM::ReserveAssetDeposit`) -/// -/// Asserts that the expected message is sent and the event is emitted -#[test] -fn send_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - new_test_ext_with_balances(balances).execute_with(|| { - let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into(); - let message = Xcm(vec![ - ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), - ClearOrigin, - buy_execution((Parent, SEND_AMOUNT)), - DepositAsset { assets: AllCounted(1).into(), beneficiary: sender }, - ]); - - let versioned_dest = Box::new(RelayLocation::get().into()); - let versioned_message = Box::new(VersionedXcm::from(message.clone())); - assert_ok!(XcmPallet::send( - RuntimeOrigin::signed(ALICE), - versioned_dest, - versioned_message - )); - let sent_message = Xcm(Some(DescendOrigin(sender.try_into().unwrap())) - .into_iter() - .chain(message.0.clone().into_iter()) - .collect()); - let id = fake_message_hash(&sent_message); - assert_eq!(sent_xcm(), vec![(Here.into(), sent_message)]); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Sent { - origin: sender, - destination: RelayLocation::get(), - message, - message_id: id, - }) - ); - }); -} - -/// Test that sending an `XCM` message fails when the `XcmRouter` blocks the -/// matching message format -/// -/// Asserts that `send` fails with `Error::SendFailure` -#[test] -fn send_fails_when_xcm_router_blocks() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - new_test_ext_with_balances(balances).execute_with(|| { - let sender: MultiLocation = - Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - let message = Xcm(vec![ - ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), - buy_execution((Parent, SEND_AMOUNT)), - DepositAsset { assets: AllCounted(1).into(), beneficiary: sender }, - ]); - assert_noop!( - XcmPallet::send( - RuntimeOrigin::signed(ALICE), - Box::new(MultiLocation::ancestor(8).into()), - Box::new(VersionedXcm::from(message.clone())), - ), - crate::Error::::SendFailure - ); - }); -} +use sp_runtime::{traits::AccountIdConversion, DispatchError, ModuleError}; +use xcm::prelude::*; +use xcm_executor::traits::ConvertLocation; // Helper function to deduplicate testing different teleport types. fn do_test_and_verify_teleport_assets( @@ -517,10 +197,10 @@ fn reserve_transfer_assets_with_paid_router_works() { // - remote reserve // - teleported // -// Bringing unique scenarios total to 3*4 = 12. So, following reserve-transfer tests try to cover +// Bringing unique scenarios total to 3*4 = 12. So, following reserve-transfer testz try to cover // the happy-case for each of these 12 scenarios. // -// TODO: also add negative tests for testing various error conditions. +// TODO: also add negative testz for testing various error conditions. fn set_up_foreign_asset( reserve_para_id: u32, @@ -2194,602 +1874,3 @@ fn reserve_transfer_assets_with_teleportable_asset_fails() { assert_eq!(Assets::active_issuance(usdt_id_multilocation), usdt_initial_local_amount); }); } - -/// Test local execution of XCM -/// -/// Asserts that the sender's balance is decreased and the beneficiary's balance -/// is increased. Verifies the expected event is emitted. -#[test] -fn execute_withdraw_to_deposit_works() { - let balances = vec![ - (ALICE, INITIAL_BALANCE), - (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), - ]; - new_test_ext_with_balances(balances).execute_with(|| { - let weight = BaseXcmWeight::get() * 3; - let dest: MultiLocation = Junction::AccountId32 { network: None, id: BOB.into() }.into(); - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); - assert_ok!(XcmPallet::execute( - RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ - WithdrawAsset((Here, SEND_AMOUNT).into()), - buy_execution((Here, SEND_AMOUNT)), - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]))), - weight - )); - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); - assert_eq!(Balances::total_balance(&BOB), SEND_AMOUNT); - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) - ); - }); -} - -/// Test drop/claim assets. -#[test] -fn trapped_assets_can_be_claimed() { - let balances = vec![(ALICE, INITIAL_BALANCE), (BOB, INITIAL_BALANCE)]; - new_test_ext_with_balances(balances).execute_with(|| { - let weight = BaseXcmWeight::get() * 6; - let dest: MultiLocation = Junction::AccountId32 { network: None, id: BOB.into() }.into(); - - assert_ok!(XcmPallet::execute( - RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ - WithdrawAsset((Here, SEND_AMOUNT).into()), - buy_execution((Here, SEND_AMOUNT)), - // Don't propagated the error into the result. - SetErrorHandler(Xcm(vec![ClearError])), - // This will make an error. - Trap(0), - // This would succeed, but we never get to it. - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]))), - weight - )); - let source: MultiLocation = - Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - let trapped = AssetTraps::::iter().collect::>(); - let vma = VersionedMultiAssets::from(MultiAssets::from((Here, SEND_AMOUNT))); - let hash = BlakeTwo256::hash_of(&(source, vma.clone())); - assert_eq!( - last_events(2), - vec![ - RuntimeEvent::XcmPallet(crate::Event::AssetsTrapped { - hash, - origin: source, - assets: vma - }), - RuntimeEvent::XcmPallet(crate::Event::Attempted { - outcome: Outcome::Complete(BaseXcmWeight::get() * 5) - }), - ] - ); - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); - assert_eq!(Balances::total_balance(&BOB), INITIAL_BALANCE); - - let expected = vec![(hash, 1u32)]; - assert_eq!(trapped, expected); - - let weight = BaseXcmWeight::get() * 3; - assert_ok!(XcmPallet::execute( - RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ - ClaimAsset { assets: (Here, SEND_AMOUNT).into(), ticket: Here.into() }, - buy_execution((Here, SEND_AMOUNT)), - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]))), - weight - )); - - assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); - assert_eq!(Balances::total_balance(&BOB), INITIAL_BALANCE + SEND_AMOUNT); - assert_eq!(AssetTraps::::iter().collect::>(), vec![]); - - let weight = BaseXcmWeight::get() * 3; - assert_ok!(XcmPallet::execute( - RuntimeOrigin::signed(ALICE), - Box::new(VersionedXcm::from(Xcm(vec![ - ClaimAsset { assets: (Here, SEND_AMOUNT).into(), ticket: Here.into() }, - buy_execution((Here, SEND_AMOUNT)), - DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, - ]))), - weight - )); - let outcome = Outcome::Incomplete(BaseXcmWeight::get(), XcmError::UnknownClaim); - assert_eq!(last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome })); - }); -} - -#[test] -fn fake_latest_versioned_multilocation_works() { - use codec::Encode; - let remote: MultiLocation = Parachain(1000).into(); - let versioned_remote = LatestVersionedMultiLocation(&remote); - assert_eq!(versioned_remote.encode(), remote.into_versioned().encode()); -} - -#[test] -fn basic_subscription_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.into()), - )); - - assert_eq!( - Queries::::iter().collect::>(), - vec![(0, QueryStatus::VersionNotifier { origin: remote.into(), is_active: false })] - ); - assert_eq!( - VersionNotifiers::::iter().collect::>(), - vec![(XCM_VERSION, remote.into(), 0)] - ); - - assert_eq!( - take_sent_xcm(), - vec![( - remote, - Xcm(vec![SubscribeVersion { query_id: 0, max_response_weight: Weight::zero() }]), - ),] - ); - - let weight = BaseXcmWeight::get(); - let mut message = Xcm::<()>(vec![ - // Remote supports XCM v2 - QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(1), - querier: None, - }, - ]); - assert_ok!(AllowKnownQueryResponses::::should_execute( - &remote, - message.inner_mut(), - weight, - &mut Properties { weight_credit: Weight::zero(), message_id: None }, - )); - }); -} - -#[test] -fn subscriptions_increment_id() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.into()), - )); - - let remote2: MultiLocation = Parachain(1001).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote2.into()), - )); - - assert_eq!( - take_sent_xcm(), - vec![ - ( - remote, - Xcm(vec![SubscribeVersion { - query_id: 0, - max_response_weight: Weight::zero() - }]), - ), - ( - remote2, - Xcm(vec![SubscribeVersion { - query_id: 1, - max_response_weight: Weight::zero() - }]), - ), - ] - ); - }); -} - -#[test] -fn double_subscription_fails() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.into()), - )); - assert_noop!( - XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.into()) - ), - Error::::AlreadySubscribed, - ); - }) -} - -#[test] -fn unsubscribe_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.into()), - )); - assert_ok!(XcmPallet::force_unsubscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.into()) - )); - assert_noop!( - XcmPallet::force_unsubscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.into()) - ), - Error::::NoSubscription, - ); - - assert_eq!( - take_sent_xcm(), - vec![ - ( - remote, - Xcm(vec![SubscribeVersion { - query_id: 0, - max_response_weight: Weight::zero() - }]), - ), - (remote, Xcm(vec![UnsubscribeVersion]),), - ] - ); - }); -} - -/// Parachain 1000 is asking us for a version subscription. -#[test] -fn subscription_side_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - AdvertisedXcmVersion::set(1); - - let remote: MultiLocation = Parachain(1000).into(); - let weight = BaseXcmWeight::get(); - let message = - Xcm(vec![SubscribeVersion { query_id: 0, max_response_weight: Weight::zero() }]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote, message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - - let instr = QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(1), - querier: None, - }; - assert_eq!(take_sent_xcm(), vec![(remote, Xcm(vec![instr]))]); - - // A runtime upgrade which doesn't alter the version sends no notifications. - CurrentMigration::::put(VersionMigrationStage::default()); - XcmPallet::on_initialize(1); - assert_eq!(take_sent_xcm(), vec![]); - - // New version. - AdvertisedXcmVersion::set(2); - - // A runtime upgrade which alters the version does send notifications. - CurrentMigration::::put(VersionMigrationStage::default()); - XcmPallet::on_initialize(2); - let instr = QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(2), - querier: None, - }; - assert_eq!(take_sent_xcm(), vec![(remote, Xcm(vec![instr]))]); - }); -} - -#[test] -fn subscription_side_upgrades_work_with_notify() { - new_test_ext_with_balances(vec![]).execute_with(|| { - AdvertisedXcmVersion::set(1); - - // An entry from a previous runtime with v2 XCM. - let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); - - // New version. - AdvertisedXcmVersion::set(3); - - // A runtime upgrade which alters the version does send notifications. - CurrentMigration::::put(VersionMigrationStage::default()); - XcmPallet::on_initialize(1); - - let instr1 = QueryResponse { - query_id: 70, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let instr3 = QueryResponse { - query_id: 72, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let mut sent = take_sent_xcm(); - sent.sort_by_key(|k| match (k.1).0[0] { - QueryResponse { query_id: q, .. } => q, - _ => 0, - }); - assert_eq!( - sent, - vec![ - (Parachain(1001).into(), Xcm(vec![instr1])), - (Parachain(1003).into(), Xcm(vec![instr3])), - ] - ); - - let mut contents = VersionNotifyTargets::::iter().collect::>(); - contents.sort_by_key(|k| k.2 .0); - assert_eq!( - contents, - vec![ - (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), - ] - ); - }); -} - -#[test] -fn subscription_side_upgrades_work_without_notify() { - new_test_ext_with_balances(vec![]).execute_with(|| { - // An entry from a previous runtime with v2 XCM. - let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); - - // A runtime upgrade which alters the version does send notifications. - CurrentMigration::::put(VersionMigrationStage::default()); - XcmPallet::on_initialize(1); - - let mut contents = VersionNotifyTargets::::iter().collect::>(); - contents.sort_by_key(|k| k.2 .0); - assert_eq!( - contents, - vec![ - (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), - ] - ); - }); -} - -#[test] -fn subscriber_side_subscription_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote: MultiLocation = Parachain(1000).into(); - assert_ok!(XcmPallet::force_subscribe_version_notify( - RuntimeOrigin::root(), - Box::new(remote.into()), - )); - take_sent_xcm(); - - // Assume subscription target is working ok. - - let weight = BaseXcmWeight::get(); - let message = Xcm(vec![ - // Remote supports XCM v2 - QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(1), - querier: None, - }, - ]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote, message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - assert_eq!(take_sent_xcm(), vec![]); - - // This message cannot be sent to a v2 remote. - let v2_msg = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); - assert_eq!(XcmPallet::wrap_version(&remote, v2_msg.clone()), Err(())); - - let message = Xcm(vec![ - // Remote upgraded to XCM v2 - QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(2), - querier: None, - }, - ]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote, message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - - // This message can now be sent to remote as it's v2. - assert_eq!( - XcmPallet::wrap_version(&remote, v2_msg.clone()), - Ok(VersionedXcm::from(v2_msg)) - ); - }); -} - -/// We should auto-subscribe when we don't know the remote's version. -#[test] -fn auto_subscription_works() { - new_test_ext_with_balances(vec![]).execute_with(|| { - let remote_v2: MultiLocation = Parachain(1000).into(); - let remote_v3: MultiLocation = Parachain(1001).into(); - - assert_ok!(XcmPallet::force_default_xcm_version(RuntimeOrigin::root(), Some(2))); - - // Wrapping a version for a destination we don't know elicits a subscription. - let msg_v2 = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); - let msg_v3 = xcm::v3::Xcm::<()>(vec![xcm::v3::Instruction::ClearTopic]); - assert_eq!( - XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone())), - ); - assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v3.clone()), Err(())); - - let expected = vec![(remote_v2.into(), 2)]; - assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); - - assert_eq!( - XcmPallet::wrap_version(&remote_v3, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone())), - ); - assert_eq!(XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), Err(())); - - let expected = vec![(remote_v2.into(), 2), (remote_v3.into(), 2)]; - assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); - - XcmPallet::on_initialize(1); - assert_eq!( - take_sent_xcm(), - vec![( - remote_v3, - Xcm(vec![SubscribeVersion { query_id: 0, max_response_weight: Weight::zero() }]), - )] - ); - - // Assume remote_v3 is working ok and XCM version 3. - - let weight = BaseXcmWeight::get(); - let message = Xcm(vec![ - // Remote supports XCM v3 - QueryResponse { - query_id: 0, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }, - ]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote_v3, message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - - // V2 messages can be sent to remote_v3 under XCM v3. - assert_eq!( - XcmPallet::wrap_version(&remote_v3, msg_v2.clone()), - Ok(VersionedXcm::from(msg_v2.clone()).into_version(3).unwrap()), - ); - // This message can now be sent to remote_v3 as it's v3. - assert_eq!( - XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), - Ok(VersionedXcm::from(msg_v3.clone())) - ); - - XcmPallet::on_initialize(2); - assert_eq!( - take_sent_xcm(), - vec![( - remote_v2, - Xcm(vec![SubscribeVersion { query_id: 1, max_response_weight: Weight::zero() }]), - )] - ); - - // Assume remote_v2 is working ok and XCM version 2. - - let weight = BaseXcmWeight::get(); - let message = Xcm(vec![ - // Remote supports XCM v2 - QueryResponse { - query_id: 1, - max_weight: Weight::zero(), - response: Response::Version(2), - querier: None, - }, - ]); - let hash = fake_message_hash(&message); - let r = XcmExecutor::::execute_xcm(remote_v2, message, hash, weight); - assert_eq!(r, Outcome::Complete(weight)); - - // v3 messages cannot be sent to remote_v2... - assert_eq!( - XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), - Ok(VersionedXcm::V2(msg_v2)) - ); - assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v3.clone()), Err(())); - }) -} - -#[test] -fn subscription_side_upgrades_work_with_multistage_notify() { - new_test_ext_with_balances(vec![]).execute_with(|| { - AdvertisedXcmVersion::set(1); - - // An entry from a previous runtime with v0 XCM. - let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1001).into()); - VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 1)); - let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1002).into()); - VersionNotifyTargets::::insert(2, v2_location, (71, Weight::zero(), 1)); - let v3_location = Parachain(1003).into_versioned(); - VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 1)); - - // New version. - AdvertisedXcmVersion::set(3); - - // A runtime upgrade which alters the version does send notifications. - CurrentMigration::::put(VersionMigrationStage::default()); - let mut maybe_migration = CurrentMigration::::take(); - let mut counter = 0; - while let Some(migration) = maybe_migration.take() { - counter += 1; - let (_, m) = XcmPallet::check_xcm_version_change(migration, Weight::zero()); - maybe_migration = m; - } - assert_eq!(counter, 4); - - let instr1 = QueryResponse { - query_id: 70, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let instr2 = QueryResponse { - query_id: 71, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let instr3 = QueryResponse { - query_id: 72, - max_weight: Weight::zero(), - response: Response::Version(3), - querier: None, - }; - let mut sent = take_sent_xcm(); - sent.sort_by_key(|k| match (k.1).0[0] { - QueryResponse { query_id: q, .. } => q, - _ => 0, - }); - assert_eq!( - sent, - vec![ - (Parachain(1001).into(), Xcm(vec![instr1])), - (Parachain(1002).into(), Xcm(vec![instr2])), - (Parachain(1003).into(), Xcm(vec![instr3])), - ] - ); - - let mut contents = VersionNotifyTargets::::iter().collect::>(); - contents.sort_by_key(|k| k.2 .0); - assert_eq!( - contents, - vec![ - (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1002).into_versioned(), (71, Weight::zero(), 3)), - (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), - ] - ); - }); -} diff --git a/polkadot/xcm/pallet-xcm/src/tests/mod.rs b/polkadot/xcm/pallet-xcm/src/tests/mod.rs new file mode 100644 index 000000000000..72814e507f2a --- /dev/null +++ b/polkadot/xcm/pallet-xcm/src/tests/mod.rs @@ -0,0 +1,951 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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. + +// Polkadot 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 Polkadot. If not, see . + +#![cfg(test)] + +mod assets_transfer; + +use crate::{ + mock::*, AssetTraps, CurrentMigration, Error, LatestVersionedMultiLocation, Queries, + QueryStatus, VersionDiscoveryQueue, VersionMigrationStage, VersionNotifiers, + VersionNotifyTargets, +}; +use frame_support::{ + assert_noop, assert_ok, + traits::{Currency, Hooks}, + weights::Weight, +}; +use polkadot_parachain_primitives::primitives::Id as ParaId; +use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash}; +use xcm::{latest::QueryResponseInfo, prelude::*}; +use xcm_builder::AllowKnownQueryResponses; +use xcm_executor::{ + traits::{Properties, QueryHandler, QueryResponseStatus, ShouldExecute}, + XcmExecutor, +}; + +const ALICE: AccountId = AccountId::new([0u8; 32]); +const BOB: AccountId = AccountId::new([1u8; 32]); +const INITIAL_BALANCE: u128 = 100; +const SEND_AMOUNT: u128 = 10; +const FEE_AMOUNT: u128 = 2; + +#[test] +fn report_outcome_notify_works() { + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), + ]; + let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into(); + let mut message = + Xcm(vec![TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }]); + let call = pallet_test_notifier::Call::notification_received { + query_id: 0, + response: Default::default(), + }; + let notify = RuntimeCall::TestNotifier(call); + new_test_ext_with_balances(balances).execute_with(|| { + XcmPallet::report_outcome_notify( + &mut message, + Parachain(OTHER_PARA_ID).into_location(), + notify, + 100, + ) + .unwrap(); + assert_eq!( + message, + Xcm(vec![ + SetAppendix(Xcm(vec![ReportError(QueryResponseInfo { + destination: Parent.into(), + query_id: 0, + max_weight: Weight::from_parts(1_000_000, 1_000_000), + })])), + TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }, + ]) + ); + let querier: MultiLocation = Here.into(); + let status = QueryStatus::Pending { + responder: MultiLocation::from(Parachain(OTHER_PARA_ID)).into(), + maybe_notify: Some((5, 2)), + timeout: 100, + maybe_match_querier: Some(querier.into()), + }; + assert_eq!(crate::Queries::::iter().collect::>(), vec![(0, status)]); + + let message = Xcm(vec![QueryResponse { + query_id: 0, + response: Response::ExecutionResult(None), + max_weight: Weight::from_parts(1_000_000, 1_000_000), + querier: Some(querier), + }]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm( + Parachain(OTHER_PARA_ID), + message, + hash, + Weight::from_parts(1_000_000_000, 1_000_000_000), + ); + assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); + assert_eq!( + last_events(2), + vec![ + RuntimeEvent::TestNotifier(pallet_test_notifier::Event::ResponseReceived( + Parachain(OTHER_PARA_ID).into(), + 0, + Response::ExecutionResult(None), + )), + RuntimeEvent::XcmPallet(crate::Event::Notified { + query_id: 0, + pallet_index: 5, + call_index: 2 + }), + ] + ); + assert_eq!(crate::Queries::::iter().collect::>(), vec![]); + }); +} + +#[test] +fn report_outcome_works() { + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), + ]; + let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into(); + let mut message = + Xcm(vec![TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }]); + new_test_ext_with_balances(balances).execute_with(|| { + XcmPallet::report_outcome(&mut message, Parachain(OTHER_PARA_ID).into_location(), 100) + .unwrap(); + assert_eq!( + message, + Xcm(vec![ + SetAppendix(Xcm(vec![ReportError(QueryResponseInfo { + destination: Parent.into(), + query_id: 0, + max_weight: Weight::zero(), + })])), + TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender }, + ]) + ); + let querier: MultiLocation = Here.into(); + let status = QueryStatus::Pending { + responder: MultiLocation::from(Parachain(OTHER_PARA_ID)).into(), + maybe_notify: None, + timeout: 100, + maybe_match_querier: Some(querier.into()), + }; + assert_eq!(crate::Queries::::iter().collect::>(), vec![(0, status)]); + + let message = Xcm(vec![QueryResponse { + query_id: 0, + response: Response::ExecutionResult(None), + max_weight: Weight::zero(), + querier: Some(querier), + }]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm( + Parachain(OTHER_PARA_ID), + message, + hash, + Weight::from_parts(1_000_000_000, 1_000_000_000), + ); + assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); + assert_eq!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::ResponseReady { + query_id: 0, + response: Response::ExecutionResult(None), + }) + ); + + let response = + QueryResponseStatus::Ready { response: Response::ExecutionResult(None), at: 1 }; + assert_eq!(XcmPallet::take_response(0), response); + }); +} + +#[test] +fn custom_querier_works() { + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), + ]; + new_test_ext_with_balances(balances).execute_with(|| { + let querier: MultiLocation = + (Parent, AccountId32 { network: None, id: ALICE.into() }).into(); + + let r = TestNotifier::prepare_new_query(RuntimeOrigin::signed(ALICE), querier); + assert_eq!(r, Ok(())); + let status = QueryStatus::Pending { + responder: MultiLocation::from(AccountId32 { network: None, id: ALICE.into() }).into(), + maybe_notify: None, + timeout: 100, + maybe_match_querier: Some(querier.into()), + }; + assert_eq!(crate::Queries::::iter().collect::>(), vec![(0, status)]); + + // Supplying no querier when one is expected will fail + let message = Xcm(vec![QueryResponse { + query_id: 0, + response: Response::ExecutionResult(None), + max_weight: Weight::zero(), + querier: None, + }]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm_in_credit( + AccountId32 { network: None, id: ALICE.into() }, + message, + hash, + Weight::from_parts(1_000_000_000, 1_000_000_000), + Weight::from_parts(1_000, 1_000), + ); + assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); + assert_eq!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::InvalidQuerier { + origin: AccountId32 { network: None, id: ALICE.into() }.into(), + query_id: 0, + expected_querier: querier, + maybe_actual_querier: None, + }), + ); + + // Supplying the wrong querier will also fail + let message = Xcm(vec![QueryResponse { + query_id: 0, + response: Response::ExecutionResult(None), + max_weight: Weight::zero(), + querier: Some(MultiLocation::here()), + }]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm_in_credit( + AccountId32 { network: None, id: ALICE.into() }, + message, + hash, + Weight::from_parts(1_000_000_000, 1_000_000_000), + Weight::from_parts(1_000, 1_000), + ); + assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); + assert_eq!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::InvalidQuerier { + origin: AccountId32 { network: None, id: ALICE.into() }.into(), + query_id: 0, + expected_querier: querier, + maybe_actual_querier: Some(MultiLocation::here()), + }), + ); + + // Multiple failures should not have changed the query state + let message = Xcm(vec![QueryResponse { + query_id: 0, + response: Response::ExecutionResult(None), + max_weight: Weight::zero(), + querier: Some(querier), + }]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm( + AccountId32 { network: None, id: ALICE.into() }, + message, + hash, + Weight::from_parts(1_000_000_000, 1_000_000_000), + ); + assert_eq!(r, Outcome::Complete(Weight::from_parts(1_000, 1_000))); + assert_eq!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::ResponseReady { + query_id: 0, + response: Response::ExecutionResult(None), + }) + ); + + let response = + QueryResponseStatus::Ready { response: Response::ExecutionResult(None), at: 1 }; + assert_eq!(XcmPallet::take_response(0), response); + }); +} + +/// Test sending an `XCM` message (`XCM::ReserveAssetDeposit`) +/// +/// Asserts that the expected message is sent and the event is emitted +#[test] +fn send_works() { + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), + ]; + new_test_ext_with_balances(balances).execute_with(|| { + let sender: MultiLocation = AccountId32 { network: None, id: ALICE.into() }.into(); + let message = Xcm(vec![ + ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), + ClearOrigin, + buy_execution((Parent, SEND_AMOUNT)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: sender }, + ]); + + let versioned_dest = Box::new(RelayLocation::get().into()); + let versioned_message = Box::new(VersionedXcm::from(message.clone())); + assert_ok!(XcmPallet::send( + RuntimeOrigin::signed(ALICE), + versioned_dest, + versioned_message + )); + let sent_message = Xcm(Some(DescendOrigin(sender.try_into().unwrap())) + .into_iter() + .chain(message.0.clone().into_iter()) + .collect()); + let id = fake_message_hash(&sent_message); + assert_eq!(sent_xcm(), vec![(Here.into(), sent_message)]); + assert_eq!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Sent { + origin: sender, + destination: RelayLocation::get(), + message, + message_id: id, + }) + ); + }); +} + +/// Test that sending an `XCM` message fails when the `XcmRouter` blocks the +/// matching message format +/// +/// Asserts that `send` fails with `Error::SendFailure` +#[test] +fn send_fails_when_xcm_router_blocks() { + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), + ]; + new_test_ext_with_balances(balances).execute_with(|| { + let sender: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + let message = Xcm(vec![ + ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), + buy_execution((Parent, SEND_AMOUNT)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: sender }, + ]); + assert_noop!( + XcmPallet::send( + RuntimeOrigin::signed(ALICE), + Box::new(MultiLocation::ancestor(8).into()), + Box::new(VersionedXcm::from(message.clone())), + ), + crate::Error::::SendFailure + ); + }); +} + +/// Test local execution of XCM +/// +/// Asserts that the sender's balance is decreased and the beneficiary's balance +/// is increased. Verifies the expected event is emitted. +#[test] +fn execute_withdraw_to_deposit_works() { + let balances = vec![ + (ALICE, INITIAL_BALANCE), + (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), + ]; + new_test_ext_with_balances(balances).execute_with(|| { + let weight = BaseXcmWeight::get() * 3; + let dest: MultiLocation = Junction::AccountId32 { network: None, id: BOB.into() }.into(); + assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); + assert_ok!(XcmPallet::execute( + RuntimeOrigin::signed(ALICE), + Box::new(VersionedXcm::from(Xcm(vec![ + WithdrawAsset((Here, SEND_AMOUNT).into()), + buy_execution((Here, SEND_AMOUNT)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, + ]))), + weight + )); + assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); + assert_eq!(Balances::total_balance(&BOB), SEND_AMOUNT); + assert_eq!( + last_event(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) + ); + }); +} + +/// Test drop/claim assets. +#[test] +fn trapped_assets_can_be_claimed() { + let balances = vec![(ALICE, INITIAL_BALANCE), (BOB, INITIAL_BALANCE)]; + new_test_ext_with_balances(balances).execute_with(|| { + let weight = BaseXcmWeight::get() * 6; + let dest: MultiLocation = Junction::AccountId32 { network: None, id: BOB.into() }.into(); + + assert_ok!(XcmPallet::execute( + RuntimeOrigin::signed(ALICE), + Box::new(VersionedXcm::from(Xcm(vec![ + WithdrawAsset((Here, SEND_AMOUNT).into()), + buy_execution((Here, SEND_AMOUNT)), + // Don't propagated the error into the result. + SetErrorHandler(Xcm(vec![ClearError])), + // This will make an error. + Trap(0), + // This would succeed, but we never get to it. + DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, + ]))), + weight + )); + let source: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + let trapped = AssetTraps::::iter().collect::>(); + let vma = VersionedMultiAssets::from(MultiAssets::from((Here, SEND_AMOUNT))); + let hash = BlakeTwo256::hash_of(&(source, vma.clone())); + assert_eq!( + last_events(2), + vec![ + RuntimeEvent::XcmPallet(crate::Event::AssetsTrapped { + hash, + origin: source, + assets: vma + }), + RuntimeEvent::XcmPallet(crate::Event::Attempted { + outcome: Outcome::Complete(BaseXcmWeight::get() * 5) + }), + ] + ); + assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); + assert_eq!(Balances::total_balance(&BOB), INITIAL_BALANCE); + + let expected = vec![(hash, 1u32)]; + assert_eq!(trapped, expected); + + let weight = BaseXcmWeight::get() * 3; + assert_ok!(XcmPallet::execute( + RuntimeOrigin::signed(ALICE), + Box::new(VersionedXcm::from(Xcm(vec![ + ClaimAsset { assets: (Here, SEND_AMOUNT).into(), ticket: Here.into() }, + buy_execution((Here, SEND_AMOUNT)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, + ]))), + weight + )); + + assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE - SEND_AMOUNT); + assert_eq!(Balances::total_balance(&BOB), INITIAL_BALANCE + SEND_AMOUNT); + assert_eq!(AssetTraps::::iter().collect::>(), vec![]); + + let weight = BaseXcmWeight::get() * 3; + assert_ok!(XcmPallet::execute( + RuntimeOrigin::signed(ALICE), + Box::new(VersionedXcm::from(Xcm(vec![ + ClaimAsset { assets: (Here, SEND_AMOUNT).into(), ticket: Here.into() }, + buy_execution((Here, SEND_AMOUNT)), + DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, + ]))), + weight + )); + let outcome = Outcome::Incomplete(BaseXcmWeight::get(), XcmError::UnknownClaim); + assert_eq!(last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome })); + }); +} + +#[test] +fn fake_latest_versioned_multilocation_works() { + use codec::Encode; + let remote: MultiLocation = Parachain(1000).into(); + let versioned_remote = LatestVersionedMultiLocation(&remote); + assert_eq!(versioned_remote.encode(), remote.into_versioned().encode()); +} + +#[test] +fn basic_subscription_works() { + new_test_ext_with_balances(vec![]).execute_with(|| { + let remote: MultiLocation = Parachain(1000).into(); + assert_ok!(XcmPallet::force_subscribe_version_notify( + RuntimeOrigin::root(), + Box::new(remote.into()), + )); + + assert_eq!( + Queries::::iter().collect::>(), + vec![(0, QueryStatus::VersionNotifier { origin: remote.into(), is_active: false })] + ); + assert_eq!( + VersionNotifiers::::iter().collect::>(), + vec![(XCM_VERSION, remote.into(), 0)] + ); + + assert_eq!( + take_sent_xcm(), + vec![( + remote, + Xcm(vec![SubscribeVersion { query_id: 0, max_response_weight: Weight::zero() }]), + ),] + ); + + let weight = BaseXcmWeight::get(); + let mut message = Xcm::<()>(vec![ + // Remote supports XCM v2 + QueryResponse { + query_id: 0, + max_weight: Weight::zero(), + response: Response::Version(1), + querier: None, + }, + ]); + assert_ok!(AllowKnownQueryResponses::::should_execute( + &remote, + message.inner_mut(), + weight, + &mut Properties { weight_credit: Weight::zero(), message_id: None }, + )); + }); +} + +#[test] +fn subscriptions_increment_id() { + new_test_ext_with_balances(vec![]).execute_with(|| { + let remote: MultiLocation = Parachain(1000).into(); + assert_ok!(XcmPallet::force_subscribe_version_notify( + RuntimeOrigin::root(), + Box::new(remote.into()), + )); + + let remote2: MultiLocation = Parachain(1001).into(); + assert_ok!(XcmPallet::force_subscribe_version_notify( + RuntimeOrigin::root(), + Box::new(remote2.into()), + )); + + assert_eq!( + take_sent_xcm(), + vec![ + ( + remote, + Xcm(vec![SubscribeVersion { + query_id: 0, + max_response_weight: Weight::zero() + }]), + ), + ( + remote2, + Xcm(vec![SubscribeVersion { + query_id: 1, + max_response_weight: Weight::zero() + }]), + ), + ] + ); + }); +} + +#[test] +fn double_subscription_fails() { + new_test_ext_with_balances(vec![]).execute_with(|| { + let remote: MultiLocation = Parachain(1000).into(); + assert_ok!(XcmPallet::force_subscribe_version_notify( + RuntimeOrigin::root(), + Box::new(remote.into()), + )); + assert_noop!( + XcmPallet::force_subscribe_version_notify( + RuntimeOrigin::root(), + Box::new(remote.into()) + ), + Error::::AlreadySubscribed, + ); + }) +} + +#[test] +fn unsubscribe_works() { + new_test_ext_with_balances(vec![]).execute_with(|| { + let remote: MultiLocation = Parachain(1000).into(); + assert_ok!(XcmPallet::force_subscribe_version_notify( + RuntimeOrigin::root(), + Box::new(remote.into()), + )); + assert_ok!(XcmPallet::force_unsubscribe_version_notify( + RuntimeOrigin::root(), + Box::new(remote.into()) + )); + assert_noop!( + XcmPallet::force_unsubscribe_version_notify( + RuntimeOrigin::root(), + Box::new(remote.into()) + ), + Error::::NoSubscription, + ); + + assert_eq!( + take_sent_xcm(), + vec![ + ( + remote, + Xcm(vec![SubscribeVersion { + query_id: 0, + max_response_weight: Weight::zero() + }]), + ), + (remote, Xcm(vec![UnsubscribeVersion]),), + ] + ); + }); +} + +/// Parachain 1000 is asking us for a version subscription. +#[test] +fn subscription_side_works() { + new_test_ext_with_balances(vec![]).execute_with(|| { + AdvertisedXcmVersion::set(1); + + let remote: MultiLocation = Parachain(1000).into(); + let weight = BaseXcmWeight::get(); + let message = + Xcm(vec![SubscribeVersion { query_id: 0, max_response_weight: Weight::zero() }]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm(remote, message, hash, weight); + assert_eq!(r, Outcome::Complete(weight)); + + let instr = QueryResponse { + query_id: 0, + max_weight: Weight::zero(), + response: Response::Version(1), + querier: None, + }; + assert_eq!(take_sent_xcm(), vec![(remote, Xcm(vec![instr]))]); + + // A runtime upgrade which doesn't alter the version sends no notifications. + CurrentMigration::::put(VersionMigrationStage::default()); + XcmPallet::on_initialize(1); + assert_eq!(take_sent_xcm(), vec![]); + + // New version. + AdvertisedXcmVersion::set(2); + + // A runtime upgrade which alters the version does send notifications. + CurrentMigration::::put(VersionMigrationStage::default()); + XcmPallet::on_initialize(2); + let instr = QueryResponse { + query_id: 0, + max_weight: Weight::zero(), + response: Response::Version(2), + querier: None, + }; + assert_eq!(take_sent_xcm(), vec![(remote, Xcm(vec![instr]))]); + }); +} + +#[test] +fn subscription_side_upgrades_work_with_notify() { + new_test_ext_with_balances(vec![]).execute_with(|| { + AdvertisedXcmVersion::set(1); + + // An entry from a previous runtime with v2 XCM. + let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1001).into()); + VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); + let v3_location = Parachain(1003).into_versioned(); + VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); + + // New version. + AdvertisedXcmVersion::set(3); + + // A runtime upgrade which alters the version does send notifications. + CurrentMigration::::put(VersionMigrationStage::default()); + XcmPallet::on_initialize(1); + + let instr1 = QueryResponse { + query_id: 70, + max_weight: Weight::zero(), + response: Response::Version(3), + querier: None, + }; + let instr3 = QueryResponse { + query_id: 72, + max_weight: Weight::zero(), + response: Response::Version(3), + querier: None, + }; + let mut sent = take_sent_xcm(); + sent.sort_by_key(|k| match (k.1).0[0] { + QueryResponse { query_id: q, .. } => q, + _ => 0, + }); + assert_eq!( + sent, + vec![ + (Parachain(1001).into(), Xcm(vec![instr1])), + (Parachain(1003).into(), Xcm(vec![instr3])), + ] + ); + + let mut contents = VersionNotifyTargets::::iter().collect::>(); + contents.sort_by_key(|k| k.2 .0); + assert_eq!( + contents, + vec![ + (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), + (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), + ] + ); + }); +} + +#[test] +fn subscription_side_upgrades_work_without_notify() { + new_test_ext_with_balances(vec![]).execute_with(|| { + // An entry from a previous runtime with v2 XCM. + let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1001).into()); + VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 2)); + let v3_location = Parachain(1003).into_versioned(); + VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 2)); + + // A runtime upgrade which alters the version does send notifications. + CurrentMigration::::put(VersionMigrationStage::default()); + XcmPallet::on_initialize(1); + + let mut contents = VersionNotifyTargets::::iter().collect::>(); + contents.sort_by_key(|k| k.2 .0); + assert_eq!( + contents, + vec![ + (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), + (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), + ] + ); + }); +} + +#[test] +fn subscriber_side_subscription_works() { + new_test_ext_with_balances(vec![]).execute_with(|| { + let remote: MultiLocation = Parachain(1000).into(); + assert_ok!(XcmPallet::force_subscribe_version_notify( + RuntimeOrigin::root(), + Box::new(remote.into()), + )); + take_sent_xcm(); + + // Assume subscription target is working ok. + + let weight = BaseXcmWeight::get(); + let message = Xcm(vec![ + // Remote supports XCM v2 + QueryResponse { + query_id: 0, + max_weight: Weight::zero(), + response: Response::Version(1), + querier: None, + }, + ]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm(remote, message, hash, weight); + assert_eq!(r, Outcome::Complete(weight)); + assert_eq!(take_sent_xcm(), vec![]); + + // This message cannot be sent to a v2 remote. + let v2_msg = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); + assert_eq!(XcmPallet::wrap_version(&remote, v2_msg.clone()), Err(())); + + let message = Xcm(vec![ + // Remote upgraded to XCM v2 + QueryResponse { + query_id: 0, + max_weight: Weight::zero(), + response: Response::Version(2), + querier: None, + }, + ]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm(remote, message, hash, weight); + assert_eq!(r, Outcome::Complete(weight)); + + // This message can now be sent to remote as it's v2. + assert_eq!( + XcmPallet::wrap_version(&remote, v2_msg.clone()), + Ok(VersionedXcm::from(v2_msg)) + ); + }); +} + +/// We should auto-subscribe when we don't know the remote's version. +#[test] +fn auto_subscription_works() { + new_test_ext_with_balances(vec![]).execute_with(|| { + let remote_v2: MultiLocation = Parachain(1000).into(); + let remote_v3: MultiLocation = Parachain(1001).into(); + + assert_ok!(XcmPallet::force_default_xcm_version(RuntimeOrigin::root(), Some(2))); + + // Wrapping a version for a destination we don't know elicits a subscription. + let msg_v2 = xcm::v2::Xcm::<()>(vec![xcm::v2::Instruction::Trap(0)]); + let msg_v3 = xcm::v3::Xcm::<()>(vec![xcm::v3::Instruction::ClearTopic]); + assert_eq!( + XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), + Ok(VersionedXcm::from(msg_v2.clone())), + ); + assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v3.clone()), Err(())); + + let expected = vec![(remote_v2.into(), 2)]; + assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); + + assert_eq!( + XcmPallet::wrap_version(&remote_v3, msg_v2.clone()), + Ok(VersionedXcm::from(msg_v2.clone())), + ); + assert_eq!(XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), Err(())); + + let expected = vec![(remote_v2.into(), 2), (remote_v3.into(), 2)]; + assert_eq!(VersionDiscoveryQueue::::get().into_inner(), expected); + + XcmPallet::on_initialize(1); + assert_eq!( + take_sent_xcm(), + vec![( + remote_v3, + Xcm(vec![SubscribeVersion { query_id: 0, max_response_weight: Weight::zero() }]), + )] + ); + + // Assume remote_v3 is working ok and XCM version 3. + + let weight = BaseXcmWeight::get(); + let message = Xcm(vec![ + // Remote supports XCM v3 + QueryResponse { + query_id: 0, + max_weight: Weight::zero(), + response: Response::Version(3), + querier: None, + }, + ]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm(remote_v3, message, hash, weight); + assert_eq!(r, Outcome::Complete(weight)); + + // V2 messages can be sent to remote_v3 under XCM v3. + assert_eq!( + XcmPallet::wrap_version(&remote_v3, msg_v2.clone()), + Ok(VersionedXcm::from(msg_v2.clone()).into_version(3).unwrap()), + ); + // This message can now be sent to remote_v3 as it's v3. + assert_eq!( + XcmPallet::wrap_version(&remote_v3, msg_v3.clone()), + Ok(VersionedXcm::from(msg_v3.clone())) + ); + + XcmPallet::on_initialize(2); + assert_eq!( + take_sent_xcm(), + vec![( + remote_v2, + Xcm(vec![SubscribeVersion { query_id: 1, max_response_weight: Weight::zero() }]), + )] + ); + + // Assume remote_v2 is working ok and XCM version 2. + + let weight = BaseXcmWeight::get(); + let message = Xcm(vec![ + // Remote supports XCM v2 + QueryResponse { + query_id: 1, + max_weight: Weight::zero(), + response: Response::Version(2), + querier: None, + }, + ]); + let hash = fake_message_hash(&message); + let r = XcmExecutor::::execute_xcm(remote_v2, message, hash, weight); + assert_eq!(r, Outcome::Complete(weight)); + + // v3 messages cannot be sent to remote_v2... + assert_eq!( + XcmPallet::wrap_version(&remote_v2, msg_v2.clone()), + Ok(VersionedXcm::V2(msg_v2)) + ); + assert_eq!(XcmPallet::wrap_version(&remote_v2, msg_v3.clone()), Err(())); + }) +} + +#[test] +fn subscription_side_upgrades_work_with_multistage_notify() { + new_test_ext_with_balances(vec![]).execute_with(|| { + AdvertisedXcmVersion::set(1); + + // An entry from a previous runtime with v0 XCM. + let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1001).into()); + VersionNotifyTargets::::insert(1, v2_location, (70, Weight::zero(), 1)); + let v2_location = VersionedMultiLocation::V2(xcm::v2::Junction::Parachain(1002).into()); + VersionNotifyTargets::::insert(2, v2_location, (71, Weight::zero(), 1)); + let v3_location = Parachain(1003).into_versioned(); + VersionNotifyTargets::::insert(3, v3_location, (72, Weight::zero(), 1)); + + // New version. + AdvertisedXcmVersion::set(3); + + // A runtime upgrade which alters the version does send notifications. + CurrentMigration::::put(VersionMigrationStage::default()); + let mut maybe_migration = CurrentMigration::::take(); + let mut counter = 0; + while let Some(migration) = maybe_migration.take() { + counter += 1; + let (_, m) = XcmPallet::check_xcm_version_change(migration, Weight::zero()); + maybe_migration = m; + } + assert_eq!(counter, 4); + + let instr1 = QueryResponse { + query_id: 70, + max_weight: Weight::zero(), + response: Response::Version(3), + querier: None, + }; + let instr2 = QueryResponse { + query_id: 71, + max_weight: Weight::zero(), + response: Response::Version(3), + querier: None, + }; + let instr3 = QueryResponse { + query_id: 72, + max_weight: Weight::zero(), + response: Response::Version(3), + querier: None, + }; + let mut sent = take_sent_xcm(); + sent.sort_by_key(|k| match (k.1).0[0] { + QueryResponse { query_id: q, .. } => q, + _ => 0, + }); + assert_eq!( + sent, + vec![ + (Parachain(1001).into(), Xcm(vec![instr1])), + (Parachain(1002).into(), Xcm(vec![instr2])), + (Parachain(1003).into(), Xcm(vec![instr3])), + ] + ); + + let mut contents = VersionNotifyTargets::::iter().collect::>(); + contents.sort_by_key(|k| k.2 .0); + assert_eq!( + contents, + vec![ + (XCM_VERSION, Parachain(1001).into_versioned(), (70, Weight::zero(), 3)), + (XCM_VERSION, Parachain(1002).into_versioned(), (71, Weight::zero(), 3)), + (XCM_VERSION, Parachain(1003).into_versioned(), (72, Weight::zero(), 3)), + ] + ); + }); +} From 30709948c6d28615a1ea90e599fbc1843dc5a049 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 23 Oct 2023 12:56:17 +0300 Subject: [PATCH 037/124] address review comments --- polkadot/xcm/pallet-xcm/src/lib.rs | 23 ++++++++++++++----- polkadot/xcm/pallet-xcm/src/mock.rs | 21 ++++++----------- .../pallet-xcm/src/tests/assets_transfer.rs | 10 ++++---- .../xcm-executor/src/traits/asset_transfer.rs | 9 ++------ 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 75ec7b041fed..bba33c0efca9 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -444,8 +444,10 @@ pub mod pallet { NoSubscription, /// The location is invalid since it already has a subscription from us. AlreadySubscribed, - /// Invalid asset for the operation. - InvalidAsset(AssetTransferError), + /// Invalid non-concrete asset. + InvalidAssetNotConcrete, + /// Invalid asset, reserve chain could not be determined for it. + InvalidAssetUnknownReserve, /// The owner does not own (all) of the asset that they wish to do the operation on. LowBalance, /// The asset owner has too many locks on the asset. @@ -472,6 +474,15 @@ pub mod pallet { } } + impl From for Error { + fn from(e: AssetTransferError) -> Self { + match e { + AssetTransferError::NotConcrete => Error::::InvalidAssetNotConcrete, + AssetTransferError::UnknownReserve => Error::::InvalidAssetUnknownReserve, + } + } + } + /// The status of a query. #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] pub enum QueryStatus { @@ -1225,7 +1236,7 @@ impl Pallet { } let transfer_type = ::determine_for(&asset, dest) - .map_err(Error::::InvalidAsset)?; + .map_err(Error::::from)?; // Ensure asset is not teleportable to `dest`. ensure!(transfer_type != TransferType::Teleport, Error::::Filtered); if let Some(reserve) = reserve.as_ref() { @@ -1265,7 +1276,7 @@ impl Pallet { let mut fees = assets.swap_remove(fee_asset_item as usize); let fees_transfer_type = ::determine_for(&fees, &dest) - .map_err(Error::::InvalidAsset)?; + .map_err(Error::::from)?; let assets_transfer_type = if assets.is_empty() { // Single asset to transfer (one used for fees where transfer type is determined above). ensure!(fees_transfer_type != TransferType::Teleport, Error::::Filtered); @@ -1309,7 +1320,7 @@ impl Pallet { beneficiary, vec![fees.clone()], ::determine_for(&fees, &assets_reserve) - .map_err(Error::::InvalidAsset)?, + .map_err(Error::::from)?, fees.clone(), quarter_weight_limit.clone(), )?; @@ -1372,7 +1383,7 @@ impl Pallet { for asset in assets.iter() { let transfer_type = ::determine_for(asset, &dest) - .map_err(Error::::InvalidAsset)?; + .map_err(Error::::from)?; ensure!(matches!(transfer_type, TransferType::Teleport), Error::::Filtered); } let fees = assets.get(fee_asset_item as usize).ok_or(Error::::Empty)?.clone(); diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index b678d33251ec..7b74322e44ca 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -18,7 +18,7 @@ use codec::Encode; use frame_support::{ construct_runtime, match_types, parameter_types, traits::{ - AsEnsureOriginWithArg, ConstU128, ConstU32, Contains, Everything, EverythingBut, Nothing, + AsEnsureOriginWithArg, ConstU128, ConstU32, Equals, Everything, EverythingBut, Nothing, }, weights::Weight, }; @@ -34,17 +34,17 @@ use xcm::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia, - ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, - FixedWeightBounds, FungiblesAdapter, IsConcrete, MatchedConvertedConcreteId, NoChecking, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, XcmFeesToAccount, + ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, DescribeAllTerminal, + DescribeFamily, FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, HashedDescription, + IsConcrete, MatchedConvertedConcreteId, NoChecking, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, XcmFeesToAccount, }; use xcm_executor::{ traits::{Identity, JustTry}, XcmExecutor, }; -use crate::{self as pallet_xcm, Get, TestWeightInfo}; +use crate::{self as pallet_xcm, TestWeightInfo}; pub type AccountId = AccountId32; pub type Balance = u128; @@ -381,16 +381,9 @@ parameter_types! { pub type SovereignAccountOf = ( ChildParachainConvertsVia, AccountId32Aliases, - SiblingParachainConvertsVia, + HashedDescription>, ); -pub struct Equals(PhantomData); -impl> Contains for Equals { - fn contains(t: &MultiLocation) -> bool { - t == &Location::get() - } -} - pub type ForeignAssetsConvertedConcreteId = MatchedConvertedConcreteId< MultiLocation, Balance, diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index 586fa1671b95..bc04fcac837b 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -190,7 +190,7 @@ fn reserve_transfer_assets_with_paid_router_works() { // - local reserve // - destination reserve // - remote reserve -// - fee assests: +// - fee assets: // - reserve-transferred with reserve: // - local reserve // - destination reserve @@ -653,8 +653,8 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works /// | /// | 1. execute `InitiateReserveWithdraw(fees)` /// | \--> sends `WithdrawAsset(fees), ClearOrigin, BuyExecution(fees), DepositAsset` -/// | 2. execute `TransferReserveAsset(assts)` -/// | \-> sends `ReserveAssetDeposited(assts), ClearOrigin, BuyExecution(fees), DepositAsset` +/// | 2. execute `TransferReserveAsset(assets)` +/// | \-> sends `ReserveAssetDeposited(assets), ClearOrigin, BuyExecution(fees), DepositAsset` /// \------------------------------------------> /// ``` #[test] @@ -1426,8 +1426,8 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work /// | /// | 1. execute `InitiateTeleport(fees)` /// | \--> sends `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)` -/// | 2. execute `TransferReserveAsset(assts)` -/// | \-> sends `ReserveAssetDeposited(assts), ClearOrigin, BuyExecution(fees), DepositAsset` +/// | 2. execute `TransferReserveAsset(assets)` +/// | \-> sends `ReserveAssetDeposited(assets), ClearOrigin, BuyExecution(fees), DepositAsset` /// \------------------------------------------> /// ``` #[test] diff --git a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs index 7d6609a24226..566b65739224 100644 --- a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs +++ b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use frame_support::traits::{ContainsPair, PalletError}; +use frame_support::traits::ContainsPair; use scale_info::TypeInfo; use sp_runtime::codec::{Decode, Encode}; use xcm::prelude::*; @@ -28,12 +28,7 @@ pub enum Error { UnknownReserve, } -impl PalletError for Error { - const MAX_ENCODED_SIZE: usize = 1; -} - -/// Specify which type of asset transfer is required for a particular `(origin, asset, dest)` -/// combination. +/// Specify which type of asset transfer is required for a particular `(asset, dest)` combination. #[derive(Copy, Clone, PartialEq, Debug)] pub enum TransferType { /// should teleport `asset` to `dest` From f045c737b3d8d3d34e9ebc5e0b5f41546134e951 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 23 Oct 2023 16:56:45 +0300 Subject: [PATCH 038/124] pallet-xcm: disallow combining remote reserves with other xfer types --- .../test-utils/src/test_cases_over_bridge.rs | 1 - polkadot/xcm/pallet-xcm/src/lib.rs | 130 ++-- .../pallet-xcm/src/tests/assets_transfer.rs | 673 +++--------------- 3 files changed, 169 insertions(+), 635 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index 9852453d283b..a4f59b563485 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -183,7 +183,6 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< )); // check alice account decreased by balance_to_transfer - // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot-sdk/pull/1234) merged assert_eq!( >::free_balance(&alice_account), alice_account_init_balance - balance_to_transfer.into() diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index bba33c0efca9..257c46746ad2 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -448,6 +448,8 @@ pub mod pallet { InvalidAssetNotConcrete, /// Invalid asset, reserve chain could not be determined for it. InvalidAssetUnknownReserve, + /// Invalid asset, do not support remote asset reserves with different fees reserves. + InvalidAssetUnsupportedReserve, /// The owner does not own (all) of the asset that they wish to do the operation on. LowBalance, /// The asset owner has too many locks on the asset. @@ -1257,7 +1259,7 @@ impl Pallet { beneficiary: Box, assets: Box, fee_asset_item: u32, - mut weight_limit: WeightLimit, + weight_limit: WeightLimit, ) -> DispatchResult { let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin)?; let dest = (*dest).try_into().map_err(|()| Error::::BadVersion)?; @@ -1273,7 +1275,7 @@ impl Pallet { if fee_asset_item as usize >= assets.len() { return Err(Error::::Empty.into()) } - let mut fees = assets.swap_remove(fee_asset_item as usize); + let fees = assets.swap_remove(fee_asset_item as usize); let fees_transfer_type = ::determine_for(&fees, &dest) .map_err(Error::::from)?; @@ -1286,68 +1288,43 @@ impl Pallet { Self::validate_assets_and_find_reserve(&assets, &dest)? }; - // Disallow (for now) different _remote_ reserves for assets and fees. - match (&fees_transfer_type, &assets_transfer_type) { - (TransferType::RemoteReserve(a), TransferType::RemoteReserve(b)) if a != b => - return Err(Error::::TooManyReserves.into()), - _ => (), - }; - + let jit_withdraw_fee_on_dest; if fees_transfer_type == assets_transfer_type { // Same reserve location (fees not teleportable), we can batch together fees and assets // in same reserve-based-transfer. assets.push(fees.clone()); + // no need to jit withdraw fee, fees batched with assets will be available in holding + jit_withdraw_fee_on_dest = false; } else { - // Different transfer types: we have to do separate transfers for fees and assets. - // This code block handles transferring the assets *used for fees*. - - // Use only half the weight limit for fees transfer, then other half for assets + // Disallow _remote reserves_ unless assets & fees have same remote reserve (covered by + // branch above). The reason for this is that we'd need to send XCMs to separate chains + // with no guarantee of delivery order on final destination; therefore we cannot + // guarantee to have fees in place on final destination chain to pay for assets // transfer. - weight_limit = Self::halve_weight_limit(&weight_limit); - - // When assets reserve is remote chain, we need to "prefund" fees to be able to - // BuyExecution on both chains. Split fees, and deposit half at assets-reserve chain - // and half at destination. - if let TransferType::RemoteReserve(assets_reserve) = assets_transfer_type { - // Halve amount of fees, each half will be sent to one chain. - Self::halve_fees(&mut fees)?; - // Halve weight limit again to be used for the two fees transfers. - let quarter_weight_limit = Self::halve_weight_limit(&weight_limit); - // Send half the `fees` to `beneficiary` on assets-reserve chain. - Self::build_and_execute_xcm_transfer_type( - origin_location, - assets_reserve, - beneficiary, - vec![fees.clone()], - ::determine_for(&fees, &assets_reserve) - .map_err(Error::::from)?, - fees.clone(), - quarter_weight_limit.clone(), - )?; - // Send the other half of the `fees` to `beneficiary` on dest chain. - Self::build_and_execute_xcm_transfer_type( - origin_location, - dest, - beneficiary, - vec![fees.clone()], - fees_transfer_type, - fees.clone(), - quarter_weight_limit, - )?; - } else { - // execute fees transfer - have to do it separately than assets because of the - // different transfer type (different XCM program required) - Self::build_and_execute_xcm_transfer_type( - origin_location, - dest, - beneficiary, - vec![fees.clone()], - fees_transfer_type, - fees.clone(), - weight_limit.clone(), - )?; - } - } + if let TransferType::RemoteReserve(_) = assets_transfer_type {} + // Disallow (for now) different _remote_ reserves for assets and fees. + match (&fees_transfer_type, &assets_transfer_type) { + (TransferType::RemoteReserve(_), _) | (_, TransferType::RemoteReserve(_)) => + return Err(Error::::InvalidAssetUnsupportedReserve.into()), + _ => (), + }; + + // execute fees transfer - do it in a separate asset transfer call to keep code logic + // simple: first send over fees, then assets with `jit_withdraw=true` + Self::build_and_execute_xcm_transfer_type( + origin_location, + dest, + beneficiary, + vec![fees.clone()], + fees_transfer_type, + fees.clone(), + false, + weight_limit.clone(), + )?; + // fees are deposited to beneficiary in call above, when transferring rest of assets, + // jit withdraw fee on destination + jit_withdraw_fee_on_dest = true; + }; // Fees have been prefunded/transferred (or batched together with assets to be transferred // here), now do reserve-transfer assets. @@ -1358,6 +1335,7 @@ impl Pallet { assets, assets_transfer_type, fees, + jit_withdraw_fee_on_dest, weight_limit, ) } @@ -1395,6 +1373,7 @@ impl Pallet { assets, TransferType::Teleport, fees, + false, weight_limit, ) } @@ -1406,16 +1385,24 @@ impl Pallet { assets: Vec, transfer_type: TransferType, fees: MultiAsset, + jit_withdraw_fee_on_dest: bool, weight_limit: WeightLimit, ) -> DispatchResult { let mut message = match transfer_type { - TransferType::LocalReserve => - Self::local_reserve_transfer_message(dest, beneficiary, assets, fees, weight_limit), + TransferType::LocalReserve => Self::local_reserve_transfer_message( + dest, + beneficiary, + assets, + fees, + jit_withdraw_fee_on_dest, + weight_limit, + ), TransferType::DestinationReserve => Self::destination_reserve_transfer_message( dest, beneficiary, assets, fees, + jit_withdraw_fee_on_dest, weight_limit, ), TransferType::RemoteReserve(reserve) => Self::remote_reserve_transfer_message( @@ -1442,12 +1429,14 @@ impl Pallet { beneficiary: MultiLocation, assets: Vec, mut fees: MultiAsset, + jit_withdraw_fee_on_dest: bool, weight_limit: WeightLimit, ) -> Result::RuntimeCall>, Error> { let context = T::UniversalLocation::get(); fees.reanchor(&dest, context).map_err(|_| Error::::CannotReanchor)?; let max_assets = assets.len() as u32; let xcm_on_dest = Xcm(vec![ + SetFeesMode { jit_withdraw: jit_withdraw_fee_on_dest }, BuyExecution { fees, weight_limit }, DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, ]); @@ -1462,12 +1451,14 @@ impl Pallet { beneficiary: MultiLocation, assets: Vec, mut fees: MultiAsset, + jit_withdraw_fee_on_dest: bool, weight_limit: WeightLimit, ) -> Result::RuntimeCall>, Error> { let context = T::UniversalLocation::get(); fees.reanchor(&dest, context).map_err(|_| Error::::CannotReanchor)?; let max_assets = assets.len() as u32; let xcm_on_dest = Xcm(vec![ + SetFeesMode { jit_withdraw: jit_withdraw_fee_on_dest }, BuyExecution { fees, weight_limit }, DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, ]); @@ -1875,25 +1866,6 @@ impl Pallet { Self::deposit_event(Event::FeesPaid { paying: location, fees: assets }); Ok(()) } - - /// Return `WeightLimit` with half the given weight `limit`. - fn halve_weight_limit(limit: &WeightLimit) -> WeightLimit { - match limit { - Unlimited => Unlimited, - Limited(w) => Limited(w.saturating_div(2)), - } - } - - /// Halve `fees` fungible amount. - pub(crate) fn halve_fees(fees: &mut MultiAsset) -> Result<(), Error> { - match &mut fees.fun { - Fungible(amount) => { - *amount = amount.saturating_div(2); - Ok(()) - }, - NonFungible(_) => Err(Error::::FeesNotMet), - } - } } pub struct LockTicket { diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index bc04fcac837b..2e90b6efccbf 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -171,13 +171,12 @@ fn reserve_transfer_assets_with_paid_router_works() { Xcm(vec![ ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), ClearOrigin, + SetFeesMode { jit_withdraw: false }, buy_execution((Parent, SEND_AMOUNT)), DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, ]), )] ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); assert_eq!( last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) @@ -291,6 +290,7 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( Xcm(vec![ ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), ClearOrigin, + SetFeesMode { jit_withdraw: false }, buy_limited_execution((Parent, SEND_AMOUNT), expected_weight_limit), DepositAsset { assets: AllCounted(1).into(), @@ -299,8 +299,6 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( ]), )] ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); assert_eq!( last_event(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) @@ -462,6 +460,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ Xcm(vec![ ReserveAssetDeposited((Parent, FEE_AMOUNT).into()), ClearOrigin, + SetFeesMode { jit_withdraw: false }, buy_limited_execution((Parent, FEE_AMOUNT), Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]) @@ -474,171 +473,77 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ Xcm(vec![ WithdrawAsset(expected_asset.into()), ClearOrigin, + SetFeesMode { jit_withdraw: true }, buy_limited_execution(expected_fee, Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]) ) ] ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } /// Test `reserve_transfer_assets` with remote asset reserve and local fee reserve. /// /// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to `OTHER_PARA_ID`. -/// Using native (local reserve) as fee. -/// -/// ```nocompile -/// | chain `A` | chain `C` | chain `B` -/// | Here (source) | FOREIGN_ASSET_RESERVE_PARA_ID | OTHER_PARA_ID (destination) -/// | `fees` reserve | `assets` reserve | no trust -/// | -/// | 1. `A` executes `TransferReserveAsset(fees)` dest `C` -/// | \----------> `C` executes `WithdrawAsset(fees), .., DepositAsset(fees)` -/// | -/// | 2. `A` executes `TransferReserveAsset(fees)` dest `B` -/// | \-------------------------------------------------> `B` executes: -/// | `WithdrawAsset(fees), .., DepositAsset(fees)` -/// | -/// | 3. `A` executes `InitiateReserveWithdraw(assets)` dest `C` -/// | -----------------> `C` executes `DepositReserveAsset(assets)` dest `B` -/// | --------------------------> `DepositAsset(assets)` -/// | all of which at step 3. being paid with fees prefunded in steps 1 & 2 -/// ``` +/// Using native (local reserve) as fee should be disallowed. #[test] -fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_works() { +fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_disallowed() { let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - let expected_beneficiary_on_reserve = beneficiary; new_test_ext_with_balances(balances).execute_with(|| { // create non-sufficient foreign asset BLA (0 total issuance) let foreign_initial_amount = 142; - let (reserve_location, reserve_sovereign_account, foreign_asset_id_multilocation) = - set_up_foreign_asset( - FOREIGN_ASSET_RESERVE_PARA_ID, - Some(FOREIGN_ASSET_INNER_JUNCTION), - foreign_initial_amount, - false, - ); + let (_, _, foreign_asset_id_multilocation) = set_up_foreign_asset( + FOREIGN_ASSET_RESERVE_PARA_ID, + Some(FOREIGN_ASSET_INNER_JUNCTION), + foreign_initial_amount, + false, + ); // transfer destination is OTHER_PARA_ID (foreign asset needs to go through its reserve // chain) let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); - let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); - let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + let (assets, fee_index, _, _) = into_multiassets_checked( // native asset for fee - local reserve (MultiLocation::here(), FEE_AMOUNT).into(), // foreign asset to transfer - remote reserve (foreign_asset_id_multilocation, SEND_AMOUNT).into(), ); - // reanchor according to test-case - let context = UniversalLocation::get(); - let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); - let mut expected_fee_on_reserve = - fee_asset.clone().reanchored(&reserve_location, context).unwrap(); - let expected_asset_on_reserve = - xfer_asset.clone().reanchored(&reserve_location, context).unwrap(); - let mut expected_fee = fee_asset.reanchored(&dest, context).unwrap(); - - // fees are split between the asset-reserve chain and the destination chain - crate::Pallet::::halve_fees(&mut expected_fee_on_reserve).unwrap(); - crate::Pallet::::halve_fees(&mut expected_fee).unwrap(); - // balances checks before assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - // do the transfer - assert_ok!(XcmPallet::limited_reserve_transfer_assets( + // try the transfer + let result = XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), Box::new(dest.into()), Box::new(beneficiary.into()), Box::new(assets.into()), fee_index as u32, Unlimited, - )); - assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) - )); - - // Alice transferred BLA + ); assert_eq!( - Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_initial_amount - SEND_AMOUNT + result, + Err(DispatchError::Module(ModuleError { + index: 4, + error: [15, 0, 0, 0], + message: Some("InvalidAssetUnsupportedReserve") + })) ); + + // Alice transferred nothing + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); // Alice spent native asset for fees - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - FEE_AMOUNT); - // Half the fee went to reserve chain - assert_eq!(Balances::free_balance(reserve_sovereign_account.clone()), FEE_AMOUNT / 2); - // Other half went to dest chain - assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), FEE_AMOUNT / 2); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // Verify total and active issuance of foreign BLA asset have decreased (burned on // reserve-withdraw) - let expected_issuance = foreign_initial_amount - SEND_AMOUNT; + let expected_issuance = foreign_initial_amount; assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_issuance); assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_issuance); - - // Verify sent XCM program - assert_eq!( - sent_xcm(), - vec![ - ( - // first message is to prefund fees on `reserve` - reserve_location, - // fees are being sent through local-reserve transfer because fee reserve is - // local chain - Xcm(vec![ - ReserveAssetDeposited(expected_fee_on_reserve.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee_on_reserve.clone(), Unlimited), - DepositAsset { - assets: AllCounted(1).into(), - beneficiary: expected_beneficiary_on_reserve - }, - ]) - ), - ( - // second message is to prefund fees on `dest` - dest, - // fees are being sent through local-reserve transfer because fee reserve - // is local chain - Xcm(vec![ - ReserveAssetDeposited(expected_fee.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee.clone(), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, - ]) - ), - ( - // third message is to transfer/deposit foreign assets on `dest` by going - // through `reserve` while paying using prefunded (teleported above) fees - reserve_location, - Xcm(vec![ - WithdrawAsset(expected_asset_on_reserve.into()), - ClearOrigin, - buy_limited_execution(expected_fee_on_reserve, Unlimited), - DepositReserveAsset { - assets: Wild(AllCounted(1)), - // final destination is `dest` as seen by `reserve` - dest: expected_dest_on_reserve, - // message sent onward to final `dest` to deposit/prefund fees - xcm: Xcm(vec![ - buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary } - ]) - } - ]) - ) - ] - ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } @@ -733,6 +638,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ Xcm(vec![ WithdrawAsset(expected_fee.clone().into()), ClearOrigin, + SetFeesMode { jit_withdraw: false }, buy_limited_execution(expected_fee.clone(), Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]) @@ -746,14 +652,13 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ Xcm(vec![ ReserveAssetDeposited(expected_asset.into()), ClearOrigin, + SetFeesMode { jit_withdraw: true }, buy_limited_execution(expected_fee, Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]) ) ] ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } @@ -836,46 +741,22 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re Xcm(vec![ WithdrawAsset(expected_assets.clone()), ClearOrigin, + SetFeesMode { jit_withdraw: false }, buy_limited_execution(expected_assets.get(0).unwrap().clone(), Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]), )] ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } -/// Test `reserve_transfer_assets` with remote asset reserve and destination fee reserve. +/// Test `reserve_transfer_assets` with remote asset reserve and destination fee reserve is +/// disallowed. /// /// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to /// `USDC_RESERVE_PARA_ID`. Using USDC (destination reserve) as fee. -/// -/// ```nocompile -/// | chain `A` | chain `C` | chain `B` -/// | Here (source) | FOREIGN_ASSET_RESERVE_PARA_ID | USDC_RESERVE_PARA_ID (destination) -/// | | `assets` reserve | `fees` reserve -/// -/// 1. `A` executes `InitiateReserveWithdraw(fees)` dest `B` -/// ---------------------------------------------------> `B` executes: -/// `WithdrawAsset(fees), ClearOrigin` -/// `BuyExecution(fees)` -/// `DepositReserveAsset(fees)` dest `C` -/// `C` executes `DepositAsset(fees)` <---------------------------- -/// -/// 2. `A` executes `InitiateReserveWithdraw(fees)` dest `B` -/// ---------------------------------------------------> `B` executes: -/// `WithdrawAsset(fees), .., DepositAsset(fees)` -/// -/// 3. `A` executes `InitiateReserveWithdraw(assets)` dest `C` -/// --------------> `C` executes `DepositReserveAsset(assets)` dest `B` -/// ----------------------------> `B` executes: -/// WithdrawAsset(assets), .., DepositAsset(assets)` -/// -/// all of which at step 3. being paid with fees prefunded in steps 1 & 2 -/// ``` #[test] -fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve_works() { +fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve_disallowed() { let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); @@ -891,7 +772,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve // create non-sufficient foreign asset BLA (0 total issuance) let foreign_initial_amount = 142; - let (reserve_location, _, foreign_asset_id_multilocation) = set_up_foreign_asset( + let (_, _, foreign_asset_id_multilocation) = set_up_foreign_asset( FOREIGN_ASSET_RESERVE_PARA_ID, Some(FOREIGN_ASSET_INNER_JUNCTION), foreign_initial_amount, @@ -902,277 +783,117 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve // reserve chain) let dest = usdc_chain; - let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + let (assets, fee_index, _, _) = into_multiassets_checked( // USDC for fees (is sufficient on local chain too) - destination reserve (usdc_id_multilocation, FEE_AMOUNT).into(), // foreign asset to transfer (not used for fees) - remote reserve (foreign_asset_id_multilocation, SEND_AMOUNT).into(), ); - // reanchor according to test-case - let context = UniversalLocation::get(); - let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); - let expected_reserve_on_dest = reserve_location.reanchored(&dest, context).unwrap(); - let mut expected_fee_on_reserve = - fee_asset.clone().reanchored(&reserve_location, context).unwrap(); - let expected_asset_on_reserve = - xfer_asset.clone().reanchored(&reserve_location, context).unwrap(); - let mut expected_fee = fee_asset.reanchored(&dest, context).unwrap(); - - // fees are split between the asset-reserve chain and the destination chain - crate::Pallet::::halve_fees(&mut expected_fee_on_reserve).unwrap(); - crate::Pallet::::halve_fees(&mut expected_fee).unwrap(); - // balances checks before assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // do the transfer - assert_ok!(XcmPallet::limited_reserve_transfer_assets( + let result = XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), Box::new(dest.into()), Box::new(beneficiary.into()), Box::new(assets.into()), fee_index as u32, Unlimited, - )); - assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) - )); - - // Alice native asset untouched - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - // Alice spent USDC for fees - assert_eq!( - Assets::balance(usdc_id_multilocation, ALICE), - usdc_initial_local_amount - FEE_AMOUNT ); - // Alice transferred BLA assert_eq!( - Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_initial_amount - SEND_AMOUNT + result, + Err(DispatchError::Module(ModuleError { + index: 4, + error: [15, 0, 0, 0], + message: Some("InvalidAssetUnsupportedReserve") + })) ); - // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) - let expected_usdc_issuance = usdc_initial_local_amount - FEE_AMOUNT; + + // Alice native asset untouched + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); + let expected_usdc_issuance = usdc_initial_local_amount; assert_eq!(Assets::total_issuance(usdc_id_multilocation), expected_usdc_issuance); assert_eq!(Assets::active_issuance(usdc_id_multilocation), expected_usdc_issuance); - // Verify total and active issuance of foreign BLA asset have decreased (burned on - // reserve-withdraw) - let expected_bla_issuance = foreign_initial_amount - SEND_AMOUNT; + let expected_bla_issuance = foreign_initial_amount; assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_bla_issuance); assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_bla_issuance); - - // Verify sent XCM program - assert_eq!( - sent_xcm(), - vec![ - ( - // first message is to prefund fees on `reserve`, but we need to go through - // `fee_reserve == dest` to get them there - dest, - // fees are reserve-withdrawn on `dest` chain then reserve-deposited to - // `asset_reserve` chain - Xcm(vec![ - WithdrawAsset(expected_fee.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee.clone(), Unlimited), - DepositReserveAsset { - assets: Wild(AllCounted(1)), - // final fees destination is `asset_reserve` as seen by `dest` - dest: expected_reserve_on_dest, - // message sent onward to final `dest` to deposit/prefund fees - xcm: Xcm(vec![ - buy_limited_execution(expected_fee_on_reserve.clone(), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary } - ]) - } - ]) - ), - ( - // second message is to prefund fees on `dest` - dest, - // fees are reserve-withdrawn on destination chain - Xcm(vec![ - WithdrawAsset(expected_fee.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee.clone(), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, - ]) - ), - ( - // third message is to transfer/deposit foreign assets on `dest` by going - // through `reserve` while paying using prefunded (teleported above) fees - reserve_location, - Xcm(vec![ - WithdrawAsset(expected_asset_on_reserve.into()), - ClearOrigin, - buy_limited_execution(expected_fee_on_reserve, Unlimited), - DepositReserveAsset { - assets: Wild(AllCounted(1)), - // final destination is `dest` as seen by `reserve` - dest: expected_dest_on_reserve, - // message sent onward to final `dest` to deposit/prefund fees - xcm: Xcm(vec![ - buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary } - ]) - } - ]) - ) - ] - ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } -/// Test `reserve_transfer_assets` with local asset reserve and remote fee reserve. +/// Test `reserve_transfer_assets` with local asset reserve and remote fee reserve is disallowed. /// /// Transferring native asset (local reserve) to `OTHER_PARA_ID` (no teleport trust). Using foreign /// asset (`USDC_RESERVE_PARA_ID` remote reserve) for fees. -/// -/// ```nocompile -/// | chain `A` | chain `C` | chain `B` -/// | Here (source) | USDC_RESERVE_PARA_ID | OTHER_PARA_ID (destination) -/// | `assets` reserve | `fees` reserve | -/// | -/// | 1. `A` executes `InitiateReserveWithdraw(fees)` dest `C` -/// | -----------------> `C` executes `DepositReserveAsset(fees)` dest `B` -/// | --------------------------> `DepositAsset(fees)` -/// | 2. `A` executes `TransferReserveAsset(assets)` dest `B` -/// | --------------------------------------------------> `ReserveAssetDeposited(assets)` -/// ``` #[test] -fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_works() { +fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_disallowed() { let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDC (0 total issuance) let usdc_initial_local_amount = 142; - let (fee_reserve_location, usdc_chain_sovereign_account, usdc_id_multilocation) = - set_up_foreign_asset( - USDC_RESERVE_PARA_ID, - Some(USDC_INNER_JUNCTION), - usdc_initial_local_amount, - true, - ); + let (_, usdc_chain_sovereign_account, usdc_id_multilocation) = set_up_foreign_asset( + USDC_RESERVE_PARA_ID, + Some(USDC_INNER_JUNCTION), + usdc_initial_local_amount, + true, + ); // transfer destination is some other parachain != fee reserve location (no teleport trust) let dest = RelayLocation::get().pushed_with_interior(Parachain(OTHER_PARA_ID)).unwrap(); let dest_sovereign_account = SovereignAccountOf::convert_location(&dest).unwrap(); - let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + let (assets, fee_index, _, _) = into_multiassets_checked( // USDC for fees (is sufficient on local chain too) - remote reserve (usdc_id_multilocation, FEE_AMOUNT).into(), // native asset to transfer (not used for fees) - local reserve (MultiLocation::here(), SEND_AMOUNT).into(), ); - // reanchor according to test-case - let context = UniversalLocation::get(); - let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); - let expected_fee_on_reserve = - fee_asset.clone().reanchored(&fee_reserve_location, context).unwrap(); - let expected_fee = fee_asset.reanchored(&dest, context).unwrap(); - let expected_asset = xfer_asset.reanchored(&dest, context).unwrap(); - // balances checks before assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // do the transfer - assert_ok!(XcmPallet::limited_reserve_transfer_assets( + let result = XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), Box::new(dest.into()), Box::new(beneficiary.into()), Box::new(assets.into()), fee_index as u32, Unlimited, - )); - assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) - )); - // Alice spent (fees) amount + ); assert_eq!( - Assets::balance(usdc_id_multilocation, ALICE), - usdc_initial_local_amount - FEE_AMOUNT + result, + Err(DispatchError::Module(ModuleError { + index: 4, + error: [15, 0, 0, 0], + message: Some("InvalidAssetUnsupportedReserve") + })) ); - // Alice used native asset for transfer - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); + assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // Sovereign account of reserve parachain is unchanged assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), 0); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); - // Sovereign account of destination parachain holds `SEND_AMOUNT` in local reserve - assert_eq!(Balances::free_balance(dest_sovereign_account), SEND_AMOUNT); - // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) - let expected_usdc_issuance = usdc_initial_local_amount - FEE_AMOUNT; + assert_eq!(Balances::free_balance(dest_sovereign_account), 0); + let expected_usdc_issuance = usdc_initial_local_amount; assert_eq!(Assets::total_issuance(usdc_id_multilocation), expected_usdc_issuance); assert_eq!(Assets::active_issuance(usdc_id_multilocation), expected_usdc_issuance); - - // Verify sent XCM program - assert_eq!( - sent_xcm(), - vec![ - ( - // first message is to prefund (USDC) fees on `dest` (by going through - // fee remote (USDC) reserve) - fee_reserve_location, - Xcm(vec![ - WithdrawAsset(expected_fee_on_reserve.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee_on_reserve, Unlimited), - DepositReserveAsset { - assets: Wild(AllCounted(1)), - // final destination is `dest` as seen by `reserve` - dest: expected_dest_on_reserve, - // message sent onward to final `dest` to deposit/prefund fees - xcm: Xcm(vec![ - buy_limited_execution(expected_fee.clone(), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary } - ]) - } - ]) - ), - ( - // second message is to transfer/deposit (native) asset on `dest` while paying - // using prefunded (transferred above) fees/USDC - dest, - // transfer is through local-reserve transfer because `assets` (native asset) - // have local reserve - Xcm(vec![ - ReserveAssetDeposited(expected_asset.into()), - ClearOrigin, - buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, - ]) - ) - ] - ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } -/// Test `reserve_transfer_assets` with destination asset reserve and remote fee reserve. +/// Test `reserve_transfer_assets` with destination asset reserve and remote fee reserve is +/// disallowed. /// /// Transferring native asset (local reserve) to `OTHER_PARA_ID` (no teleport trust). Using foreign /// asset (`USDC_RESERVE_PARA_ID` remote reserve) for fees. -/// -/// ```nocompile -/// | chain `A` | chain `C` | chain `B` -/// | Here (source) | USDC_RESERVE_PARA_ID | FOREIGN_ASSET_RESERVE_PARA_ID (destination) -/// | | `fees` reserve | `assets` reserve -/// | -/// | 1. `A` executes `InitiateReserveWithdraw(fees)` dest `C` -/// | -----------------> `C` executes `DepositReserveAsset(fees)` dest `B` -/// | --------------------------> `DepositAsset(fees)` -/// | 2. `A` executes `InitiateReserveWithdraw(assets)` dest `B` -/// | --------------------------------------------------> `DepositAsset(assets)` -/// ``` #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve_works() { let balances = vec![(ALICE, INITIAL_BALANCE)]; @@ -1181,13 +902,12 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDC (0 total issuance) let usdc_initial_local_amount = 42; - let (fee_reserve_location, usdc_chain_sovereign_account, usdc_id_multilocation) = - set_up_foreign_asset( - USDC_RESERVE_PARA_ID, - Some(USDC_INNER_JUNCTION), - usdc_initial_local_amount, - true, - ); + let (_, usdc_chain_sovereign_account, usdc_id_multilocation) = set_up_foreign_asset( + USDC_RESERVE_PARA_ID, + Some(USDC_INNER_JUNCTION), + usdc_initial_local_amount, + true, + ); // create non-sufficient foreign asset BLA (0 total issuance) let foreign_initial_amount = 142; @@ -1203,106 +923,48 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve let dest = reserve_location; let dest_sovereign_account = foreign_sovereign_account; - let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + let (assets, fee_index, _, _) = into_multiassets_checked( // USDC for fees (is sufficient on local chain too) - remote reserve (usdc_id_multilocation, FEE_AMOUNT).into(), // foreign asset to transfer (not used for fees) - destination reserve (foreign_asset_id_multilocation, SEND_AMOUNT).into(), ); - // reanchor according to test-case - let context = UniversalLocation::get(); - let expected_dest_on_reserve = dest.reanchored(&fee_reserve_location, context).unwrap(); - let expected_fee_on_reserve = - fee_asset.clone().reanchored(&fee_reserve_location, context).unwrap(); - let expected_fee = fee_asset.reanchored(&dest, context).unwrap(); - let expected_asset = xfer_asset.reanchored(&dest, context).unwrap(); - // balances checks before assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // do the transfer - assert_ok!(XcmPallet::limited_reserve_transfer_assets( + let result = XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), Box::new(dest.into()), Box::new(beneficiary.into()), Box::new(assets.into()), fee_index as u32, Unlimited, - )); - assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) - )); - // Alice native asset untouched - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - // Alice spent USDC for fees - assert_eq!( - Assets::balance(usdc_id_multilocation, ALICE), - usdc_initial_local_amount - FEE_AMOUNT ); - // Alice transferred BLA assert_eq!( - Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_initial_amount - SEND_AMOUNT + result, + Err(DispatchError::Module(ModuleError { + index: 4, + error: [15, 0, 0, 0], + message: Some("InvalidAssetUnsupportedReserve") + })) ); - // Verify balances of USDC reserve parachain + // Alice native asset untouched + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + assert_eq!(Assets::balance(usdc_id_multilocation, ALICE), usdc_initial_local_amount); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); assert_eq!(Balances::free_balance(usdc_chain_sovereign_account.clone()), 0); assert_eq!(Assets::balance(usdc_id_multilocation, usdc_chain_sovereign_account), 0); - // Verify balances of transferred-asset reserve parachain assert_eq!(Balances::free_balance(dest_sovereign_account.clone()), 0); assert_eq!(Assets::balance(foreign_asset_id_multilocation, dest_sovereign_account), 0); - // Verify total and active issuance of USDC have decreased (burned on reserve-withdraw) - let expected_usdc_issuance = usdc_initial_local_amount - FEE_AMOUNT; + let expected_usdc_issuance = usdc_initial_local_amount; assert_eq!(Assets::total_issuance(usdc_id_multilocation), expected_usdc_issuance); assert_eq!(Assets::active_issuance(usdc_id_multilocation), expected_usdc_issuance); - // Verify total and active issuance of foreign BLA asset have decreased (burned on - // reserve-withdraw) - let expected_bla_issuance = foreign_initial_amount - SEND_AMOUNT; + let expected_bla_issuance = foreign_initial_amount; assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_bla_issuance); assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_bla_issuance); - - // Verify sent XCM program - assert_eq!( - sent_xcm(), - vec![ - ( - // first message is to prefund (USDC) fees on `dest` (by going through - // fee remote (USDC) reserve) - fee_reserve_location, - Xcm(vec![ - WithdrawAsset(expected_fee_on_reserve.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee_on_reserve, Unlimited), - DepositReserveAsset { - assets: Wild(AllCounted(1)), - // final destination is `dest` as seen by `reserve` - dest: expected_dest_on_reserve, - // message sent onward to final `dest` to deposit/prefund fees - xcm: Xcm(vec![ - buy_limited_execution(expected_fee.clone(), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary } - ]) - } - ]) - ), - ( - // second message is to transfer/deposit foreign assets on `dest` while paying - // using prefunded (transferred above) fees (USDC) - // (dest is reserve location for `expected_asset`) - dest, - Xcm(vec![ - WithdrawAsset(expected_asset.into()), - ClearOrigin, - buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, - ]) - ) - ] - ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } @@ -1410,8 +1072,6 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_remote_fee_reserve_work ]) )], ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } @@ -1512,14 +1172,13 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { Xcm(vec![ ReserveAssetDeposited(expected_asset.into()), ClearOrigin, + SetFeesMode { jit_withdraw: true }, buy_limited_execution(expected_fee, Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]) ) ] ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } @@ -1644,45 +1303,25 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor Xcm(vec![ WithdrawAsset(expected_asset.into()), ClearOrigin, + SetFeesMode { jit_withdraw: true }, buy_limited_execution(expected_fee, Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]) ) ] ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } -/// Test `reserve_transfer_assets` with remote asset reserve and teleported fee. +/// Test `reserve_transfer_assets` with remote asset reserve and teleported fee is disallowed. /// -/// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to `USDT_PARA_ID`. Using -/// teleport-trusted USDT for fees. -/// -/// ```nocompile -/// | chain `A` | chain `C` | chain `B` -/// | Here (source) | FOREIGN_ASSET_RESERVE_PARA_ID | USDT_PARA_ID (destination) -/// | | `assets` reserve | `fees` (USDT) teleport-trust -/// | -/// | 1. `A` executes `InitiateTeleport(fees)` dest `C` -/// | \----------> `C` executes `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)` -/// | -/// | 2. `A` executes `InitiateTeleport(fees)` dest `B` -/// | \-------------------------------------------------> `B` executes: -/// | `ReceiveTeleportedAsset(fees), .., DepositAsset(fees)` -/// | -/// | 3. `A` executes `InitiateReserveWithdraw(assets)` dest `C` -/// | -----------------> `C` executes `DepositReserveAsset(assets)` dest `B` -/// | --------------------------> `DepositAsset(assets)` -/// | all of which at step 3. being paid with fees prefunded in steps 1 & 2 -/// ``` +/// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to `USDT_PARA_ID`. +/// Using teleport-trusted USDT for fees. #[test] fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() { let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - let expected_beneficiary_on_reserve = beneficiary; new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDT (0 total issuance) let usdt_initial_local_amount = 42; @@ -1691,135 +1330,58 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() // create non-sufficient foreign asset BLA (0 total issuance) let foreign_initial_amount = 142; - let (reserve_location, reserve_sovereign_account, foreign_asset_id_multilocation) = - set_up_foreign_asset( - FOREIGN_ASSET_RESERVE_PARA_ID, - Some(FOREIGN_ASSET_INNER_JUNCTION), - foreign_initial_amount, - false, - ); + let (_, reserve_sovereign_account, foreign_asset_id_multilocation) = set_up_foreign_asset( + FOREIGN_ASSET_RESERVE_PARA_ID, + Some(FOREIGN_ASSET_INNER_JUNCTION), + foreign_initial_amount, + false, + ); // transfer destination is USDT chain (foreign asset needs to go through its reserve chain) let dest = usdt_chain; - let (assets, fee_index, fee_asset, xfer_asset) = into_multiassets_checked( + let (assets, fee_index, _, _) = into_multiassets_checked( // USDT for fees (is sufficient on local chain too) - teleported (usdt_id_multilocation, FEE_AMOUNT).into(), // foreign asset to transfer (not used for fees) - remote reserve (foreign_asset_id_multilocation, SEND_AMOUNT).into(), ); - // reanchor according to test-case - let context = UniversalLocation::get(); - let expected_dest_on_reserve = dest.reanchored(&reserve_location, context).unwrap(); - let mut expected_fee_on_reserve = - fee_asset.clone().reanchored(&reserve_location, context).unwrap(); - let expected_asset_on_reserve = - xfer_asset.clone().reanchored(&reserve_location, context).unwrap(); - let mut expected_fee = fee_asset.reanchored(&dest, context).unwrap(); - - // fees are split between the asset-reserve chain and the destination chain - crate::Pallet::::halve_fees(&mut expected_fee_on_reserve).unwrap(); - crate::Pallet::::halve_fees(&mut expected_fee).unwrap(); - // balances checks before assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); // do the transfer - assert_ok!(XcmPallet::limited_reserve_transfer_assets( + let result = XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), Box::new(dest.into()), Box::new(beneficiary.into()), Box::new(assets.into()), fee_index as u32, Unlimited, - )); - assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) - )); - // Alice native asset untouched - assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); - // Alice spent USDT for fees - assert_eq!( - Assets::balance(usdt_id_multilocation, ALICE), - usdt_initial_local_amount - FEE_AMOUNT ); - // Alice transferred BLA assert_eq!( - Assets::balance(foreign_asset_id_multilocation, ALICE), - foreign_initial_amount - SEND_AMOUNT + result, + Err(DispatchError::Module(ModuleError { + index: 4, + error: [15, 0, 0, 0], + message: Some("InvalidAssetUnsupportedReserve") + })) ); - // Verify balances of USDT reserve parachain + // Alice native asset untouched + assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); + assert_eq!(Assets::balance(usdt_id_multilocation, ALICE), usdt_initial_local_amount); + assert_eq!(Assets::balance(foreign_asset_id_multilocation, ALICE), foreign_initial_amount); assert_eq!(Balances::free_balance(usdt_chain_sovereign_account.clone()), 0); assert_eq!(Assets::balance(usdt_id_multilocation, usdt_chain_sovereign_account), 0); - // Verify balances of transferred-asset reserve parachain assert_eq!(Balances::free_balance(reserve_sovereign_account.clone()), 0); assert_eq!(Assets::balance(foreign_asset_id_multilocation, reserve_sovereign_account), 0); - // Verify total and active issuance of USDT have decreased (teleported) - let expected_usdt_issuance = usdt_initial_local_amount - FEE_AMOUNT; + let expected_usdt_issuance = usdt_initial_local_amount; assert_eq!(Assets::total_issuance(usdt_id_multilocation), expected_usdt_issuance); assert_eq!(Assets::active_issuance(usdt_id_multilocation), expected_usdt_issuance); - // Verify total and active issuance of foreign BLA asset have decreased (burned on - // reserve-withdraw) - let expected_bla_issuance = foreign_initial_amount - SEND_AMOUNT; + let expected_bla_issuance = foreign_initial_amount; assert_eq!(Assets::total_issuance(foreign_asset_id_multilocation), expected_bla_issuance); assert_eq!(Assets::active_issuance(foreign_asset_id_multilocation), expected_bla_issuance); - - // Verify sent XCM program - assert_eq!( - sent_xcm(), - vec![ - ( - // first message is to prefund fees on `reserve` - reserve_location, - // fees are teleported to reserve chain - Xcm(vec![ - ReceiveTeleportedAsset(expected_fee_on_reserve.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee_on_reserve.clone(), Unlimited), - DepositAsset { - assets: AllCounted(1).into(), - beneficiary: expected_beneficiary_on_reserve - }, - ]) - ), - ( - // second message is to prefund fees on `dest` - dest, - // fees are teleported to destination chain - Xcm(vec![ - ReceiveTeleportedAsset(expected_fee.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee.clone(), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, - ]) - ), - ( - // third message is to transfer/deposit foreign assets on `dest` by going - // through `reserve` while paying using prefunded (teleported above) fees - reserve_location, - Xcm(vec![ - WithdrawAsset(expected_asset_on_reserve.into()), - ClearOrigin, - buy_limited_execution(expected_fee_on_reserve, Unlimited), - DepositReserveAsset { - assets: Wild(AllCounted(1)), - // final destination is `dest` as seen by `reserve` - dest: expected_dest_on_reserve, - // message sent onward to final `dest` to deposit/prefund fees - xcm: Xcm(vec![ - buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary } - ]) - } - ]) - ) - ] - ); - let versioned_sent = VersionedXcm::from(sent_xcm().into_iter().next().unwrap().1); - let _check_v2_ok: xcm::v2::Xcm<()> = versioned_sent.try_into().unwrap(); }); } @@ -1831,6 +1393,7 @@ fn reserve_transfer_assets_with_teleportable_asset_fails() { let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + new_test_ext_with_balances(balances).execute_with(|| { // create sufficient foreign asset USDT (0 total issuance) let usdt_initial_local_amount = 42; From d1a9709e5f8a45d1fdedab6734ed659dd05ee722 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 23 Oct 2023 18:07:50 +0300 Subject: [PATCH 039/124] xcm-barriers: allow SetFeesMode in BuyExecution barrier and fix tests --- .../assets/test-utils/src/test_cases.rs | 21 +++++----- .../test-utils/src/test_cases_over_bridge.rs | 40 +++++++++++-------- polkadot/xcm/xcm-builder/src/barriers.rs | 2 + 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index af9fc4475cf9..2a32989aae9a 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -1463,7 +1463,8 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< ); // drip ED to account - let alice_account_init_balance = existential_deposit + balance_to_transfer.into(); + let alice_account_init_balance = + existential_deposit.saturating_mul(2.into()) + balance_to_transfer.into(); let _ = >::deposit_creating( &alice_account, alice_account_init_balance, @@ -1503,6 +1504,15 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< weight_limit, )); + // check events + // check pallet_xcm attempted + RuntimeHelper::::assert_pallet_xcm_event_outcome( + &unwrap_pallet_xcm_event, + |outcome| { + assert_ok!(outcome.ensure_complete()); + }, + ); + // check alice account decreased by balance_to_transfer // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot/pull/7005) merged assert_eq!( @@ -1517,15 +1527,6 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< existential_deposit + balance_to_transfer.into() ); - // check events - // check pallet_xcm attempted - RuntimeHelper::::assert_pallet_xcm_event_outcome( - &unwrap_pallet_xcm_event, - |outcome| { - assert_ok!(outcome.ensure_complete()); - }, - ); - // check that xcm was sent let xcm_sent_message_hash = >::events() .into_iter() diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index a4f59b563485..2d4039357660 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -30,7 +30,7 @@ use parachains_runtimes_test_utils::{ mock_open_hrmp_channel, AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, RuntimeHelper, ValidatorIdOf, XcmReceivedFrom, }; -use sp_runtime::traits::StaticLookup; +use sp_runtime::{traits::StaticLookup, Saturating}; use xcm::{latest::prelude::*, VersionedMultiAssets}; use xcm_builder::{CreateMatcher, MatchXcm}; use xcm_executor::{traits::ConvertLocation, XcmExecutor}; @@ -127,7 +127,8 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< ); // drip ED to account - let alice_account_init_balance = existential_deposit + balance_to_transfer.into(); + let alice_account_init_balance = + existential_deposit.saturating_mul(2.into()) + balance_to_transfer.into(); let _ = >::deposit_creating( &alice_account, alice_account_init_balance, @@ -168,7 +169,7 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< // Make sure sender has enough funds for paying delivery fees // TODO: Get this fee via weighing the corresponding message - let delivery_fees = 1324039894; + let delivery_fees = 1324173226; >::mint_into(&alice_account, delivery_fees.into()) .unwrap(); @@ -182,19 +183,6 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< weight_limit, )); - // check alice account decreased by balance_to_transfer - assert_eq!( - >::free_balance(&alice_account), - alice_account_init_balance - balance_to_transfer.into() - ); - - // check reserve account - // check reserve account increased by balance_to_transfer - assert_eq!( - >::free_balance(&reserve_account), - existential_deposit + balance_to_transfer.into() - ); - // check events // check pallet_xcm attempted RuntimeHelper::::assert_pallet_xcm_event_outcome( @@ -219,7 +207,6 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< local_bridge_hub_para_id.into(), ) .unwrap(); - assert_eq!( xcm_sent_message_hash, Some(xcm_sent.using_encoded(sp_io::hashing::blake2_256)) @@ -274,6 +261,19 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< _ => Err(ProcessMessageError::BadFormat), }) .expect("contains ExportMessage"); + + // check alice account decreased by balance_to_transfer + assert_eq!( + >::free_balance(&alice_account), + alice_account_init_balance - balance_to_transfer.into() + ); + + // check reserve account + // check reserve account increased by balance_to_transfer + assert_eq!( + >::free_balance(&reserve_account), + existential_deposit + balance_to_transfer.into() + ); }) } @@ -415,6 +415,7 @@ pub fn receive_reserve_asset_deposited_from_different_consensus_works< fun: Fungible(transfered_foreign_asset_id_amount), }])), ClearOrigin, + SetFeesMode { jit_withdraw: false }, BuyExecution { fees: MultiAsset { id: Concrete(foreign_asset_id_multilocation), @@ -516,6 +517,11 @@ fn assert_matches_pallet_xcm_reserve_transfer_assets_instructions( _ => Err(ProcessMessageError::BadFormat), }) .expect("expected instruction ClearOrigin") + .match_next_inst(|instr| match instr { + SetFeesMode { .. } => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction SetFeesMode") .match_next_inst(|instr| match instr { BuyExecution { .. } => Ok(()), _ => Err(ProcessMessageError::BadFormat), diff --git a/polkadot/xcm/xcm-builder/src/barriers.rs b/polkadot/xcm/xcm-builder/src/barriers.rs index 3b13cab2c1ea..50098791b443 100644 --- a/polkadot/xcm/xcm-builder/src/barriers.rs +++ b/polkadot/xcm/xcm-builder/src/barriers.rs @@ -88,6 +88,8 @@ impl> ShouldExecute for AllowTopLevelPaidExecutionFro _ => Err(ProcessMessageError::BadFormat), })? .skip_inst_while(|inst| matches!(inst, ClearOrigin))? + // allow setting fees mode to jit or not for use in following `BuyExecution` + .skip_inst_while(|inst| matches!(inst, SetFeesMode { .. }))? .match_next_inst(|inst| match inst { BuyExecution { weight_limit: Limited(ref mut weight), .. } if weight.all_gte(max_weight) => From 955fe40b4c5465748fb9abf7bd540ba3bdbbcc68 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 19 Oct 2023 15:43:40 +0200 Subject: [PATCH 040/124] adds message queue pallet --- Cargo.lock | 1 + .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 2 ++ .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 27 ++++++++++++++++++- substrate/frame/nomination-pools/src/lib.rs | 1 + 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index a8d679c6ce8b..903d709329ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2068,6 +2068,7 @@ dependencies = [ "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-collator-selection", + "pallet-message-queue", "pallet-multisig", "pallet-session", "pallet-timestamp", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 5befb21c8911..4e220e68c2e6 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -29,6 +29,7 @@ pallet-authorship = { path = "../../../../../substrate/frame/authorship", defaul pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false} pallet-session = { path = "../../../../../substrate/frame/session", default-features = false} pallet-multisig = { path = "../../../../../substrate/frame/multisig", default-features = false} +pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false} pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false} pallet-transaction-payment-rpc-runtime-api = { path = "../../../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false} @@ -139,6 +140,7 @@ std = [ "pallet-bridge-relayers/std", "pallet-collator-selection/std", "pallet-multisig/std", + "pallet-message-queue/std", "pallet-session/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 5973801d37c4..1832fdf8ec33 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -327,7 +327,8 @@ impl pallet_transaction_payment::Config for Runtime { parameter_types! { pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + // For beacon checkpoint to work require a bigger default + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT; } impl cumulus_pallet_parachain_system::Config for Runtime { @@ -457,6 +458,25 @@ impl pallet_utility::Config for Runtime { type WeightInfo = weights::pallet_utility::WeightInfo; } +parameter_types! { + /// Amount of weight that can be spent per block to service messages. + pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000); + pub const MessageQueueHeapSize: u32 = 65_536; + pub const MessageQueueMaxStale: u32 = 16; +} + +impl pallet_message_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Size = u32; + type HeapSize = MessageQueueHeapSize; + type MaxStale = MessageQueueMaxStale; + type ServiceWeight = MessageQueueServiceWeight; + type MessageProcessor = (); + type QueueChangeHandler = (); + type QueuePausedQuery = (); + type WeightInfo = (); +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -505,6 +525,10 @@ construct_runtime!( BridgeWococoToRococoMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 45, BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 47, + + // Message Queue. Registered after EthereumOutboundQueue so that their `on_initialize` handlers + // run in the desired order. + MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} = 60, } ); @@ -528,6 +552,7 @@ mod benches { [frame_system, SystemBench::] [pallet_balances, Balances] [pallet_multisig, Multisig] + [pallet_message_queue, MessageQueue] [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 909a930e3821..8d78ff546a39 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3406,6 +3406,7 @@ impl Pallet { // Warn if any pool has incorrect ED frozen. We don't want to fail hard as this could be a // result of an intentional ED change. + #[cfg(any(feature = "try-runtime", feature = "runtime-benchmarks", test, debug_assertions))] let _ = Self::check_ed_imbalance()?; Ok(()) From 00d27560819c12c7bdf1cfbfadbd9d0ac30e766e Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 19 Oct 2023 16:00:32 +0200 Subject: [PATCH 041/124] adds outbound queue --- Cargo.lock | 171 ++++++++++++++++++ .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 4 + .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 25 ++- 3 files changed, 198 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 903d709329ef..4d1cfb4fe19a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,6 +197,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4436e0292ab1bb631b42973c61205e704475fe8126af845c8d923c0996328127" +[[package]] +name = "amcl" +version = "0.3.0" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -2087,6 +2096,7 @@ dependencies = [ "scale-info", "serde", "smallvec", + "snowbridge-outbound-queue", "sp-api", "sp-block-builder", "sp-consensus-aura", @@ -4871,6 +4881,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ethabi-decode" +version = "1.4.0" +source = "git+https://github.com/Snowfork/ethabi-decode.git?branch=master#7d215837b626650bd9a076821e57ad488101301f" +dependencies = [ + "ethereum-types", + "tiny-keccak", +] + [[package]] name = "ethbloom" version = "0.13.0" @@ -4879,8 +4898,10 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "tiny-keccak", ] @@ -4892,9 +4913,11 @@ checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", "primitive-types", + "scale-info", "uint", ] @@ -7922,6 +7945,20 @@ dependencies = [ "thrift", ] +[[package]] +name = "milagro_bls" +version = "1.5.0" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" +dependencies = [ + "amcl", + "hex", + "lazy_static", + "parity-scale-codec", + "rand 0.8.5", + "scale-info", + "zeroize", +] + [[package]] name = "mime" version = "0.3.17" @@ -11162,6 +11199,12 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "parity-bytes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b56e3a2420138bdb970f84dfb9c774aea80fa0e7371549eedec0d80c209c67" + [[package]] name = "parity-db" version = "0.4.10" @@ -16234,6 +16277,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd31f59f6fe2b0c055371bb2f16d7f0aa7d8881676c04a55b1596d1a17cd10a4" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.188" @@ -16672,6 +16724,102 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "snowbridge-beacon-primitives" +version = "0.0.1" +dependencies = [ + "byte-slice-cast", + "frame-support", + "frame-system", + "hex", + "milagro_bls", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-ethereum", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "ssz_rs", + "ssz_rs_derive", + "static_assertions", +] + +[[package]] +name = "snowbridge-core" +version = "0.1.1" +dependencies = [ + "derivative", + "ethabi-decode", + "frame-support", + "frame-system", + "parity-scale-codec", + "polkadot-parachain-primitives", + "scale-info", + "serde", + "snowbridge-beacon-primitives", + "snowbridge-ethereum", + "sp-core", + "sp-runtime", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "snowbridge-ethereum" +version = "0.1.0" +dependencies = [ + "ethabi-decode", + "ethbloom", + "ethereum-types", + "hex-literal", + "parity-bytes", + "parity-scale-codec", + "rlp", + "rustc-hex", + "scale-info", + "serde", + "serde-big-array", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "snowbridge-outbound-queue" +version = "0.1.1" +dependencies = [ + "bp-runtime", + "ethabi-decode", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde", + "snowbridge-core", + "snowbridge-outbound-queue-merkle-tree", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "snowbridge-outbound-queue-merkle-tree" +version = "0.1.1" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + [[package]] name = "socket2" version = "0.4.9" @@ -17649,6 +17797,29 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ssz_rs" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057291e5631f280978fa9c8009390663ca4613359fc1318e36a8c24c392f6d1f" +dependencies = [ + "bitvec", + "num-bigint", + "sha2 0.9.9", + "ssz_rs_derive", +] + +[[package]] +name = "ssz_rs_derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f07d54c4d01a1713eb363b55ba51595da15f6f1211435b71466460da022aa140" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 4e220e68c2e6..c6a3d60e897d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -92,6 +92,9 @@ pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false } bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false } +# Ethereum Bridge (Snowbridge) +snowbridge-outbound-queue = { path = "../../../../../../parachain/pallets/outbound-queue", default-features = false } + [dev-dependencies] static_assertions = "1.1" bridge-hub-test-utils = { path = "../test-utils" } @@ -174,6 +177,7 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", + "snowbridge-outbound-queue/std", ] runtime-benchmarks = [ diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 1832fdf8ec33..e55ec1499d94 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -42,7 +42,7 @@ use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT}, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, Keccak256}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, }; @@ -471,12 +471,31 @@ impl pallet_message_queue::Config for Runtime { type HeapSize = MessageQueueHeapSize; type MaxStale = MessageQueueMaxStale; type ServiceWeight = MessageQueueServiceWeight; - type MessageProcessor = (); + type MessageProcessor = EthereumOutboundQueue; type QueueChangeHandler = (); type QueuePausedQuery = (); type WeightInfo = (); } +parameter_types! { + pub const MaxMessagePayloadSize: u32 = 2048; + pub const MaxMessagesPerBlock: u32 = 32; +} + +impl snowbridge_outbound_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Hashing = Keccak256; + type MessageQueue = MessageQueue; + type MaxMessagePayloadSize = MaxMessagePayloadSize; + type MaxMessagesPerBlock = MaxMessagesPerBlock; + type GasMeter = snowbridge_core::outbound::ConstantGasMeter; + type Balance = Balance; + type DeliveryFeePerGas = DeliveryFeePerGas; + type DeliveryRefundPerGas = DeliveryRefundPerGas; + type DeliveryReward = DeliveryReward; + type WeightInfo = (); +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -526,6 +545,8 @@ construct_runtime!( BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 47, + EthereumOutboundQueue: snowbridge_outbound_queue::{Pallet, Call, Storage, Event} = 49, + // Message Queue. Registered after EthereumOutboundQueue so that their `on_initialize` handlers // run in the desired order. MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} = 60, From e39beb118c6d911ea587c1458d5b4a53eb121089 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 19 Oct 2023 20:46:37 +0200 Subject: [PATCH 042/124] fix compiler errors --- Cargo.lock | 1 + .../runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml | 2 ++ .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 4d1cfb4fe19a..d2e827ad794d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2096,6 +2096,7 @@ dependencies = [ "scale-info", "serde", "smallvec", + "snowbridge-core", "snowbridge-outbound-queue", "sp-api", "sp-block-builder", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index c6a3d60e897d..31497db4c4e7 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -93,6 +93,7 @@ pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", def bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false } # Ethereum Bridge (Snowbridge) +snowbridge-core = { path = "../../../../../../parachain/primitives/core", default-features = false } snowbridge-outbound-queue = { path = "../../../../../../parachain/pallets/outbound-queue", default-features = false } [dev-dependencies] @@ -177,6 +178,7 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", + "snowbridge-core/std", "snowbridge-outbound-queue/std", ] diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index e55ec1499d94..b7aa500277b4 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -477,9 +477,14 @@ impl pallet_message_queue::Config for Runtime { type WeightInfo = (); } +pub const GWEI: u128 = 1_000_000_000; + parameter_types! { pub const MaxMessagePayloadSize: u32 = 2048; pub const MaxMessagesPerBlock: u32 = 32; + pub const DeliveryFeePerGas: u128 = 10; + pub const DeliveryRefundPerGas: u128 = 10 * GWEI; + pub const DeliveryReward: u128 = 1000 * GWEI; } impl snowbridge_outbound_queue::Config for Runtime { From 3c16e0f9074edb5d419ab76bd99f7c0410be8310 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 19 Oct 2023 21:57:26 +0200 Subject: [PATCH 043/124] adds snowbridge to rococo bridgehub --- Cargo.lock | 119 +++++++++++ .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 21 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 149 ++++++++++++- .../bridge-hub-rococo/src/weights/mod.rs | 3 + .../src/weights/snowbridge_control.rs | 202 ++++++++++++++++++ .../snowbridge_ethereum_beacon_client.rs | 137 ++++++++++++ .../src/weights/snowbridge_inbound_queue.rs | 55 +++++ .../bridge-hub-rococo/src/xcm_config.rs | 82 ++++++- 8 files changed, 762 insertions(+), 6 deletions(-) create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs diff --git a/Cargo.lock b/Cargo.lock index d2e827ad794d..b41a10fe6170 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2096,8 +2096,14 @@ dependencies = [ "scale-info", "serde", "smallvec", + "snowbridge-beacon-primitives", + "snowbridge-control", "snowbridge-core", + "snowbridge-ethereum-beacon-client", + "snowbridge-inbound-queue", "snowbridge-outbound-queue", + "snowbridge-outbound-queue-runtime-api", + "snowbridge-router-primitives", "sp-api", "sp-block-builder", "sp-consensus-aura", @@ -16748,6 +16754,27 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "snowbridge-control" +version = "4.0.0-dev" +dependencies = [ + "ethabi-decode", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "snowbridge-core", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + [[package]] name = "snowbridge-core" version = "0.1.1" @@ -16789,6 +16816,61 @@ dependencies = [ "sp-std", ] +[[package]] +name = "snowbridge-ethereum-beacon-client" +version = "0.0.1" +dependencies = [ + "bp-runtime", + "byte-slice-cast", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex-literal", + "log", + "pallet-timestamp", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-ethereum", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "ssz_rs", + "ssz_rs_derive", + "static_assertions", +] + +[[package]] +name = "snowbridge-inbound-queue" +version = "0.1.1" +dependencies = [ + "bp-runtime", + "ethabi-decode", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex-literal", + "pallet-balances", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-ethereum", + "snowbridge-router-primitives", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", +] + [[package]] name = "snowbridge-outbound-queue" version = "0.1.1" @@ -16798,7 +16880,9 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "hex-literal", "parity-scale-codec", + "rlp", "scale-info", "serde", "snowbridge-core", @@ -16821,6 +16905,41 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "snowbridge-outbound-queue-runtime-api" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "snowbridge-core", + "snowbridge-outbound-queue-merkle-tree", + "sp-api", + "sp-core", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "snowbridge-router-primitives" +version = "0.1.1" +dependencies = [ + "ethabi-decode", + "frame-support", + "frame-system", + "hex-literal", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "snowbridge-core", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + [[package]] name = "socket2" version = "0.4.9" diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 31497db4c4e7..7738967b1a54 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -94,7 +94,13 @@ bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", de # Ethereum Bridge (Snowbridge) snowbridge-core = { path = "../../../../../../parachain/primitives/core", default-features = false } +snowbridge-beacon-primitives = { path = "../../../../../../parachain/primitives/beacon", default-features = false } +snowbridge-router-primitives = { path = "../../../../../../parachain/primitives/router", default-features = false } +snowbridge-ethereum-beacon-client = { path = "../../../../../../parachain/pallets/ethereum-beacon-client", default-features = false } +snowbridge-inbound-queue = { path = "../../../../../../parachain/pallets/inbound-queue", default-features = false } snowbridge-outbound-queue = { path = "../../../../../../parachain/pallets/outbound-queue", default-features = false } +snowbridge-outbound-queue-runtime-api = { path = "../../../../../../parachain/pallets/outbound-queue/runtime-api", default-features = false } +snowbridge-control = { path = "../../../../../../parachain/pallets/control", default-features = false } [dev-dependencies] static_assertions = "1.1" @@ -179,7 +185,13 @@ std = [ "xcm-executor/std", "xcm/std", "snowbridge-core/std", + "snowbridge-router-primitives/std", + "snowbridge-beacon-primitives/std", + "snowbridge-ethereum-beacon-client/std", + "snowbridge-inbound-queue/std", "snowbridge-outbound-queue/std", + "snowbridge-outbound-queue-runtime-api/std", + "snowbridge-control/std", ] runtime-benchmarks = [ @@ -209,6 +221,11 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "snowbridge-core/runtime-benchmarks", + "snowbridge-control/runtime-benchmarks", + "snowbridge-inbound-queue/runtime-benchmarks", + "snowbridge-outbound-queue/runtime-benchmarks", + "snowbridge-ethereum-beacon-client/runtime-benchmarks" ] try-runtime = [ @@ -239,5 +256,7 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", ] - +beacon-spec-mainnet = [ + "snowbridge-ethereum-beacon-client/beacon-spec-mainnet", +] experimental = [ "pallet-aura/experimental" ] diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index b7aa500277b4..22e9949ae0d0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -38,8 +38,11 @@ pub mod xcm_config; use codec::{Decode, Encode}; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; +use snowbridge_beacon_primitives::{Fork, ForkVersions}; +use snowbridge_router_primitives::inbound::MessageToXcm; use sp_api::impl_runtime_apis; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160}; +use sp_runtime::traits::AccountIdConversion; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, Keccak256}, @@ -47,6 +50,18 @@ use sp_runtime::{ ApplyExtrinsicResult, }; +#[cfg(feature = "runtime-benchmarks")] +use crate::xcm_config::benchmark_helper::DoNothingRouter; +#[cfg(feature = "runtime-benchmarks")] +use snowbridge_beacon_primitives::CompactExecutionHeader; +#[cfg(feature = "runtime-benchmarks")] +use snowbridge_core::RingBufferMap; +#[cfg(feature = "runtime-benchmarks")] +pub use snowbridge_ethereum_beacon_client::ExecutionHeaderBuffer; +#[cfg(feature = "runtime-benchmarks")] +use snowbridge_inbound_queue::BenchmarkHelper; +#[cfg(feature = "runtime-benchmarks")] +use sp_core::H256; use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; @@ -65,9 +80,12 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, }; + +use pallet_xcm::EnsureXcm; + pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; pub use sp_runtime::{MultiAddress, Perbill, Permill}; -use xcm_config::{XcmConfig, XcmOriginToTransactDispatchOrigin}; +use xcm_config::{EthereumGatewayAddress, XcmConfig, XcmOriginToTransactDispatchOrigin}; use bp_runtime::HeaderId; @@ -79,6 +97,8 @@ use xcm::latest::prelude::*; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +#[cfg(not(feature = "runtime-benchmarks"))] +use crate::xcm_config::AllowSiblingsOnly; use crate::{ bridge_hub_rococo_config::BridgeRefundBridgeHubWococoMessages, bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages, xcm_config::XcmRouter, @@ -477,6 +497,40 @@ impl pallet_message_queue::Config for Runtime { type WeightInfo = (); } +// Ethereum Bridge + +parameter_types! { + pub const Reward: u128 = 10; + pub const GatewayAddress: H160 = H160(EthereumGatewayAddress::get()); + pub const CreateAssetCall: [u8;2] = [53, 0]; + pub const CreateAssetExecutionFee: u128 = 2_000_000_000; + pub const SendTokenExecutionFee: u128 = 1_000_000_000; +} + +#[cfg(feature = "runtime-benchmarks")] +impl BenchmarkHelper for Runtime { + fn initialize_storage(block_hash: H256, header: CompactExecutionHeader) { + >::insert(block_hash, header); + } +} + +impl snowbridge_inbound_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Verifier = snowbridge_ethereum_beacon_client::Pallet; + type Token = Balances; + type Reward = Reward; + #[cfg(not(feature = "runtime-benchmarks"))] + type XcmSender = XcmRouter; + #[cfg(feature = "runtime-benchmarks")] + type XcmSender = DoNothingRouter; + type WeightInfo = weights::snowbridge_inbound_queue::WeightInfo; + type GatewayAddress = GatewayAddress; + #[cfg(feature = "runtime-benchmarks")] + type Helper = Runtime; + type MessageConverter = + MessageToXcm; +} + pub const GWEI: u128 = 1_000_000_000; parameter_types! { @@ -501,6 +555,90 @@ impl snowbridge_outbound_queue::Config for Runtime { type WeightInfo = (); } +#[cfg(not(feature = "beacon-spec-mainnet"))] +parameter_types! { + pub const ChainForkVersions: ForkVersions = ForkVersions { + genesis: Fork { + version: [0, 0, 0, 1], // 0x00000001 + epoch: 0, + }, + altair: Fork { + version: [1, 0, 0, 1], // 0x01000001 + epoch: 0, + }, + bellatrix: Fork { + version: [2, 0, 0, 1], // 0x02000001 + epoch: 0, + }, + capella: Fork { + version: [3, 0, 0, 1], // 0x03000001 + epoch: 0, + }, + }; + pub const MaxExecutionHeadersToKeep:u32 = 1000; +} + +#[cfg(feature = "beacon-spec-mainnet")] +parameter_types! { + pub const ChainForkVersions: ForkVersions = ForkVersions { + genesis: Fork { + version: [0, 0, 16, 32], // 0x00001020 + epoch: 0, + }, + altair: Fork { + version: [1, 0, 16, 32], // 0x01001020 + epoch: 36660, + }, + bellatrix: Fork { + version: [2, 0, 16, 32], // 0x02001020 + epoch: 112260, + }, + capella: Fork { + version: [3, 0, 16, 32], // 0x03001020 + epoch: 162304, + }, + }; + pub const MaxExecutionHeadersToKeep:u32 = 8192 * 2; +} + +impl snowbridge_ethereum_beacon_client::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type ForkVersions = ChainForkVersions; + type MaxExecutionHeadersToKeep = MaxExecutionHeadersToKeep; + type WeightInfo = weights::snowbridge_ethereum_beacon_client::WeightInfo; +} + +parameter_types! { + // TODO: placeholder value - choose a real one + pub const MaxUpgradeDataSize: u32 = 1024; + pub const RelayNetwork: NetworkId = Rococo; +} + +parameter_types! { + pub TreasuryAccount: AccountId = PalletId(*b"py/trsry").into_account_truncating(); +} + +#[cfg(feature = "runtime-benchmarks")] +impl snowbridge_control::BenchmarkHelper for () { + fn make_xcm_origin(location: xcm::latest::MultiLocation) -> RuntimeOrigin { + RuntimeOrigin::from(pallet_xcm::Origin::Xcm(location)) + } +} + +impl snowbridge_control::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OwnParaId = ParachainInfo; + type OutboundQueue = EthereumOutboundQueue; + type MessageHasher = BlakeTwo256; + type SiblingOrigin = EnsureXcm; + type AgentIdOf = xcm_config::AgentIdOf; + type TreasuryAccount = TreasuryAccount; + type Token = Balances; + type WeightInfo = weights::snowbridge_control::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -550,7 +688,10 @@ construct_runtime!( BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 47, + EthereumInboundQueue: snowbridge_inbound_queue::{Pallet, Call, Storage, Event} = 48, EthereumOutboundQueue: snowbridge_outbound_queue::{Pallet, Call, Storage, Event} = 49, + EthereumBeaconClient: snowbridge_ethereum_beacon_client::{Pallet, Call, Storage, Event} = 50, + EthereumControl: snowbridge_control::{Pallet, Call, Storage, Event} = 51, // Message Queue. Registered after EthereumOutboundQueue so that their `on_initialize` handlers // run in the desired order. @@ -599,6 +740,10 @@ mod benches { [pallet_bridge_messages, WococoToRococo] // Bridge relayer pallets [pallet_bridge_relayers, BridgeRelayersBench::] + // Ethereum Bridge + [snowbridge_inbound_queue, EthereumInboundQueue] + [snowbridge_control, EthereumControl] + [snowbridge_ethereum_beacon_client, EthereumBeaconClient] ); } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs index c41900097a1b..2dab4c4d0257 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs @@ -37,6 +37,9 @@ pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; pub mod rocksdb_weights; +pub mod snowbridge_ethereum_beacon_client; +pub mod snowbridge_inbound_queue; +pub mod snowbridge_control; pub mod xcm; pub use block_weights::constants::BlockExecutionWeight; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs new file mode 100644 index 000000000000..06e12a2a0382 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs @@ -0,0 +1,202 @@ + +//! Autogenerated weights for `snowbridge_control` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-10-09, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `crake.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/polkadot-parachain +// benchmark +// pallet +// --chain +// bridge-hub-rococo-dev +// --pallet=snowbridge_control +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --output +// parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `snowbridge_control`. +pub struct WeightInfo(PhantomData); +impl snowbridge_control::WeightInfo for WeightInfo { + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn upgrade() -> Weight { + // Proof Size summary in bytes: + // Measured: `80` + // Estimated: `3517` + // Minimum execution time: 47_000_000 picoseconds. + Weight::from_parts(47_000_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: EthereumControl Agents (r:1 w:1) + /// Proof: EthereumControl Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn create_agent() -> Weight { + // Proof Size summary in bytes: + // Measured: `187` + // Estimated: `6196` + // Minimum execution time: 87_000_000 picoseconds. + Weight::from_parts(87_000_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) + } + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: EthereumControl Agents (r:1 w:0) + /// Proof: EthereumControl Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: EthereumControl Channels (r:1 w:1) + /// Proof: EthereumControl Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn create_channel() -> Weight { + // Proof Size summary in bytes: + // Measured: `602` + // Estimated: `69050` + // Minimum execution time: 84_000_000 picoseconds. + Weight::from_parts(84_000_000, 0) + .saturating_add(Weight::from_parts(0, 69050)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: EthereumControl Channels (r:1 w:0) + /// Proof: EthereumControl Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn update_channel() -> Weight { + // Proof Size summary in bytes: + // Measured: `256` + // Estimated: `6044` + // Minimum execution time: 41_000_000 picoseconds. + Weight::from_parts(41_000_000, 0) + .saturating_add(Weight::from_parts(0, 6044)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: EthereumControl Channels (r:1 w:0) + /// Proof: EthereumControl Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn force_update_channel() -> Weight { + // Proof Size summary in bytes: + // Measured: `256` + // Estimated: `6044` + // Minimum execution time: 41_000_000 picoseconds. + Weight::from_parts(41_000_000, 0) + .saturating_add(Weight::from_parts(0, 6044)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn set_operating_mode() -> Weight { + // Proof Size summary in bytes: + // Measured: `80` + // Estimated: `3517` + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(30_000_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: EthereumControl Agents (r:1 w:0) + /// Proof: EthereumControl Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn transfer_native_from_agent() -> Weight { + // Proof Size summary in bytes: + // Measured: `252` + // Estimated: `6044` + // Minimum execution time: 43_000_000 picoseconds. + Weight::from_parts(43_000_000, 0) + .saturating_add(Weight::from_parts(0, 6044)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: EthereumControl Agents (r:1 w:0) + /// Proof: EthereumControl Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn force_transfer_native_from_agent() -> Weight { + // Proof Size summary in bytes: + // Measured: `252` + // Estimated: `6044` + // Minimum execution time: 42_000_000 picoseconds. + Weight::from_parts(42_000_000, 0) + .saturating_add(Weight::from_parts(0, 6044)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs new file mode 100644 index 000000000000..4ca518b45b87 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs @@ -0,0 +1,137 @@ + +//! Autogenerated weights for `snowbridge_ethereum_beacon_client` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-172-31-8-124`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/polkadot-parachain +// benchmark +// pallet +// --base-path +// /mnt/scratch/benchmark +// --chain=bridge-hub-rococo-dev +// --pallet=snowbridge_ethereum_beacon_client +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --steps +// 50 +// --repeat +// 20 +// --output +// ./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `snowbridge_ethereum_beacon_client`. +pub struct WeightInfo(PhantomData); +impl snowbridge_ethereum_beacon_client::WeightInfo for WeightInfo { + /// Storage: EthereumBeaconClient FinalizedBeaconStateIndex (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconStateIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconStateMapping (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconStateMapping (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient NextSyncCommittee (r:0 w:1) + /// Proof: EthereumBeaconClient NextSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient InitialCheckpointRoot (r:0 w:1) + /// Proof: EthereumBeaconClient InitialCheckpointRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ValidatorsRoot (r:0 w:1) + /// Proof: EthereumBeaconClient ValidatorsRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:0 w:1) + /// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient CurrentSyncCommittee (r:0 w:1) + /// Proof: EthereumBeaconClient CurrentSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestExecutionState (r:0 w:1) + /// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconState (r:0 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + fn force_checkpoint() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `3501` + // Minimum execution time: 97_185_781_000 picoseconds. + Weight::from_parts(97_263_571_000, 0) + .saturating_add(Weight::from_parts(0, 3501)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(9)) + } + /// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:1 w:1) + /// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconState (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestExecutionState (r:1 w:0) + /// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient NextSyncCommittee (r:1 w:0) + /// Proof: EthereumBeaconClient NextSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient CurrentSyncCommittee (r:1 w:0) + /// Proof: EthereumBeaconClient CurrentSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ValidatorsRoot (r:1 w:0) + /// Proof: EthereumBeaconClient ValidatorsRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconStateIndex (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconStateIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconStateMapping (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconStateMapping (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + fn submit() -> Weight { + // Proof Size summary in bytes: + // Measured: `92753` + // Estimated: `93857` + // Minimum execution time: 25_999_968_000 picoseconds. + Weight::from_parts(26_051_019_000, 0) + .saturating_add(Weight::from_parts(0, 93857)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:1 w:0) + /// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconState (r:1 w:0) + /// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestExecutionState (r:1 w:0) + /// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient NextSyncCommittee (r:1 w:1) + /// Proof: EthereumBeaconClient NextSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient CurrentSyncCommittee (r:1 w:0) + /// Proof: EthereumBeaconClient CurrentSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ValidatorsRoot (r:1 w:0) + /// Proof: EthereumBeaconClient ValidatorsRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + fn submit_with_sync_committee() -> Weight { + // Proof Size summary in bytes: + // Measured: `92717` + // Estimated: `93857` + // Minimum execution time: 122_354_917_000 picoseconds. + Weight::from_parts(122_461_312_000, 0) + .saturating_add(Weight::from_parts(0, 93857)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:1 w:0) + /// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconState (r:1 w:0) + /// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestExecutionState (r:1 w:1) + /// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ExecutionHeaderIndex (r:1 w:1) + /// Proof: EthereumBeaconClient ExecutionHeaderIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ExecutionHeaderMapping (r:1 w:1) + /// Proof: EthereumBeaconClient ExecutionHeaderMapping (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ExecutionHeaders (r:0 w:1) + /// Proof: EthereumBeaconClient ExecutionHeaders (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen) + fn submit_execution_header() -> Weight { + // Proof Size summary in bytes: + // Measured: `386` + // Estimated: `3537` + // Minimum execution time: 108_761_000 picoseconds. + Weight::from_parts(113_158_000, 0) + .saturating_add(Weight::from_parts(0, 3537)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs new file mode 100644 index 000000000000..ae04fa162504 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs @@ -0,0 +1,55 @@ + +//! Autogenerated weights for `snowbridge_inbound_queue` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-09-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `macbook pro 14 m2`, CPU: `m2-arm64` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/polkadot-parachain +// benchmark +// pallet +// --chain=bridge-hub-rococo-dev +// --pallet=snowbridge_inbound_queue +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --steps +// 50 +// --repeat +// 20 +// --output +// ./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `snowbridge_inbound_queue`. +pub struct WeightInfo(PhantomData); +impl snowbridge_inbound_queue::WeightInfo for WeightInfo { + /// Storage: EthereumInboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumInboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ExecutionHeaders (r:1 w:0) + /// Proof: EthereumBeaconClient ExecutionHeaders (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen) + /// Storage: EthereumInboundQueue Nonce (r:1 w:1) + /// Proof: EthereumInboundQueue Nonce (max_values: None, max_size: Some(20), added: 2495, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn submit() -> Weight { + // Proof Size summary in bytes: + // Measured: `457` + // Estimated: `3601` + // Minimum execution time: 69_000_000 picoseconds. + Weight::from_parts(70_000_000, 0) + .saturating_add(Weight::from_parts(0, 3601)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 703acfa44174..d2a41ab6d580 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -41,7 +41,7 @@ use parachains_common::{ use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; use rococo_runtime_constants::system_parachain::SystemParachains; -use sp_core::Get; +use sp_core::{Get, H256}; use sp_runtime::traits::AccountIdConversion; use xcm::latest::prelude::*; use xcm_builder::{ @@ -51,12 +51,13 @@ use xcm_builder::{ ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, - XcmFeesToAccount, + XcmFeesToAccount, HashedDescription, DescribeFamily, DescribeAllTerminal }; use xcm_executor::{ traits::{ExportXcm, WithOriginFilter}, XcmExecutor, }; +use snowbridge_router_primitives::outbound::EthereumBlobExporter; parameter_types! { pub storage Flavor: RuntimeFlavor = RuntimeFlavor::default(); @@ -67,6 +68,21 @@ parameter_types! { pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; pub TreasuryAccount: Option = Some(TREASURY_PALLET_ID.into_account_truncating()); + + + // Network and location for the local Ethereum testnet. + pub const EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; + pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); + + pub const EthereumGatewayAddress: [u8; 20] = hex_literal::hex!("EDa338E4dC46038493b885327842fD3E301CaB39"); + // The Registry contract for the bridge which is also the origin for reserves and the prefix of all assets. + pub EthereumGatewayLocation: MultiLocation = EthereumLocation::get() + .pushed_with_interior( + AccountKey20 { + network: None, + key: EthereumGatewayAddress::get(), + } + ).unwrap(); } /// Adapter for resolving `NetworkId` based on `pub storage Flavor: RuntimeFlavor`. @@ -204,7 +220,18 @@ impl Contains for SafeCallFilter { RuntimeCall::BridgeWococoGrandpa(pallet_bridge_grandpa::Call::< Runtime, BridgeGrandpaWococoInstance, - >::initialize { .. }) + >::initialize { .. }) | + RuntimeCall::EthereumBeaconClient( + snowbridge_ethereum_beacon_client::Call::force_checkpoint { .. } + | snowbridge_ethereum_beacon_client::Call::set_owner { .. } + | snowbridge_ethereum_beacon_client::Call::set_operating_mode { .. }, + ) | RuntimeCall::EthereumInboundQueue( + snowbridge_inbound_queue::Call::set_owner { .. } + | snowbridge_inbound_queue::Call::set_operating_mode { .. }, + ) | RuntimeCall::EthereumOutboundQueue( + snowbridge_outbound_queue::Call::set_owner { .. } | + snowbridge_outbound_queue::Call::set_operating_mode { .. }, + ) | RuntimeCall::EthereumControl(..) ) } } @@ -306,6 +333,22 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; +#[cfg(feature = "runtime-benchmarks")] +pub(crate) mod benchmark_helper { + use crate::xcm_config::{MultiAssets, MultiLocation, SendError, SendResult, SendXcm, Xcm, XcmHash}; + + pub struct DoNothingRouter; + impl SendXcm for DoNothingRouter { + type Ticket = (); + fn validate(_dest: &mut Option, _msg: &mut Option>) -> SendResult<()> { + Ok(((), MultiAssets::new())) + } + fn deliver(_: ()) -> Result { + Ok([0; 32]) + } + } +} + #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); @@ -350,6 +393,15 @@ impl cumulus_pallet_xcm::Config for Runtime { type XcmExecutor = XcmExecutor; } +pub type AgentIdOf = HashedDescription>; + +pub type SnowbridgeExporter = EthereumBlobExporter< + UniversalLocation, + EthereumGatewayLocation, + snowbridge_outbound_queue::Pallet, + AgentIdOf, +>; + /// Hacky switch implementation, because we have just one runtime for Rococo and Wococo BridgeHub, /// so it means we have just one XcmConfig pub struct BridgeHubRococoOrBridgeHubWococoSwitchExporter; @@ -380,6 +432,16 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { message, ) .map(|result| ((Wococo, result.0), result.1)), + location if location == EthereumNetwork::get() && network == Rococo => { + SnowbridgeExporter::validate( + network, + channel, + universal_source, + destination, + message, + ) + .map(|result| ((Ethereum {chain_id: 15}, result.0), result.1)) // TODO get network ID + }, _ => unimplemented!("Unsupported network: {:?}", network), } } @@ -389,7 +451,21 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { match network { Rococo => ToBridgeHubRococoHaulBlobExporter::deliver(ticket), Wococo => ToBridgeHubWococoHaulBlobExporter::deliver(ticket), + location if location == EthereumNetwork::get() && network == Rococo => { + SnowbridgeExporter::deliver(ticket) + }, _ => unimplemented!("Unsupported network: {:?}", network), } } } + +pub struct AllowSiblingsOnly; +impl Contains for AllowSiblingsOnly { + fn contains(location: &MultiLocation) -> bool { + if let MultiLocation { parents: 1, interior: X1(Parachain(_)) } = location { + true + } else { + false + } + } +} From a3157896c8e471d9cd0cd35b062d52d36db4aeed Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Fri, 20 Oct 2023 06:16:39 +0200 Subject: [PATCH 044/124] asset hub rococo --- Cargo.lock | 5 + cumulus/pallets/dmp-queue/src/lib.rs | 21 +- .../parachain-template/node/src/chain_spec.rs | 6 +- .../pallets/template/Cargo.toml | 7 + .../pallets/template/src/lib.rs | 37 +- .../bridges/bridge-hub-rococo/Cargo.toml | 3 + .../bridge-hub-rococo/src/tests/mod.rs | 1 + .../bridge-hub-rococo/src/tests/snowbridge.rs | 126 ++++++ .../emulated/common/src/lib.rs | 1 + .../assets/asset-hub-rococo/Cargo.toml | 2 + .../assets/asset-hub-rococo/src/lib.rs | 156 +++---- .../assets/asset-hub-rococo/src/xcm_config.rs | 412 ++++++++++-------- 12 files changed, 506 insertions(+), 271 deletions(-) create mode 100644 cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs diff --git a/Cargo.lock b/Cargo.lock index b41a10fe6170..fa41280a104a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -886,6 +886,7 @@ dependencies = [ "rococo-runtime-constants", "scale-info", "smallvec", + "snowbridge-router-primitives", "sp-api", "sp-block-builder", "sp-consensus-aura", @@ -2029,6 +2030,7 @@ dependencies = [ "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-runtime-parachains", + "snowbridge-control", "staging-xcm", "staging-xcm-executor", "xcm-emulator", @@ -10318,12 +10320,15 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "pallet-xcm", "parity-scale-codec", "scale-info", "serde", "sp-core", "sp-io", "sp-runtime", + "sp-std", + "staging-xcm", ] [[package]] diff --git a/cumulus/pallets/dmp-queue/src/lib.rs b/cumulus/pallets/dmp-queue/src/lib.rs index eff4a625ef1b..9ec84ca7fe7b 100644 --- a/cumulus/pallets/dmp-queue/src/lib.rs +++ b/cumulus/pallets/dmp-queue/src/lib.rs @@ -54,9 +54,10 @@ pub struct ConfigData { impl Default for ConfigData { fn default() -> Self { Self { + // For beacon checkpoint to work require a bigger default max_individual: Weight::from_parts( - 10u64 * WEIGHT_REF_TIME_PER_MILLIS, // 10 ms of execution time maximum by default - DEFAULT_POV_SIZE, // 64 KB of proof size by default + 20u64 * 10u64 * WEIGHT_REF_TIME_PER_MILLIS, // 200 ms of execution time maximum by default + 10u64 * DEFAULT_POV_SIZE, // 640 KB of proof size by default ), } } @@ -230,7 +231,7 @@ pub mod pallet { if *messages_processed >= MAX_MESSAGES_PER_BLOCK { // Exceeded block message limit - put the remaining messages back and bail Pages::::insert(page_index.begin_used, &page[i..]); - return used + return used; } *messages_processed += 1; match Self::try_service_message(limit.saturating_sub(used), sent_at, &data[..]) @@ -239,7 +240,7 @@ pub mod pallet { Err(..) => { // Too much weight needed - put the remaining messages back and bail Pages::::insert(page_index.begin_used, &page[i..]); - return used + return used; }, } } @@ -288,8 +289,9 @@ pub mod pallet { Weight::zero(), ); match outcome { - Outcome::Error(XcmError::WeightLimitReached(required_weight)) => - Err(ServiceMessageError { message_hash, message_id, required_weight }), + Outcome::Error(XcmError::WeightLimitReached(required_weight)) => { + Err(ServiceMessageError { message_hash, message_id, required_weight }) + }, outcome => { let weight_used = outcome.weight_used(); Self::deposit_event(Event::ExecutedDownward { @@ -370,7 +372,7 @@ pub mod pallet { // Not needed for control flow, but only to ensure that the // compiler understands that we won't attempt to re-use `data` // later. - continue + continue; } else { // not overweight. stop executing inline and enqueue normally // from here on. @@ -517,8 +519,9 @@ mod tests { ) -> Outcome { let message = prepared.0; let o = match (message.0.len(), &message.0.first()) { - (1, Some(Transact { require_weight_at_most, .. })) => - Outcome::Complete(*require_weight_at_most), + (1, Some(Transact { require_weight_at_most, .. })) => { + Outcome::Complete(*require_weight_at_most) + }, // use 1000 to decide that it's not supported. _ => Outcome::Incomplete(Weight::from_parts(1, 1), XcmError::Unimplemented), }; diff --git a/cumulus/parachain-template/node/src/chain_spec.rs b/cumulus/parachain-template/node/src/chain_spec.rs index 0ca3c51900f2..733e6136d7e6 100644 --- a/cumulus/parachain-template/node/src/chain_spec.rs +++ b/cumulus/parachain-template/node/src/chain_spec.rs @@ -102,7 +102,7 @@ pub fn development_config() -> ChainSpec { get_account_id_from_seed::("Ferdie//stash"), ], get_account_id_from_seed::("Alice"), - 1000.into(), + 1001.into(), ) }, Vec::new(), @@ -112,7 +112,7 @@ pub fn development_config() -> ChainSpec { None, Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: 1000, + para_id: 1001, }, ) } @@ -174,7 +174,7 @@ pub fn local_testnet_config() -> ChainSpec { // Extensions Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: 1000, + para_id: 1001, }, ) } diff --git a/cumulus/parachain-template/pallets/template/Cargo.toml b/cumulus/parachain-template/pallets/template/Cargo.toml index 925457839348..71f7371a73ce 100644 --- a/cumulus/parachain-template/pallets/template/Cargo.toml +++ b/cumulus/parachain-template/pallets/template/Cargo.toml @@ -27,6 +27,10 @@ serde = { version = "1.0.188" } sp-core = { path = "../../../../substrate/primitives/core", default-features = false} sp-io = { path = "../../../../substrate/primitives/io", default-features = false} sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false} +sp-std = { path = "../../../../substrate/primitives/std", default-features = false} + +pallet-xcm = { path = "../../../../polkadot/xcm/pallet-xcm", default-features = false} +xcm = { package = "staging-xcm", path = "../../../../polkadot/xcm", default-features = false} [features] default = [ "std" ] @@ -45,6 +49,9 @@ std = [ "sp-core/std", "sp-io/std", "sp-runtime/std", + "sp-std/std", + "pallet-xcm/std", + "xcm/std", ] try-runtime = [ "frame-support/try-runtime", diff --git a/cumulus/parachain-template/pallets/template/src/lib.rs b/cumulus/parachain-template/pallets/template/src/lib.rs index 5f3252bfc3a7..911896d15d40 100644 --- a/cumulus/parachain-template/pallets/template/src/lib.rs +++ b/cumulus/parachain-template/pallets/template/src/lib.rs @@ -18,10 +18,12 @@ mod benchmarking; pub mod pallet { use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*}; use frame_system::pallet_prelude::*; + use sp_std::boxed::Box; + use xcm::{v3::prelude::*, VersionedMultiLocation, VersionedXcm}; /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] - pub trait Config: frame_system::Config { + pub trait Config: frame_system::Config + pallet_xcm::Config { /// Because this pallet emits events, it depends on the runtime's definition of an event. type RuntimeEvent: From> + IsType<::RuntimeEvent>; } @@ -45,6 +47,8 @@ pub mod pallet { /// Event documentation should end with an array that provides descriptive names for event /// parameters. [something, who] SomethingStored(u32, T::AccountId), + /// XCM message sent. \[to, message\] + Sent { from: T::AccountId, to: MultiLocation, message: Xcm<()> }, } // Errors inform users that something went wrong. @@ -54,6 +58,15 @@ pub mod pallet { NoneValue, /// Errors should have helpful documentation associated with them. StorageOverflow, + /// The message and destination combination was not recognized as being + /// reachable. + Unreachable, + /// The message and destination was recognized as being reachable but + /// the operation could not be completed. + SendFailure, + /// The version of the `Versioned` value used is not able to be + /// interpreted. + BadVersion, } #[pallet::hooks] @@ -102,5 +115,27 @@ pub mod pallet { }, } } + + /// Send an XCM message as parachain sovereign. + #[pallet::call_index(2)] + #[pallet::weight(Weight::from_parts(100_000_000, 0))] + pub fn send_xcm( + origin: OriginFor, + dest: Box, + message: Box>, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let dest = MultiLocation::try_from(*dest).map_err(|()| Error::::BadVersion)?; + let message: Xcm<()> = (*message).try_into().map_err(|()| Error::::BadVersion)?; + + pallet_xcm::Pallet::::send_xcm(Here, dest, message.clone()).map_err( + |e| match e { + SendError::Unroutable => Error::::Unreachable, + _ => Error::::SendFailure, + }, + )?; + Self::deposit_event(Event::Sent { from: who, to: dest, message }); + Ok(()) + } } } diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml index b3ce2a99f70a..29499034fba5 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml @@ -33,3 +33,6 @@ bridge-hub-rococo-runtime = { path = "../../../../../parachains/runtimes/bridge- # Local xcm-emulator = { path = "../../../../../xcm/xcm-emulator", default-features = false} integration-tests-common = { path = "../../common", default-features = false} + +# Snowbridge +snowbridge-control = { path = "../../../../../../../parachain/pallets/control" } diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs index 1eef05c6b928..6d439b634f4e 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs @@ -14,4 +14,5 @@ // limitations under the License. mod example; +mod snowbridge; mod teleport; diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs new file mode 100644 index 000000000000..fa494fbac3c6 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -0,0 +1,126 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::*; +use integration_tests_common::BridgeHubRococoPallet; +use snowbridge_control; + +#[test] +fn create_agent() { + let sudo_origin = ::RuntimeOrigin::root(); + let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into(); + + let remote_xcm = VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, + DescendOrigin(X1(Parachain(1000))), + Transact { + require_weight_at_most: 3000000000.into(), + origin_kind: OriginKind::Xcm, + call: vec![51, 1].into(), + }, + ])); + + //Rococo Global Consensus + // Send XCM message from Relay Chain to Bridge Hub source Parachain + Rococo::execute_with(|| { + assert_ok!(::XcmPallet::send( + sudo_origin, + bx!(destination), + bx!(remote_xcm), + )); + + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward { + outcome: Outcome::Complete(_), + .. + }) => {}, + RuntimeEvent::EthereumControl(snowbridge_control::Event::CreateAgent { + .. + }) => {}, + ] + ); + }); +} + +#[test] +fn create_channel() { + let sudo_origin = ::RuntimeOrigin::root(); + let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into(); + + let remote_xcm = VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, + DescendOrigin(X1(Parachain(1000))), + Transact { + require_weight_at_most: 8000000000.into(), + origin_kind: OriginKind::Xcm, + call: vec![51, 2].into(), + }, + ])); + + //BridgeHubRococo::execute_with(|| { // TODO Create agent in storage + // ::EthereumControl::create_agent(sudo_origin); + //}); + + //Rococo Global Consensus + // Send XCM message from Relay Chain to Bridge Hub source Parachain + Rococo::execute_with(|| { + assert_ok!(::XcmPallet::send( + sudo_origin, + bx!(destination), + bx!(remote_xcm), + )); + + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward { + outcome: Outcome::Complete(_), + .. + }) => {}, + RuntimeEvent::EthereumControl(snowbridge_control::Event::CreateChannel { + .. + }) => {}, + ] + ); + }); +} diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index 8a8081c9fac3..3317ba2950e5 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -150,6 +150,7 @@ decl_test_parachains! { pallets = { PolkadotXcm: bridge_hub_rococo_runtime::PolkadotXcm, Balances: bridge_hub_rococo_runtime::Balances, + EthereumControl: bridge_hub_rococo_runtime::EthereumControl, } }, // AssetHubRococo diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index b1ec66f40bff..02fc43b81521 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -78,6 +78,7 @@ pallet-collator-selection = { path = "../../../../pallets/collator-selection", d parachain-info = { path = "../../../pallets/parachain-info", default-features = false } parachains-common = { path = "../../../common", default-features = false } assets-common = { path = "../common", default-features = false } +snowbridge-router-primitives = { path = "../../../../../../parachain/primitives/router", default-features = false } # Bridges pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } @@ -219,6 +220,7 @@ std = [ "polkadot-runtime-common/std", "rococo-runtime-constants/std", "scale-info/std", + "snowbridge-router-primitives/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 20b59368a5b5..d60d5fd21ca6 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -387,7 +387,12 @@ impl pallet_assets::Config for Runtime { type AssetIdParameter = MultiLocationForAssetId; type Currency = Balances; type CreateOrigin = ForeignCreators< - (FromSiblingParachain>,), + ( + FromSiblingParachain>, + snowbridge_router_primitives::inbound::FromEthereumGlobalConsensus< + xcm_config::bridging::EthereumGatewayLocation, + >, + ), ForeignCreatorsSovereignAccountOf, AccountId, >; @@ -486,97 +491,98 @@ impl InstanceFilter for ProxyType { ProxyType::Any => true, ProxyType::NonTransfer => !matches!( c, - RuntimeCall::Balances { .. } | - RuntimeCall::Assets { .. } | - RuntimeCall::NftFractionalization { .. } | - RuntimeCall::Nfts { .. } | - RuntimeCall::Uniques { .. } + RuntimeCall::Balances { .. } + | RuntimeCall::Assets { .. } + | RuntimeCall::NftFractionalization { .. } + | RuntimeCall::Nfts { .. } + | RuntimeCall::Uniques { .. } ), ProxyType::CancelProxy => matches!( c, - RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) | - RuntimeCall::Utility { .. } | - RuntimeCall::Multisig { .. } + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) + | RuntimeCall::Utility { .. } + | RuntimeCall::Multisig { .. } ), ProxyType::Assets => { matches!( c, - RuntimeCall::Assets { .. } | - RuntimeCall::Utility { .. } | - RuntimeCall::Multisig { .. } | - RuntimeCall::NftFractionalization { .. } | - RuntimeCall::Nfts { .. } | RuntimeCall::Uniques { .. } + RuntimeCall::Assets { .. } + | RuntimeCall::Utility { .. } + | RuntimeCall::Multisig { .. } + | RuntimeCall::NftFractionalization { .. } + | RuntimeCall::Nfts { .. } + | RuntimeCall::Uniques { .. } ) }, ProxyType::AssetOwner => matches!( c, - RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::create { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::destroy { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::transfer_ownership { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::set_team { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::set_metadata { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::set_attribute { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::set_collection_metadata { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::clear_metadata { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::clear_attribute { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::clear_collection_metadata { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::set_collection_max_supply { .. }) | - RuntimeCall::Utility { .. } | - RuntimeCall::Multisig { .. } + RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::create { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::destroy { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::transfer_ownership { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::set_team { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::set_metadata { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::set_attribute { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::set_collection_metadata { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::clear_metadata { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::clear_attribute { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::clear_collection_metadata { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::set_collection_max_supply { .. }) + | RuntimeCall::Utility { .. } + | RuntimeCall::Multisig { .. } ), ProxyType::AssetManager => matches!( c, - RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | - RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) | - RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::mint { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::burn { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::freeze { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::thaw { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::freeze_collection { .. }) | - RuntimeCall::Uniques(pallet_uniques::Call::thaw_collection { .. }) | - RuntimeCall::Utility { .. } | - RuntimeCall::Multisig { .. } + RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) + | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) + | RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::mint { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::burn { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::freeze { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::thaw { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::freeze_collection { .. }) + | RuntimeCall::Uniques(pallet_uniques::Call::thaw_collection { .. }) + | RuntimeCall::Utility { .. } + | RuntimeCall::Multisig { .. } ), ProxyType::Collator => matches!( c, - RuntimeCall::CollatorSelection { .. } | - RuntimeCall::Utility { .. } | - RuntimeCall::Multisig { .. } + RuntimeCall::CollatorSelection { .. } + | RuntimeCall::Utility { .. } + | RuntimeCall::Multisig { .. } ), } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index ae4a275d43ac..e8110971984d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -41,6 +41,7 @@ use parachains_common::{ use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; use rococo_runtime_constants::system_parachain::SystemParachains; +use snowbridge_router_primitives::inbound::GlobalConsensusEthereumAccountConvertsFor; use sp_runtime::traits::{AccountIdConversion, ConvertInto}; use xcm::latest::prelude::*; use xcm_builder::{ @@ -57,6 +58,7 @@ use xcm_builder::{ }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; +use crate::xcm_config::bridging::to_rococo::EthereumNetwork; #[cfg(feature = "runtime-benchmarks")] use cumulus_primitives_core::ParaId; @@ -109,6 +111,9 @@ pub type LocationToAccountId = ( // Different global consensus parachain sovereign account. // (Used for over-bridge transfers and reserve processing) GlobalConsensusParachainConvertsFor, + // Ethereum contract sovereign account. + // (Used to get convert ethereum contract locations to sovereign account) + GlobalConsensusEthereumAccountConvertsFor, ); /// Means for transacting the native currency on this chain. @@ -278,203 +283,205 @@ impl Contains for SafeCallFilter { #[cfg(feature = "runtime-benchmarks")] { if matches!(call, RuntimeCall::System(frame_system::Call::remark_with_event { .. })) { - return true + return true; } } // Allow to change dedicated storage items (called by governance-like) match call { RuntimeCall::System(frame_system::Call::set_storage { items }) - if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) || - items.iter().all(|(k, _)| k.eq(&Flavor::key())) => - return true, + if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) + || items.iter().all(|(k, _)| k.eq(&Flavor::key())) => + { + return true + }, _ => (), }; matches!( call, - RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | - RuntimeCall::System( - frame_system::Call::set_heap_pages { .. } | - frame_system::Call::set_code { .. } | - frame_system::Call::set_code_without_checks { .. } | - frame_system::Call::kill_prefix { .. }, - ) | RuntimeCall::ParachainSystem(..) | - RuntimeCall::Timestamp(..) | - RuntimeCall::Balances(..) | - RuntimeCall::CollatorSelection( - pallet_collator_selection::Call::set_desired_candidates { .. } | - pallet_collator_selection::Call::set_candidacy_bond { .. } | - pallet_collator_selection::Call::register_as_candidate { .. } | - pallet_collator_selection::Call::leave_intent { .. } | - pallet_collator_selection::Call::set_invulnerables { .. } | - pallet_collator_selection::Call::add_invulnerable { .. } | - pallet_collator_selection::Call::remove_invulnerable { .. }, - ) | RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) | - RuntimeCall::XcmpQueue(..) | - RuntimeCall::DmpQueue(..) | - RuntimeCall::Assets( - pallet_assets::Call::create { .. } | - pallet_assets::Call::force_create { .. } | - pallet_assets::Call::start_destroy { .. } | - pallet_assets::Call::destroy_accounts { .. } | - pallet_assets::Call::destroy_approvals { .. } | - pallet_assets::Call::finish_destroy { .. } | - pallet_assets::Call::block { .. } | - pallet_assets::Call::mint { .. } | - pallet_assets::Call::burn { .. } | - pallet_assets::Call::transfer { .. } | - pallet_assets::Call::transfer_keep_alive { .. } | - pallet_assets::Call::force_transfer { .. } | - pallet_assets::Call::freeze { .. } | - pallet_assets::Call::thaw { .. } | - pallet_assets::Call::freeze_asset { .. } | - pallet_assets::Call::thaw_asset { .. } | - pallet_assets::Call::transfer_ownership { .. } | - pallet_assets::Call::set_team { .. } | - pallet_assets::Call::set_metadata { .. } | - pallet_assets::Call::clear_metadata { .. } | - pallet_assets::Call::force_set_metadata { .. } | - pallet_assets::Call::force_clear_metadata { .. } | - pallet_assets::Call::force_asset_status { .. } | - pallet_assets::Call::approve_transfer { .. } | - pallet_assets::Call::cancel_approval { .. } | - pallet_assets::Call::force_cancel_approval { .. } | - pallet_assets::Call::transfer_approved { .. } | - pallet_assets::Call::touch { .. } | - pallet_assets::Call::touch_other { .. } | - pallet_assets::Call::refund { .. } | - pallet_assets::Call::refund_other { .. }, + RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) + | RuntimeCall::System( + frame_system::Call::set_heap_pages { .. } + | frame_system::Call::set_code { .. } + | frame_system::Call::set_code_without_checks { .. } + | frame_system::Call::kill_prefix { .. }, + ) | RuntimeCall::ParachainSystem(..) + | RuntimeCall::Timestamp(..) + | RuntimeCall::Balances(..) + | RuntimeCall::CollatorSelection( + pallet_collator_selection::Call::set_desired_candidates { .. } + | pallet_collator_selection::Call::set_candidacy_bond { .. } + | pallet_collator_selection::Call::register_as_candidate { .. } + | pallet_collator_selection::Call::leave_intent { .. } + | pallet_collator_selection::Call::set_invulnerables { .. } + | pallet_collator_selection::Call::add_invulnerable { .. } + | pallet_collator_selection::Call::remove_invulnerable { .. }, + ) | RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) + | RuntimeCall::XcmpQueue(..) + | RuntimeCall::DmpQueue(..) + | RuntimeCall::Assets( + pallet_assets::Call::create { .. } + | pallet_assets::Call::force_create { .. } + | pallet_assets::Call::start_destroy { .. } + | pallet_assets::Call::destroy_accounts { .. } + | pallet_assets::Call::destroy_approvals { .. } + | pallet_assets::Call::finish_destroy { .. } + | pallet_assets::Call::block { .. } + | pallet_assets::Call::mint { .. } + | pallet_assets::Call::burn { .. } + | pallet_assets::Call::transfer { .. } + | pallet_assets::Call::transfer_keep_alive { .. } + | pallet_assets::Call::force_transfer { .. } + | pallet_assets::Call::freeze { .. } + | pallet_assets::Call::thaw { .. } + | pallet_assets::Call::freeze_asset { .. } + | pallet_assets::Call::thaw_asset { .. } + | pallet_assets::Call::transfer_ownership { .. } + | pallet_assets::Call::set_team { .. } + | pallet_assets::Call::set_metadata { .. } + | pallet_assets::Call::clear_metadata { .. } + | pallet_assets::Call::force_set_metadata { .. } + | pallet_assets::Call::force_clear_metadata { .. } + | pallet_assets::Call::force_asset_status { .. } + | pallet_assets::Call::approve_transfer { .. } + | pallet_assets::Call::cancel_approval { .. } + | pallet_assets::Call::force_cancel_approval { .. } + | pallet_assets::Call::transfer_approved { .. } + | pallet_assets::Call::touch { .. } + | pallet_assets::Call::touch_other { .. } + | pallet_assets::Call::refund { .. } + | pallet_assets::Call::refund_other { .. }, ) | RuntimeCall::ForeignAssets( - pallet_assets::Call::create { .. } | - pallet_assets::Call::force_create { .. } | - pallet_assets::Call::start_destroy { .. } | - pallet_assets::Call::destroy_accounts { .. } | - pallet_assets::Call::destroy_approvals { .. } | - pallet_assets::Call::finish_destroy { .. } | - pallet_assets::Call::block { .. } | - pallet_assets::Call::mint { .. } | - pallet_assets::Call::burn { .. } | - pallet_assets::Call::transfer { .. } | - pallet_assets::Call::transfer_keep_alive { .. } | - pallet_assets::Call::force_transfer { .. } | - pallet_assets::Call::freeze { .. } | - pallet_assets::Call::thaw { .. } | - pallet_assets::Call::freeze_asset { .. } | - pallet_assets::Call::thaw_asset { .. } | - pallet_assets::Call::transfer_ownership { .. } | - pallet_assets::Call::set_team { .. } | - pallet_assets::Call::set_metadata { .. } | - pallet_assets::Call::clear_metadata { .. } | - pallet_assets::Call::force_set_metadata { .. } | - pallet_assets::Call::force_clear_metadata { .. } | - pallet_assets::Call::force_asset_status { .. } | - pallet_assets::Call::approve_transfer { .. } | - pallet_assets::Call::cancel_approval { .. } | - pallet_assets::Call::force_cancel_approval { .. } | - pallet_assets::Call::transfer_approved { .. } | - pallet_assets::Call::touch { .. } | - pallet_assets::Call::touch_other { .. } | - pallet_assets::Call::refund { .. } | - pallet_assets::Call::refund_other { .. }, + pallet_assets::Call::create { .. } + | pallet_assets::Call::force_create { .. } + | pallet_assets::Call::start_destroy { .. } + | pallet_assets::Call::destroy_accounts { .. } + | pallet_assets::Call::destroy_approvals { .. } + | pallet_assets::Call::finish_destroy { .. } + | pallet_assets::Call::block { .. } + | pallet_assets::Call::mint { .. } + | pallet_assets::Call::burn { .. } + | pallet_assets::Call::transfer { .. } + | pallet_assets::Call::transfer_keep_alive { .. } + | pallet_assets::Call::force_transfer { .. } + | pallet_assets::Call::freeze { .. } + | pallet_assets::Call::thaw { .. } + | pallet_assets::Call::freeze_asset { .. } + | pallet_assets::Call::thaw_asset { .. } + | pallet_assets::Call::transfer_ownership { .. } + | pallet_assets::Call::set_team { .. } + | pallet_assets::Call::set_metadata { .. } + | pallet_assets::Call::clear_metadata { .. } + | pallet_assets::Call::force_set_metadata { .. } + | pallet_assets::Call::force_clear_metadata { .. } + | pallet_assets::Call::force_asset_status { .. } + | pallet_assets::Call::approve_transfer { .. } + | pallet_assets::Call::cancel_approval { .. } + | pallet_assets::Call::force_cancel_approval { .. } + | pallet_assets::Call::transfer_approved { .. } + | pallet_assets::Call::touch { .. } + | pallet_assets::Call::touch_other { .. } + | pallet_assets::Call::refund { .. } + | pallet_assets::Call::refund_other { .. }, ) | RuntimeCall::PoolAssets( - pallet_assets::Call::force_create { .. } | - pallet_assets::Call::block { .. } | - pallet_assets::Call::burn { .. } | - pallet_assets::Call::transfer { .. } | - pallet_assets::Call::transfer_keep_alive { .. } | - pallet_assets::Call::force_transfer { .. } | - pallet_assets::Call::freeze { .. } | - pallet_assets::Call::thaw { .. } | - pallet_assets::Call::freeze_asset { .. } | - pallet_assets::Call::thaw_asset { .. } | - pallet_assets::Call::transfer_ownership { .. } | - pallet_assets::Call::set_team { .. } | - pallet_assets::Call::set_metadata { .. } | - pallet_assets::Call::clear_metadata { .. } | - pallet_assets::Call::force_set_metadata { .. } | - pallet_assets::Call::force_clear_metadata { .. } | - pallet_assets::Call::force_asset_status { .. } | - pallet_assets::Call::approve_transfer { .. } | - pallet_assets::Call::cancel_approval { .. } | - pallet_assets::Call::force_cancel_approval { .. } | - pallet_assets::Call::transfer_approved { .. } | - pallet_assets::Call::touch { .. } | - pallet_assets::Call::touch_other { .. } | - pallet_assets::Call::refund { .. } | - pallet_assets::Call::refund_other { .. }, + pallet_assets::Call::force_create { .. } + | pallet_assets::Call::block { .. } + | pallet_assets::Call::burn { .. } + | pallet_assets::Call::transfer { .. } + | pallet_assets::Call::transfer_keep_alive { .. } + | pallet_assets::Call::force_transfer { .. } + | pallet_assets::Call::freeze { .. } + | pallet_assets::Call::thaw { .. } + | pallet_assets::Call::freeze_asset { .. } + | pallet_assets::Call::thaw_asset { .. } + | pallet_assets::Call::transfer_ownership { .. } + | pallet_assets::Call::set_team { .. } + | pallet_assets::Call::set_metadata { .. } + | pallet_assets::Call::clear_metadata { .. } + | pallet_assets::Call::force_set_metadata { .. } + | pallet_assets::Call::force_clear_metadata { .. } + | pallet_assets::Call::force_asset_status { .. } + | pallet_assets::Call::approve_transfer { .. } + | pallet_assets::Call::cancel_approval { .. } + | pallet_assets::Call::force_cancel_approval { .. } + | pallet_assets::Call::transfer_approved { .. } + | pallet_assets::Call::touch { .. } + | pallet_assets::Call::touch_other { .. } + | pallet_assets::Call::refund { .. } + | pallet_assets::Call::refund_other { .. }, ) | RuntimeCall::AssetConversion( - pallet_asset_conversion::Call::create_pool { .. } | - pallet_asset_conversion::Call::add_liquidity { .. } | - pallet_asset_conversion::Call::remove_liquidity { .. } | - pallet_asset_conversion::Call::swap_tokens_for_exact_tokens { .. } | - pallet_asset_conversion::Call::swap_exact_tokens_for_tokens { .. }, + pallet_asset_conversion::Call::create_pool { .. } + | pallet_asset_conversion::Call::add_liquidity { .. } + | pallet_asset_conversion::Call::remove_liquidity { .. } + | pallet_asset_conversion::Call::swap_tokens_for_exact_tokens { .. } + | pallet_asset_conversion::Call::swap_exact_tokens_for_tokens { .. }, ) | RuntimeCall::NftFractionalization( - pallet_nft_fractionalization::Call::fractionalize { .. } | - pallet_nft_fractionalization::Call::unify { .. }, + pallet_nft_fractionalization::Call::fractionalize { .. } + | pallet_nft_fractionalization::Call::unify { .. }, ) | RuntimeCall::Nfts( - pallet_nfts::Call::create { .. } | - pallet_nfts::Call::force_create { .. } | - pallet_nfts::Call::destroy { .. } | - pallet_nfts::Call::mint { .. } | - pallet_nfts::Call::force_mint { .. } | - pallet_nfts::Call::burn { .. } | - pallet_nfts::Call::transfer { .. } | - pallet_nfts::Call::lock_item_transfer { .. } | - pallet_nfts::Call::unlock_item_transfer { .. } | - pallet_nfts::Call::lock_collection { .. } | - pallet_nfts::Call::transfer_ownership { .. } | - pallet_nfts::Call::set_team { .. } | - pallet_nfts::Call::force_collection_owner { .. } | - pallet_nfts::Call::force_collection_config { .. } | - pallet_nfts::Call::approve_transfer { .. } | - pallet_nfts::Call::cancel_approval { .. } | - pallet_nfts::Call::clear_all_transfer_approvals { .. } | - pallet_nfts::Call::lock_item_properties { .. } | - pallet_nfts::Call::set_attribute { .. } | - pallet_nfts::Call::force_set_attribute { .. } | - pallet_nfts::Call::clear_attribute { .. } | - pallet_nfts::Call::approve_item_attributes { .. } | - pallet_nfts::Call::cancel_item_attributes_approval { .. } | - pallet_nfts::Call::set_metadata { .. } | - pallet_nfts::Call::clear_metadata { .. } | - pallet_nfts::Call::set_collection_metadata { .. } | - pallet_nfts::Call::clear_collection_metadata { .. } | - pallet_nfts::Call::set_accept_ownership { .. } | - pallet_nfts::Call::set_collection_max_supply { .. } | - pallet_nfts::Call::update_mint_settings { .. } | - pallet_nfts::Call::set_price { .. } | - pallet_nfts::Call::buy_item { .. } | - pallet_nfts::Call::pay_tips { .. } | - pallet_nfts::Call::create_swap { .. } | - pallet_nfts::Call::cancel_swap { .. } | - pallet_nfts::Call::claim_swap { .. }, + pallet_nfts::Call::create { .. } + | pallet_nfts::Call::force_create { .. } + | pallet_nfts::Call::destroy { .. } + | pallet_nfts::Call::mint { .. } + | pallet_nfts::Call::force_mint { .. } + | pallet_nfts::Call::burn { .. } + | pallet_nfts::Call::transfer { .. } + | pallet_nfts::Call::lock_item_transfer { .. } + | pallet_nfts::Call::unlock_item_transfer { .. } + | pallet_nfts::Call::lock_collection { .. } + | pallet_nfts::Call::transfer_ownership { .. } + | pallet_nfts::Call::set_team { .. } + | pallet_nfts::Call::force_collection_owner { .. } + | pallet_nfts::Call::force_collection_config { .. } + | pallet_nfts::Call::approve_transfer { .. } + | pallet_nfts::Call::cancel_approval { .. } + | pallet_nfts::Call::clear_all_transfer_approvals { .. } + | pallet_nfts::Call::lock_item_properties { .. } + | pallet_nfts::Call::set_attribute { .. } + | pallet_nfts::Call::force_set_attribute { .. } + | pallet_nfts::Call::clear_attribute { .. } + | pallet_nfts::Call::approve_item_attributes { .. } + | pallet_nfts::Call::cancel_item_attributes_approval { .. } + | pallet_nfts::Call::set_metadata { .. } + | pallet_nfts::Call::clear_metadata { .. } + | pallet_nfts::Call::set_collection_metadata { .. } + | pallet_nfts::Call::clear_collection_metadata { .. } + | pallet_nfts::Call::set_accept_ownership { .. } + | pallet_nfts::Call::set_collection_max_supply { .. } + | pallet_nfts::Call::update_mint_settings { .. } + | pallet_nfts::Call::set_price { .. } + | pallet_nfts::Call::buy_item { .. } + | pallet_nfts::Call::pay_tips { .. } + | pallet_nfts::Call::create_swap { .. } + | pallet_nfts::Call::cancel_swap { .. } + | pallet_nfts::Call::claim_swap { .. }, ) | RuntimeCall::Uniques( - pallet_uniques::Call::create { .. } | - pallet_uniques::Call::force_create { .. } | - pallet_uniques::Call::destroy { .. } | - pallet_uniques::Call::mint { .. } | - pallet_uniques::Call::burn { .. } | - pallet_uniques::Call::transfer { .. } | - pallet_uniques::Call::freeze { .. } | - pallet_uniques::Call::thaw { .. } | - pallet_uniques::Call::freeze_collection { .. } | - pallet_uniques::Call::thaw_collection { .. } | - pallet_uniques::Call::transfer_ownership { .. } | - pallet_uniques::Call::set_team { .. } | - pallet_uniques::Call::approve_transfer { .. } | - pallet_uniques::Call::cancel_approval { .. } | - pallet_uniques::Call::force_item_status { .. } | - pallet_uniques::Call::set_attribute { .. } | - pallet_uniques::Call::clear_attribute { .. } | - pallet_uniques::Call::set_metadata { .. } | - pallet_uniques::Call::clear_metadata { .. } | - pallet_uniques::Call::set_collection_metadata { .. } | - pallet_uniques::Call::clear_collection_metadata { .. } | - pallet_uniques::Call::set_accept_ownership { .. } | - pallet_uniques::Call::set_collection_max_supply { .. } | - pallet_uniques::Call::set_price { .. } | - pallet_uniques::Call::buy_item { .. } + pallet_uniques::Call::create { .. } + | pallet_uniques::Call::force_create { .. } + | pallet_uniques::Call::destroy { .. } + | pallet_uniques::Call::mint { .. } + | pallet_uniques::Call::burn { .. } + | pallet_uniques::Call::transfer { .. } + | pallet_uniques::Call::freeze { .. } + | pallet_uniques::Call::thaw { .. } + | pallet_uniques::Call::freeze_collection { .. } + | pallet_uniques::Call::thaw_collection { .. } + | pallet_uniques::Call::transfer_ownership { .. } + | pallet_uniques::Call::set_team { .. } + | pallet_uniques::Call::approve_transfer { .. } + | pallet_uniques::Call::cancel_approval { .. } + | pallet_uniques::Call::force_item_status { .. } + | pallet_uniques::Call::set_attribute { .. } + | pallet_uniques::Call::clear_attribute { .. } + | pallet_uniques::Call::set_metadata { .. } + | pallet_uniques::Call::clear_metadata { .. } + | pallet_uniques::Call::set_collection_metadata { .. } + | pallet_uniques::Call::clear_collection_metadata { .. } + | pallet_uniques::Call::set_accept_ownership { .. } + | pallet_uniques::Call::set_collection_max_supply { .. } + | pallet_uniques::Call::set_price { .. } + | pallet_uniques::Call::buy_item { .. } ) | RuntimeCall::ToWococoXcmRouter( pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } ) | RuntimeCall::ToRococoXcmRouter( @@ -616,8 +623,11 @@ impl xcm_executor::Config for XcmConfig { type AssetExchanger = (); type FeeManager = XcmFeesToAccount; type MessageExporter = (); - type UniversalAliases = - (bridging::to_wococo::UniversalAliases, bridging::to_rococo::UniversalAliases); + type UniversalAliases = ( + bridging::to_wococo::UniversalAliases, + bridging::to_rococo::UniversalAliases, + GlobalConsensus(EthereumNetwork::get()), + ); type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; @@ -707,6 +717,7 @@ pub type ForeignCreatorsSovereignAccountOf = ( SiblingParachainConvertsVia, AccountId32Aliases, ParentIsPreset, + GlobalConsensusEthereumAccountConvertsFor, ); /// Simple conversion of `u32` into an `AssetId` for use in benchmarking. @@ -877,6 +888,18 @@ pub mod bridging { pub const RococoNetwork: NetworkId = NetworkId::Rococo; pub AssetHubRococo: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(RococoNetwork::get()), Parachain(bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID))); pub RocLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(RococoNetwork::get()))); + pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; + pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); // TODO: Maybe registry address belongs here + + pub const EthereumGatewayAddress: [u8; 20] = hex_literal::hex!("EDa338E4dC46038493b885327842fD3E301CaB39"); + // The Registry contract for the bridge which is also the origin for reserves and the prefix of all assets. + pub EthereumGatewayLocation: MultiLocation = EthereumLocation::get() + .pushed_with_interior( + AccountKey20 { + network: None, + key: EthereumGatewayAddress::get(), + } + ).unwrap(); pub RocFromAssetHubRococo: (MultiAssetFilter, MultiLocation) = ( Wild(AllOf { fun: WildFungible, id: Concrete(RocLocation::get()) }), @@ -897,7 +920,14 @@ pub mod bridging { XcmBridgeHubRouterFeeAssetId::get(), bp_asset_hub_wococo::BridgeHubWococoBaseFeeInWocs::get(), ).into()) - ) + ), + NetworkExportTableItem::new( + EthereumNetwork::get(), + Some(sp_std::vec![LocationFilter::default() + .add_equals(EthereumLocation::get().interior.split_global().expect("invalid configuration for Ethereum").1)]), + BridgeHubRococo::get(), + None // TODO check + ), ]; /// Allowed assets for reserve transfer to `AssetHubWococo`. @@ -907,6 +937,12 @@ pub mod bridging { // and nothing else ]; + pub AllowedReserveTransferAssetsToEthereum: sp_std::vec::Vec = sp_std::vec![ + // allow send only WOC + Wild(AllOf { fun: WildFungible, id: Concrete(EthereumGatewayLocation::get()) }), // TODO check + // and nothing else + ]; + /// Universal aliases pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( sp_std::vec![ @@ -939,6 +975,16 @@ pub mod bridging { AllowedReserveTransferAssetsToAssetHubRococo, >; + pub type AllowedReserveTransferAssetsToEthereum = LocationWithAssetFilters< + StartsWithExplicitGlobalConsensus, // TODO check + AllowedReserveTransferAssetsToEthereum, + >; + + pub type AllowedReserveTransferAssetsToEthereumGateway = LocationWithAssetFilters< + StartsWithExplicitGlobalConsensus, // TODO check + AllowedReserveTransferAssetsToEthereum, + >; + impl Contains for ToRococoXcmRouter { fn contains(call: &RuntimeCall) -> bool { matches!( From 4d012bf5083454163978e38ce2d4334d5c22aabf Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Fri, 20 Oct 2023 09:00:48 +0200 Subject: [PATCH 045/124] asset hub rococo --- .../assets/asset-hub-rococo/src/lib.rs | 6 ++-- .../assets/asset-hub-rococo/src/xcm_config.rs | 28 ++++++++----------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index d60d5fd21ca6..308b5b219da1 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -97,8 +97,8 @@ use xcm::latest::prelude::*; use xcm_executor::XcmExecutor; use crate::xcm_config::{ - ForeignCreatorsSovereignAccountOf, LocalAndForeignAssetsMultiLocationMatcher, - TrustBackedAssetsPalletLocation, + bridging::to_rococo::EthereumGatewayLocation, ForeignCreatorsSovereignAccountOf, + LocalAndForeignAssetsMultiLocationMatcher, TrustBackedAssetsPalletLocation, }; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; @@ -390,7 +390,7 @@ impl pallet_assets::Config for Runtime { ( FromSiblingParachain>, snowbridge_router_primitives::inbound::FromEthereumGlobalConsensus< - xcm_config::bridging::EthereumGatewayLocation, + EthereumGatewayLocation, >, ), ForeignCreatorsSovereignAccountOf, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index e8110971984d..6335b396e0eb 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -58,7 +58,6 @@ use xcm_builder::{ }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; -use crate::xcm_config::bridging::to_rococo::EthereumNetwork; #[cfg(feature = "runtime-benchmarks")] use cumulus_primitives_core::ParaId; @@ -623,11 +622,8 @@ impl xcm_executor::Config for XcmConfig { type AssetExchanger = (); type FeeManager = XcmFeesToAccount; type MessageExporter = (); - type UniversalAliases = ( - bridging::to_wococo::UniversalAliases, - bridging::to_rococo::UniversalAliases, - GlobalConsensus(EthereumNetwork::get()), - ); + type UniversalAliases = + (bridging::to_wococo::UniversalAliases, bridging::to_rococo::UniversalAliases); type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; @@ -682,6 +678,7 @@ impl pallet_xcm::Config for Runtime { type XcmReserveTransferFilter = ( LocationWithAssetFilters, bridging::to_rococo::AllowedReserveTransferAssets, + bridging::to_rococo::AllowedReserveTransferAssetsEthereum, bridging::to_wococo::AllowedReserveTransferAssets, ); @@ -923,9 +920,10 @@ pub mod bridging { ), NetworkExportTableItem::new( EthereumNetwork::get(), - Some(sp_std::vec![LocationFilter::default() - .add_equals(EthereumLocation::get().interior.split_global().expect("invalid configuration for Ethereum").1)]), - BridgeHubRococo::get(), + Some(sp_std::vec![ + EthereumLocation::get().interior.split_global().expect("invalid configuration for AssetHubRococo").1, + ]), + SiblingBridgeHub::get(), // TODO check None // TODO check ), ]; @@ -946,7 +944,8 @@ pub mod bridging { /// Universal aliases pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( sp_std::vec![ - (SiblingBridgeHubWithBridgeHubRococoInstance::get(), GlobalConsensus(RococoNetwork::get())) + (SiblingBridgeHubWithBridgeHubRococoInstance::get(), GlobalConsensus(RococoNetwork::get())), + (SiblingBridgeHub::get(), GlobalConsensus(EthereumNetwork::get())), // TODO check ] ); } @@ -975,13 +974,8 @@ pub mod bridging { AllowedReserveTransferAssetsToAssetHubRococo, >; - pub type AllowedReserveTransferAssetsToEthereum = LocationWithAssetFilters< - StartsWithExplicitGlobalConsensus, // TODO check - AllowedReserveTransferAssetsToEthereum, - >; - - pub type AllowedReserveTransferAssetsToEthereumGateway = LocationWithAssetFilters< - StartsWithExplicitGlobalConsensus, // TODO check + pub type AllowedReserveTransferAssetsEthereum = LocationWithAssetFilters< + StartsWithExplicitGlobalConsensus, // TODO check AllowedReserveTransferAssetsToEthereum, >; From 2aec192f72817f5128181aab9ebd70431ae8e54f Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Fri, 20 Oct 2023 10:10:11 +0200 Subject: [PATCH 046/124] finishing up applying changes --- cumulus/polkadot-parachain/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index 3c2069c81ef4..9720e505b59f 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -145,3 +145,4 @@ try-runtime = [ "shell-runtime/try-runtime", "sp-runtime/try-runtime", ] +beacon-spec-mainnet = [] From 546274a158def3a38f9ad3f1b157bb07001174da Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Fri, 20 Oct 2023 11:29:14 +0200 Subject: [PATCH 047/124] fix incorrect pallet-xcm imports --- cumulus/parachain-template/pallets/template/Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cumulus/parachain-template/pallets/template/Cargo.toml b/cumulus/parachain-template/pallets/template/Cargo.toml index 71f7371a73ce..1f53ff50e81a 100644 --- a/cumulus/parachain-template/pallets/template/Cargo.toml +++ b/cumulus/parachain-template/pallets/template/Cargo.toml @@ -19,6 +19,10 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive frame-benchmarking = { path = "../../../../substrate/frame/benchmarking", default-features = false, optional = true} frame-support = { path = "../../../../substrate/frame/support", default-features = false} frame-system = { path = "../../../../substrate/frame/system", default-features = false} +sp-std = { path = "../../../../substrate/primitives/std", default-features = false} + +pallet-xcm = { path = "../../../../polkadot/xcm/pallet-xcm", default-features = false} +xcm = { package = "staging-xcm", path = "../../../../polkadot/xcm", default-features = false} [dev-dependencies] serde = { version = "1.0.188" } @@ -27,10 +31,6 @@ serde = { version = "1.0.188" } sp-core = { path = "../../../../substrate/primitives/core", default-features = false} sp-io = { path = "../../../../substrate/primitives/io", default-features = false} sp-runtime = { path = "../../../../substrate/primitives/runtime", default-features = false} -sp-std = { path = "../../../../substrate/primitives/std", default-features = false} - -pallet-xcm = { path = "../../../../polkadot/xcm/pallet-xcm", default-features = false} -xcm = { package = "staging-xcm", path = "../../../../polkadot/xcm", default-features = false} [features] default = [ "std" ] From 50d844f5d049d7de9a86a0ec9abdcf092c0119fc Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 24 Oct 2023 16:23:19 +0300 Subject: [PATCH 048/124] verify assets and beneficiary in over-bridge test --- .../runtimes/assets/test-utils/src/lib.rs | 16 +++- .../test-utils/src/test_cases_over_bridge.rs | 87 ++++++++----------- 2 files changed, 47 insertions(+), 56 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs index 82482599fd4d..019287cd1bf8 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs @@ -19,15 +19,17 @@ pub mod test_cases; pub mod test_cases_over_bridge; pub mod xcm_helpers; + use frame_support::traits::ProcessMessageError; pub use parachains_runtimes_test_utils::*; +use std::fmt::Debug; use xcm::latest::prelude::*; use xcm_builder::{CreateMatcher, MatchXcm}; /// Helper function to verify `xcm` contains all relevant instructions expected on destination /// chain as part of a reserve-asset-transfer. -pub(crate) fn assert_matches_reserve_asset_deposited_instructions( +pub(crate) fn assert_matches_reserve_asset_deposited_instructions( xcm: &mut Xcm, expected_reserve_assets_deposited: &MultiAssets, expected_beneficiary: &MultiLocation, @@ -38,9 +40,10 @@ pub(crate) fn assert_matches_reserve_asset_deposited_instructions( .skip_inst_while(|inst| !matches!(inst, ReserveAssetDeposited(..))) .expect("no instruction ReserveAssetDeposited?") .match_next_inst(|instr| match instr { - ReserveAssetDeposited(reserve_assets) - if reserve_assets == expected_reserve_assets_deposited => - Ok(()), + ReserveAssetDeposited(reserve_assets) => { + assert_eq!(reserve_assets, expected_reserve_assets_deposited); + Ok(()) + }, _ => Err(ProcessMessageError::BadFormat), }) .expect("expected instruction ReserveAssetDeposited") @@ -49,6 +52,11 @@ pub(crate) fn assert_matches_reserve_asset_deposited_instructions( _ => Err(ProcessMessageError::BadFormat), }) .expect("expected instruction ClearOrigin") + .match_next_inst(|instr| match instr { + SetFeesMode { .. } => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction SetFeesMode") .match_next_inst(|instr| match instr { BuyExecution { .. } => Ok(()), _ => Err(ProcessMessageError::BadFormat), diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index 2d4039357660..1eed91a64a4a 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -16,6 +16,7 @@ //! Module contains predefined test-case scenarios for `Runtime` with various assets transferred //! over a bridge. +use crate::assert_matches_reserve_asset_deposited_instructions; use codec::Encode; use cumulus_primitives_core::XcmpMessageSource; use frame_support::{ @@ -173,12 +174,24 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< >::mint_into(&alice_account, delivery_fees.into()) .unwrap(); + let assets_to_transfer = MultiAssets::from(asset_to_transfer); + let mut expected_assets = assets_to_transfer.clone(); + expected_assets + .reanchor(&target_location_from_different_consensus, Here.into()) + .unwrap(); + // FIXME: remove this hardcode here when fixing reanchor over bridge + expected_assets = MultiAssets::from(MultiAsset { + id: Concrete(MultiLocation { parents: 2, interior: X1(GlobalConsensus(Rococo)) }), + fun: Fungible(1000000000000), + }); + + let expected_beneficiary = target_destination_account; // do pallet_xcm call reserve transfer assert_ok!(>::limited_reserve_transfer_assets( RuntimeHelper::::origin_of(alice_account.clone()), Box::new(target_location_from_different_consensus.into_versioned()), Box::new(target_destination_account.into_versioned()), - Box::new(VersionedMultiAssets::from(MultiAssets::from(asset_to_transfer))), + Box::new(VersionedMultiAssets::from(assets_to_transfer)), 0, weight_limit, )); @@ -255,7 +268,11 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< .split_global() .expect("split works"); assert_eq!(destination, &target_location_junctions_without_global_consensus); - assert_matches_pallet_xcm_reserve_transfer_assets_instructions(inner_xcm); + assert_matches_reserve_asset_deposited_instructions( + inner_xcm, + &expected_assets, + &expected_beneficiary, + ); Ok(()) }, _ => Err(ProcessMessageError::BadFormat), @@ -405,15 +422,21 @@ pub fn receive_reserve_asset_deposited_from_different_consensus_works< 0.into() ); + let expected_assets = MultiAssets::from(vec![MultiAsset { + id: Concrete(foreign_asset_id_multilocation), + fun: Fungible(transfered_foreign_asset_id_amount), + }]); + let expected_beneficiary = MultiLocation { + parents: 0, + interior: X1(AccountId32 { network: None, id: target_account.clone().into() }), + }; + // Call received XCM execution let xcm = Xcm(vec![ DescendOrigin(bridge_instance), UniversalOrigin(universal_origin), DescendOrigin(descend_origin), - ReserveAssetDeposited(MultiAssets::from(vec![MultiAsset { - id: Concrete(foreign_asset_id_multilocation), - fun: Fungible(transfered_foreign_asset_id_amount), - }])), + ReserveAssetDeposited(expected_assets.clone()), ClearOrigin, SetFeesMode { jit_withdraw: false }, BuyExecution { @@ -423,22 +446,17 @@ pub fn receive_reserve_asset_deposited_from_different_consensus_works< }, weight_limit: Unlimited, }, - DepositAsset { - assets: Wild(AllCounted(1)), - beneficiary: MultiLocation { - parents: 0, - interior: X1(AccountId32 { - network: None, - id: target_account.clone().into(), - }), - }, - }, + DepositAsset { assets: Wild(AllCounted(1)), beneficiary: expected_beneficiary }, SetTopic([ 220, 188, 144, 32, 213, 83, 111, 175, 44, 210, 111, 19, 90, 165, 191, 112, 140, 247, 192, 124, 42, 17, 153, 141, 114, 34, 189, 20, 83, 69, 237, 173, ]), ]); - assert_matches_pallet_xcm_reserve_transfer_assets_instructions(&mut xcm.clone()); + assert_matches_reserve_asset_deposited_instructions( + &mut xcm.clone(), + &expected_assets, + &expected_beneficiary, + ); let hash = xcm.using_encoded(sp_io::hashing::blake2_256); @@ -499,41 +517,6 @@ pub fn receive_reserve_asset_deposited_from_different_consensus_works< }) } -fn assert_matches_pallet_xcm_reserve_transfer_assets_instructions( - xcm: &mut Xcm, -) { - let _ = xcm - .0 - .matcher() - .skip_inst_while(|inst| !matches!(inst, ReserveAssetDeposited(..))) - .expect("no instruction ReserveAssetDeposited?") - .match_next_inst(|instr| match instr { - ReserveAssetDeposited(..) => Ok(()), - _ => Err(ProcessMessageError::BadFormat), - }) - .expect("expected instruction ReserveAssetDeposited") - .match_next_inst(|instr| match instr { - ClearOrigin => Ok(()), - _ => Err(ProcessMessageError::BadFormat), - }) - .expect("expected instruction ClearOrigin") - .match_next_inst(|instr| match instr { - SetFeesMode { .. } => Ok(()), - _ => Err(ProcessMessageError::BadFormat), - }) - .expect("expected instruction SetFeesMode") - .match_next_inst(|instr| match instr { - BuyExecution { .. } => Ok(()), - _ => Err(ProcessMessageError::BadFormat), - }) - .expect("expected instruction BuyExecution") - .match_next_inst(|instr| match instr { - DepositAsset { .. } => Ok(()), - _ => Err(ProcessMessageError::BadFormat), - }) - .expect("expected instruction DepositAsset"); -} - pub fn report_bridge_status_from_xcm_bridge_router_works< Runtime, AllPalletsWithoutSystem, From 0bf64e687eb3c987be74c25af2cc391758f9d60b Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 24 Oct 2023 16:43:28 +0300 Subject: [PATCH 049/124] fix AHs tests --- .../runtimes/assets/test-utils/src/test_cases.rs | 13 +++++++++---- .../assets/test-utils/src/test_cases_over_bridge.rs | 10 +++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 2a32989aae9a..9d15eea49f2d 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -169,7 +169,7 @@ pub fn teleports_for_native_asset_works< id: sp_runtime::AccountId32::new([3; 32]).into(), }) .unwrap(); - dest_beneficiary.reanchor(&dest, Here.into()).unwrap(); + dest_beneficiary.reanchor(&dest, XcmConfig::UniversalLocation::get()).unwrap(); let target_account_balance_before_teleport = >::free_balance(&target_account); @@ -234,7 +234,7 @@ pub fn teleports_for_native_asset_works< id: sp_runtime::AccountId32::new([3; 32]).into(), }) .unwrap(); - dest_beneficiary.reanchor(&dest, Here.into()).unwrap(); + dest_beneficiary.reanchor(&dest, XcmConfig::UniversalLocation::get()).unwrap(); let target_account_balance_before_teleport = >::free_balance(&target_account); @@ -543,7 +543,7 @@ pub fn teleports_for_foreign_assets_works< id: sp_runtime::AccountId32::new([3; 32]).into(), }) .unwrap(); - dest_beneficiary.reanchor(&dest, Here.into()).unwrap(); + dest_beneficiary.reanchor(&dest, XcmConfig::UniversalLocation::get()).unwrap(); let target_account_balance_before_teleport = >::balance( @@ -1448,7 +1448,7 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< id: sp_runtime::AccountId32::new([3; 32]).into(), }) .unwrap(); - dest_beneficiary.reanchor(&dest, Here.into()).unwrap(); + dest_beneficiary.reanchor(&dest, XcmConfig::UniversalLocation::get()).unwrap(); let reserve_account = LocationToAccountId::convert_location(&dest) .expect("Sovereign account for reserves"); @@ -1494,6 +1494,11 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< id: Concrete(native_asset), }; + // TODO: Get this fee via weighing the corresponding message + let delivery_fees = 31010000000; + >::mint_into(&alice_account, delivery_fees.into()) + .unwrap(); + // pallet_xcm call reserve transfer assert_ok!(>::limited_reserve_transfer_assets( RuntimeHelper::::origin_of(alice_account.clone()), diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index 1eed91a64a4a..547d4dfcec7c 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -22,7 +22,7 @@ use cumulus_primitives_core::XcmpMessageSource; use frame_support::{ assert_ok, traits::{ - fungible::Mutate, Currency, OnFinalize, OnInitialize, OriginTrait, ProcessMessageError, + fungible::Mutate, Currency, Get, OnFinalize, OnInitialize, OriginTrait, ProcessMessageError, }, }; use frame_system::pallet_prelude::BlockNumberFor; @@ -176,14 +176,10 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< let assets_to_transfer = MultiAssets::from(asset_to_transfer); let mut expected_assets = assets_to_transfer.clone(); + let context = XcmConfig::UniversalLocation::get(); expected_assets - .reanchor(&target_location_from_different_consensus, Here.into()) + .reanchor(&target_location_from_different_consensus, context) .unwrap(); - // FIXME: remove this hardcode here when fixing reanchor over bridge - expected_assets = MultiAssets::from(MultiAsset { - id: Concrete(MultiLocation { parents: 2, interior: X1(GlobalConsensus(Rococo)) }), - fun: Fungible(1000000000000), - }); let expected_beneficiary = target_destination_account; // do pallet_xcm call reserve transfer From c71196166e422a6d12e0d00ffd40ba859482b29e Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 24 Oct 2023 16:58:24 +0300 Subject: [PATCH 050/124] AHs: fix emulated tests --- .../src/tests/reserve_transfer.rs | 2 +- .../asset-hub-rococo/src/tests/teleport.rs | 12 ++--- .../src/tests/reserve_transfer.rs | 10 ++-- .../asset-hub-westend/src/tests/teleport.rs | 12 ++--- .../emulated/common/src/macros.rs | 2 +- .../assets/test-utils/src/test_cases.rs | 4 +- .../assets/test-utils/src/xcm_helpers.rs | 50 ++++++++++++++++--- 7 files changed, 62 insertions(+), 30 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index 073c93ec254a..0a55a609ecce 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -176,7 +176,7 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { let sender_balance_after = test.sender.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::reserve_transfer_localreserve_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs index 4b2ea0e160cb..e74e97dc3391 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs @@ -174,7 +174,7 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Rococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -221,7 +221,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -262,7 +262,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -295,7 +295,7 @@ fn teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Rococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -342,7 +342,7 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -380,7 +380,7 @@ fn teleport_native_assets_from_system_para_to_relay_fails() { test.assert(); let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs index c7a25dde78d3..bc18daf35eb7 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -175,13 +175,9 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { let sender_balance_after = test.sender.balance; let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::<::XcmSender>( - test.args.assets.clone(), - 0, - test.args.weight_limit, - test.args.beneficiary, - test.args.dest, - ) + xcm_helpers::reserve_transfer_localreserve_assets_delivery_fees::< + ::XcmSender, + >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs index 4fe0062dafcd..7423f6f60eb1 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs @@ -176,7 +176,7 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Westend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -223,7 +223,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -264,7 +264,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -297,7 +297,7 @@ fn teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Westend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -341,7 +341,7 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() { test.assert(); let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -382,7 +382,7 @@ fn teleport_native_assets_from_system_para_to_relay_fails() { test.assert(); let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::transfer_assets_delivery_fees::< + xcm_helpers::teleport_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs index a65b2057afda..52780a5c4a75 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs @@ -90,7 +90,7 @@ macro_rules! test_parachain_is_trusted_teleporter { let para_receiver_balance_after = <$receiver_para as $crate::Chain>::account_data_of(receiver.clone()).free; let delivery_fees = <$sender_para>::execute_with(|| { - asset_test_utils::xcm_helpers::transfer_assets_delivery_fees::< + asset_test_utils::xcm_helpers::teleport_assets_delivery_fees::< <$sender_xcm_config as xcm_executor::Config>::XcmSender, >($assets.clone(), fee_asset_item, weight_limit.clone(), beneficiary, para_destination) }); diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 9d15eea49f2d..31f235db0edb 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -181,7 +181,7 @@ pub fn teleports_for_native_asset_works< // Mint funds into account to ensure it has enough balance to pay delivery fees let delivery_fees = - xcm_helpers::transfer_assets_delivery_fees::( + xcm_helpers::teleport_assets_delivery_fees::( (native_asset_id, native_asset_to_teleport_away.into()).into(), 0, Unlimited, @@ -560,7 +560,7 @@ pub fn teleports_for_foreign_assets_works< // Make sure the target account has enough native asset to pay for delivery fees let delivery_fees = - xcm_helpers::transfer_assets_delivery_fees::( + xcm_helpers::teleport_assets_delivery_fees::( (foreign_asset_id_multilocation, asset_to_teleport_away).into(), 0, Unlimited, diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs b/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs index 0aebe38fef53..ca92c469df80 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs @@ -18,11 +18,10 @@ use xcm::latest::prelude::*; -/// Returns the delivery fees amount for pallet xcm's `teleport_assets` and -/// `reserve_transfer_assets` extrinsics. -/// Because it returns only a `u128`, it assumes delivery fees are only paid -/// in one asset and that asset is known. -pub fn transfer_assets_delivery_fees( +/// Returns the delivery fees amount for pallet xcm's `teleport_assets` extrinsic. +/// Because it returns only a `u128`, it assumes delivery fees are only paid in one asset and that +/// asset is known. +pub fn teleport_assets_delivery_fees( assets: MultiAssets, fee_asset_item: u32, weight_limit: WeightLimit, @@ -33,6 +32,25 @@ pub fn transfer_assets_delivery_fees( get_fungible_delivery_fees::(destination, message) } +/// Returns the delivery fees amount for pallet xcm's `reserve_transfer_assets` extrinsics. +/// Because it returns only a `u128`, it assumes delivery fees are only paid in one asset and that +/// asset is known. +pub fn reserve_transfer_localreserve_assets_delivery_fees( + assets: MultiAssets, + fee_asset_item: u32, + weight_limit: WeightLimit, + beneficiary: MultiLocation, + destination: MultiLocation, +) -> u128 { + let message = reserve_transfer_localreserve_assets_dummy_message( + assets, + fee_asset_item, + weight_limit, + beneficiary, + ); + get_fungible_delivery_fees::(destination, message) +} + /// Returns the delivery fees amount for a query response as a result of the execution /// of a `ExpectError` instruction with no error. pub fn query_response_delivery_fees(querier: MultiLocation) -> u128 { @@ -76,7 +94,6 @@ pub fn pay_over_xcm_delivery_fees( /// Approximates the actual message sent by the teleport extrinsic. /// The assets are not reanchored and the topic is a dummy one. /// However, it should have the same encoded size, which is what matters for delivery fees. -/// Also has same encoded size as the one created by the reserve transfer assets extrinsic. fn teleport_assets_dummy_message( assets: MultiAssets, fee_asset_item: u32, @@ -84,8 +101,27 @@ fn teleport_assets_dummy_message( beneficiary: MultiLocation, ) -> Xcm<()> { Xcm(vec![ - ReceiveTeleportedAsset(assets.clone()), // Same encoded size as `ReserveAssetDeposited` + ReceiveTeleportedAsset(assets.clone()), + ClearOrigin, + BuyExecution { fees: assets.get(fee_asset_item as usize).unwrap().clone(), weight_limit }, + DepositAsset { assets: Wild(AllCounted(assets.len() as u32)), beneficiary }, + SetTopic([0u8; 32]), // Dummy topic + ]) +} + +/// Approximates the actual message sent by the reserve-transfer of local reserve asset extrinsic. +/// The assets are not reanchored and the topic is a dummy one. +/// However, it should have the same encoded size, which is what matters for delivery fees. +fn reserve_transfer_localreserve_assets_dummy_message( + assets: MultiAssets, + fee_asset_item: u32, + weight_limit: WeightLimit, + beneficiary: MultiLocation, +) -> Xcm<()> { + Xcm(vec![ + ReserveAssetDeposited(assets.clone()), ClearOrigin, + SetFeesMode { jit_withdraw: false }, BuyExecution { fees: assets.get(fee_asset_item as usize).unwrap().clone(), weight_limit }, DepositAsset { assets: Wild(AllCounted(assets.len() as u32)), beneficiary }, SetTopic([0u8; 32]), // Dummy topic From 67929a54ea86b32bcba7b9ef44843a179c42156d Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 24 Oct 2023 18:32:28 +0300 Subject: [PATCH 051/124] AHs: include delivery-fee checking in tests --- .../assets/asset-hub-rococo/tests/tests.rs | 29 +++++++++++ .../runtimes/assets/test-utils/src/lib.rs | 15 ++++++ .../assets/test-utils/src/test_cases.rs | 51 ++++++++++--------- 3 files changed, 71 insertions(+), 24 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs index 2fffd63316bf..49fae83d5091 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs @@ -810,6 +810,35 @@ mod asset_hub_rococo_tests { actual ); } + + #[test] + fn reserve_transfer_native_asset_to_non_teleport_para_works() { + asset_test_utils::test_cases::reserve_transfer_native_asset_to_non_teleport_para_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + WeightLimit::Unlimited, + ); + } } mod asset_hub_wococo_tests { diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs index 019287cd1bf8..2a1e72dc002f 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs @@ -27,6 +27,21 @@ use std::fmt::Debug; use xcm::latest::prelude::*; use xcm_builder::{CreateMatcher, MatchXcm}; +/// Given a message, a sender, and a destination, it returns the delivery fees +fn get_fungible_delivery_fees(destination: MultiLocation, message: Xcm<()>) -> u128 { + let Ok((_, delivery_fees)) = validate_send::(destination, message) else { + unreachable!("message can be sent; qed") + }; + if let Some(delivery_fee) = delivery_fees.inner().first() { + let Fungible(delivery_fee_amount) = delivery_fee.fun else { + unreachable!("asset is fungible; qed"); + }; + delivery_fee_amount + } else { + 0 + } +} + /// Helper function to verify `xcm` contains all relevant instructions expected on destination /// chain as part of a reserve-asset-transfer. pub(crate) fn assert_matches_reserve_asset_deposited_instructions( diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 31f235db0edb..2fab95832fe4 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -16,7 +16,7 @@ //! Module contains predefined test-case scenarios for `Runtime` with various assets. use super::xcm_helpers; -use crate::assert_matches_reserve_asset_deposited_instructions; +use crate::{assert_matches_reserve_asset_deposited_instructions, get_fungible_delivery_fees}; use codec::Encode; use cumulus_primitives_core::XcmpMessageSource; use frame_support::{ @@ -1462,9 +1462,14 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< &alice, ); - // drip ED to account - let alice_account_init_balance = - existential_deposit.saturating_mul(2.into()) + balance_to_transfer.into(); + // we calculate exact delivery fees _after_ sending the message by weighing the sent + // xcm, and this delivery fee varies for different runtimes, so just add enough buffer, + // then verify the arithmetics check out on final balance. + let delivery_fees_buffer = 40_000_000_000u128; + // drip 2xED + transfer_amount + delivery_fees_buffer to Alice account + let alice_account_init_balance = existential_deposit.saturating_mul(2.into()) + + balance_to_transfer.into() + + delivery_fees_buffer.into(); let _ = >::deposit_creating( &alice_account, alice_account_init_balance, @@ -1494,15 +1499,10 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< id: Concrete(native_asset), }; - // TODO: Get this fee via weighing the corresponding message - let delivery_fees = 31010000000; - >::mint_into(&alice_account, delivery_fees.into()) - .unwrap(); - // pallet_xcm call reserve transfer assert_ok!(>::limited_reserve_transfer_assets( RuntimeHelper::::origin_of(alice_account.clone()), - Box::new(dest.into_versioned()), + Box::new(dest.clone().into_versioned()), Box::new(dest_beneficiary.into_versioned()), Box::new(VersionedMultiAssets::from(MultiAssets::from(asset_to_transfer))), 0, @@ -1518,20 +1518,6 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< }, ); - // check alice account decreased by balance_to_transfer - // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot/pull/7005) merged - assert_eq!( - >::free_balance(&alice_account), - alice_account_init_balance - balance_to_transfer.into() - ); - - // check reserve account - // check reserve account increased by balance_to_transfer - assert_eq!( - >::free_balance(&reserve_account), - existential_deposit + balance_to_transfer.into() - ); - // check that xcm was sent let xcm_sent_message_hash = >::events() .into_iter() @@ -1548,6 +1534,10 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< ) .unwrap(); + let delivery_fees = get_fungible_delivery_fees::< + ::XcmSender, + >(dest, Xcm::try_from(xcm_sent.clone()).unwrap()); + assert_eq!( xcm_sent_message_hash, Some(xcm_sent.using_encoded(sp_io::hashing::blake2_256)) @@ -1566,5 +1556,18 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< &reserve_assets_deposited, &dest_beneficiary, ); + + // check alice account decreased by balance_to_transfer ( + delivery_fees) + assert_eq!( + >::free_balance(&alice_account), + alice_account_init_balance - balance_to_transfer.into() - delivery_fees.into() + ); + + // check reserve account + // check reserve account increased by balance_to_transfer + assert_eq!( + >::free_balance(&reserve_account), + existential_deposit + balance_to_transfer.into() + ); }) } From dd46f23d2f6d7c1ede65a01b1a44c8fdf30b2624 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 24 Oct 2023 18:38:36 +0300 Subject: [PATCH 052/124] fix runtime-benchmarks for AHRococo --- .../assets/asset-hub-rococo/src/xcm_config.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index ae4a275d43ac..e76417ba309a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -653,6 +653,16 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); + // Relay/native token can be teleported between AH and Relay. + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + Parent.into(), + )); + // We can reserve transfer some local token to Relay. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + Parent.into(), + )); } impl pallet_xcm::Config for Runtime { @@ -691,11 +701,15 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + #[cfg(feature = "runtime-benchmarks")] + type TeleportableAssets = TeleportableAssets; + #[cfg(feature = "runtime-benchmarks")] + type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { From e8cbcb954782db95a918a8c8bbb6d0682b5c29bd Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 24 Oct 2023 18:51:39 +0300 Subject: [PATCH 053/124] fix clippy --- cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 2fab95832fe4..97f68269c81a 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -1502,7 +1502,7 @@ pub fn reserve_transfer_native_asset_to_non_teleport_para_works< // pallet_xcm call reserve transfer assert_ok!(>::limited_reserve_transfer_assets( RuntimeHelper::::origin_of(alice_account.clone()), - Box::new(dest.clone().into_versioned()), + Box::new(dest.into_versioned()), Box::new(dest_beneficiary.into_versioned()), Box::new(VersionedMultiAssets::from(MultiAssets::from(asset_to_transfer))), 0, From ea3aaadab8d2bad2a7bb9946fb42cdfacd7d68db Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Tue, 24 Oct 2023 22:36:55 +0200 Subject: [PATCH 054/124] fixing tests --- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 22e9949ae0d0..f508ccbeb946 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -982,6 +982,12 @@ impl_runtime_apis! { } } + impl snowbridge_outbound_queue_runtime_api::OutboundQueueApi for Runtime { + fn prove_message(leaf_index: u64) -> Option { + snowbridge_outbound_queue::api::prove_message::(leaf_index) + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { From 22cc658f0904fde4d787ad74265d978a17c12106 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 25 Oct 2023 09:15:13 +0200 Subject: [PATCH 055/124] adds upstream changes --- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 4 +- .../bridge-hub-rococo/src/weights/mod.rs | 3 +- .../src/weights/snowbridge_outbound_queue.rs | 64 +++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index f508ccbeb946..9c52962b4a4d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -547,12 +547,13 @@ impl snowbridge_outbound_queue::Config for Runtime { type MessageQueue = MessageQueue; type MaxMessagePayloadSize = MaxMessagePayloadSize; type MaxMessagesPerBlock = MaxMessagesPerBlock; + type OwnParaId = ParachainInfo; type GasMeter = snowbridge_core::outbound::ConstantGasMeter; type Balance = Balance; type DeliveryFeePerGas = DeliveryFeePerGas; type DeliveryRefundPerGas = DeliveryRefundPerGas; type DeliveryReward = DeliveryReward; - type WeightInfo = (); + type WeightInfo = weights::snowbridge_outbound_queue::WeightInfo; } #[cfg(not(feature = "beacon-spec-mainnet"))] @@ -742,6 +743,7 @@ mod benches { [pallet_bridge_relayers, BridgeRelayersBench::] // Ethereum Bridge [snowbridge_inbound_queue, EthereumInboundQueue] + [snowbridge_outbound_queue, EthereumOutboundQueue] [snowbridge_control, EthereumControl] [snowbridge_ethereum_beacon_client, EthereumBeaconClient] ); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs index 2dab4c4d0257..7a791db64756 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs @@ -37,9 +37,10 @@ pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; pub mod rocksdb_weights; +pub mod snowbridge_control; pub mod snowbridge_ethereum_beacon_client; pub mod snowbridge_inbound_queue; -pub mod snowbridge_control; +pub mod snowbridge_outbound_queue; pub mod xcm; pub use block_weights::constants::BlockExecutionWeight; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs new file mode 100644 index 000000000000..ef2ab1d4f53f --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs @@ -0,0 +1,64 @@ +//! Autogenerated weights for `snowbridge_outbound_queue` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-10-20, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `192.168.1.13`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024 + +// Executed Command: +// ../target/release/polkadot-parachain +// benchmark +// pallet +// --chain=bridge-hub-rococo-dev +// --pallet=snowbridge_outbound_queue +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --output +// ../parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `snowbridge_outbound_queue`. +pub struct WeightInfo(PhantomData); +impl snowbridge_outbound_queue::WeightInfo for WeightInfo { + /// Storage: EthereumOutboundQueue MessageLeaves (r:1 w:1) + /// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: EthereumOutboundQueue PendingHighPriorityMessageCount (r:1 w:1) + /// Proof: EthereumOutboundQueue PendingHighPriorityMessageCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue Nonce (r:1 w:1) + /// Proof: EthereumOutboundQueue Nonce (max_values: None, max_size: Some(20), added: 2495, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue Messages (r:1 w:1) + /// Proof Skipped: EthereumOutboundQueue Messages (max_values: Some(1), max_size: None, mode: Measured) + fn do_process_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `3485` + // Minimum execution time: 38_000_000 picoseconds. + Weight::from_parts(38_000_000, 0) + .saturating_add(Weight::from_parts(0, 3485)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: EthereumOutboundQueue MessageLeaves (r:1 w:0) + /// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + fn on_finalize() -> Weight { + // Proof Size summary in bytes: + // Measured: `1094` + // Estimated: `2579` + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(28_000_000, 0) + .saturating_add(Weight::from_parts(0, 2579)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} From 9e941d361170875eb174539da1259e964e1cba28 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 25 Oct 2023 10:20:16 +0200 Subject: [PATCH 056/124] cleanup comments, fix upgrade gateway test --- .../runtimes/assets/asset-hub-rococo/src/xcm_config.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 6335b396e0eb..ee294dac2c96 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -936,9 +936,7 @@ pub mod bridging { ]; pub AllowedReserveTransferAssetsToEthereum: sp_std::vec::Vec = sp_std::vec![ - // allow send only WOC Wild(AllOf { fun: WildFungible, id: Concrete(EthereumGatewayLocation::get()) }), // TODO check - // and nothing else ]; /// Universal aliases From d725103702fc8f76405b507185f7b1ae7d9bfece Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 25 Oct 2023 13:39:49 +0300 Subject: [PATCH 057/124] withdraw fees before buyexecution - still broken because of executor appended ClearOrigin --- polkadot/xcm/pallet-xcm/src/lib.rs | 58 +++++++++++-------- .../pallet-xcm/src/tests/assets_transfer.rs | 21 +++---- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 257c46746ad2..3b066f3df83a 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1288,21 +1288,20 @@ impl Pallet { Self::validate_assets_and_find_reserve(&assets, &dest)? }; - let jit_withdraw_fee_on_dest; + let explicit_withdraw_fee_on_dest; if fees_transfer_type == assets_transfer_type { // Same reserve location (fees not teleportable), we can batch together fees and assets // in same reserve-based-transfer. assets.push(fees.clone()); - // no need to jit withdraw fee, fees batched with assets will be available in holding - jit_withdraw_fee_on_dest = false; + // no need to withdraw fee on dest, fees batched with assets will be available in + // holding + explicit_withdraw_fee_on_dest = false; } else { // Disallow _remote reserves_ unless assets & fees have same remote reserve (covered by // branch above). The reason for this is that we'd need to send XCMs to separate chains // with no guarantee of delivery order on final destination; therefore we cannot // guarantee to have fees in place on final destination chain to pay for assets // transfer. - if let TransferType::RemoteReserve(_) = assets_transfer_type {} - // Disallow (for now) different _remote_ reserves for assets and fees. match (&fees_transfer_type, &assets_transfer_type) { (TransferType::RemoteReserve(_), _) | (_, TransferType::RemoteReserve(_)) => return Err(Error::::InvalidAssetUnsupportedReserve.into()), @@ -1322,8 +1321,8 @@ impl Pallet { weight_limit.clone(), )?; // fees are deposited to beneficiary in call above, when transferring rest of assets, - // jit withdraw fee on destination - jit_withdraw_fee_on_dest = true; + // withdraw fee to holding on destination so it can be used for `BuyExecution` + explicit_withdraw_fee_on_dest = true; }; // Fees have been prefunded/transferred (or batched together with assets to be transferred @@ -1335,7 +1334,7 @@ impl Pallet { assets, assets_transfer_type, fees, - jit_withdraw_fee_on_dest, + explicit_withdraw_fee_on_dest, weight_limit, ) } @@ -1385,7 +1384,7 @@ impl Pallet { assets: Vec, transfer_type: TransferType, fees: MultiAsset, - jit_withdraw_fee_on_dest: bool, + explicit_withdraw_fee_on_dest: bool, weight_limit: WeightLimit, ) -> DispatchResult { let mut message = match transfer_type { @@ -1394,7 +1393,7 @@ impl Pallet { beneficiary, assets, fees, - jit_withdraw_fee_on_dest, + explicit_withdraw_fee_on_dest, weight_limit, ), TransferType::DestinationReserve => Self::destination_reserve_transfer_message( @@ -1402,7 +1401,7 @@ impl Pallet { beneficiary, assets, fees, - jit_withdraw_fee_on_dest, + explicit_withdraw_fee_on_dest, weight_limit, ), TransferType::RemoteReserve(reserve) => Self::remote_reserve_transfer_message( @@ -1429,17 +1428,21 @@ impl Pallet { beneficiary: MultiLocation, assets: Vec, mut fees: MultiAsset, - jit_withdraw_fee_on_dest: bool, + explicit_withdraw_fee_on_dest: bool, weight_limit: WeightLimit, ) -> Result::RuntimeCall>, Error> { let context = T::UniversalLocation::get(); fees.reanchor(&dest, context).map_err(|_| Error::::CannotReanchor)?; - let max_assets = assets.len() as u32; - let xcm_on_dest = Xcm(vec![ - SetFeesMode { jit_withdraw: jit_withdraw_fee_on_dest }, - BuyExecution { fees, weight_limit }, - DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, - ]); + let mut max_assets = assets.len() as u32; + let mut xcm_on_dest = Vec::with_capacity(3); + if explicit_withdraw_fee_on_dest { + // also deposit `fees` which are not included in `assets` + max_assets += 1; + xcm_on_dest.push(WithdrawAsset(fees.clone().into())); + }; + xcm_on_dest.push(BuyExecution { fees, weight_limit }); + xcm_on_dest.push(DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }); + let xcm_on_dest = Xcm(xcm_on_dest); Ok(Xcm(vec![ SetFeesMode { jit_withdraw: true }, TransferReserveAsset { assets: assets.into(), dest, xcm: xcm_on_dest }, @@ -1451,17 +1454,22 @@ impl Pallet { beneficiary: MultiLocation, assets: Vec, mut fees: MultiAsset, - jit_withdraw_fee_on_dest: bool, + explicit_withdraw_fee_on_dest: bool, weight_limit: WeightLimit, ) -> Result::RuntimeCall>, Error> { let context = T::UniversalLocation::get(); fees.reanchor(&dest, context).map_err(|_| Error::::CannotReanchor)?; - let max_assets = assets.len() as u32; - let xcm_on_dest = Xcm(vec![ - SetFeesMode { jit_withdraw: jit_withdraw_fee_on_dest }, - BuyExecution { fees, weight_limit }, - DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, - ]); + let mut max_assets = assets.len() as u32; + + let mut xcm_on_dest = Vec::with_capacity(3); + if explicit_withdraw_fee_on_dest { + // also deposit `fees` which are not included in `assets` + max_assets += 1; + xcm_on_dest.push(WithdrawAsset(fees.clone().into())); + }; + xcm_on_dest.push(BuyExecution { fees, weight_limit }); + xcm_on_dest.push(DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }); + let xcm_on_dest = Xcm(xcm_on_dest); Ok(Xcm(vec![ WithdrawAsset(assets.into()), InitiateReserveWithdraw { diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index 2e90b6efccbf..44e41d641447 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -171,7 +171,6 @@ fn reserve_transfer_assets_with_paid_router_works() { Xcm(vec![ ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), ClearOrigin, - SetFeesMode { jit_withdraw: false }, buy_execution((Parent, SEND_AMOUNT)), DepositAsset { assets: AllCounted(1).into(), beneficiary: dest }, ]), @@ -290,7 +289,6 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( Xcm(vec![ ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), ClearOrigin, - SetFeesMode { jit_withdraw: false }, buy_limited_execution((Parent, SEND_AMOUNT), expected_weight_limit), DepositAsset { assets: AllCounted(1).into(), @@ -460,7 +458,6 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ Xcm(vec![ ReserveAssetDeposited((Parent, FEE_AMOUNT).into()), ClearOrigin, - SetFeesMode { jit_withdraw: false }, buy_limited_execution((Parent, FEE_AMOUNT), Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]) @@ -473,9 +470,9 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ Xcm(vec![ WithdrawAsset(expected_asset.into()), ClearOrigin, - SetFeesMode { jit_withdraw: true }, + WithdrawAsset(expected_fee.clone().into()), buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, + DepositAsset { assets: AllCounted(2).into(), beneficiary }, ]) ) ] @@ -638,7 +635,6 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ Xcm(vec![ WithdrawAsset(expected_fee.clone().into()), ClearOrigin, - SetFeesMode { jit_withdraw: false }, buy_limited_execution(expected_fee.clone(), Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]) @@ -652,9 +648,9 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ Xcm(vec![ ReserveAssetDeposited(expected_asset.into()), ClearOrigin, - SetFeesMode { jit_withdraw: true }, + WithdrawAsset(expected_fee.clone().into()), buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, + DepositAsset { assets: AllCounted(2).into(), beneficiary }, ]) ) ] @@ -741,7 +737,6 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re Xcm(vec![ WithdrawAsset(expected_assets.clone()), ClearOrigin, - SetFeesMode { jit_withdraw: false }, buy_limited_execution(expected_assets.get(0).unwrap().clone(), Unlimited), DepositAsset { assets: AllCounted(1).into(), beneficiary }, ]), @@ -1172,9 +1167,9 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { Xcm(vec![ ReserveAssetDeposited(expected_asset.into()), ClearOrigin, - SetFeesMode { jit_withdraw: true }, + WithdrawAsset(expected_fee.clone().into()), buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, + DepositAsset { assets: AllCounted(2).into(), beneficiary }, ]) ) ] @@ -1303,9 +1298,9 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor Xcm(vec![ WithdrawAsset(expected_asset.into()), ClearOrigin, - SetFeesMode { jit_withdraw: true }, + WithdrawAsset(expected_fee.clone().into()), buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, + DepositAsset { assets: AllCounted(2).into(), beneficiary }, ]) ) ] From 3d97f19e679735daa6e5c2c9b27960e624270b81 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 25 Oct 2023 14:19:31 +0300 Subject: [PATCH 058/124] pallet-xcm: uses single custom XCM to send both fees and assets --- polkadot/xcm/pallet-xcm/src/lib.rs | 346 ++++++++++++++++++++--------- 1 file changed, 246 insertions(+), 100 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 3b066f3df83a..f2d5779019ed 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1288,41 +1288,32 @@ impl Pallet { Self::validate_assets_and_find_reserve(&assets, &dest)? }; - let explicit_withdraw_fee_on_dest; + let prefund_fees_messages: Option<(Xcm<::RuntimeCall>, Xcm<()>)>; if fees_transfer_type == assets_transfer_type { // Same reserve location (fees not teleportable), we can batch together fees and assets // in same reserve-based-transfer. assets.push(fees.clone()); - // no need to withdraw fee on dest, fees batched with assets will be available in - // holding - explicit_withdraw_fee_on_dest = false; + // no need for custom prefund messages, fees are batched with assets + prefund_fees_messages = None; } else { // Disallow _remote reserves_ unless assets & fees have same remote reserve (covered by // branch above). The reason for this is that we'd need to send XCMs to separate chains // with no guarantee of delivery order on final destination; therefore we cannot // guarantee to have fees in place on final destination chain to pay for assets // transfer. - match (&fees_transfer_type, &assets_transfer_type) { - (TransferType::RemoteReserve(_), _) | (_, TransferType::RemoteReserve(_)) => + if let TransferType::RemoteReserve(_) = assets_transfer_type { + return Err(Error::::InvalidAssetUnsupportedReserve.into()) + } + // build fees transfer instructions to be added to assets transfers XCM programs + prefund_fees_messages = Some(match fees_transfer_type { + TransferType::LocalReserve => + Self::prefund_local_reserve_fees_messages(dest, fees.clone())?, + TransferType::DestinationReserve => + Self::prefund_destination_reserve_fees_messages(dest, fees.clone())?, + TransferType::Teleport => Self::prefund_teleport_fees_messages(dest, fees.clone())?, + TransferType::RemoteReserve(_) => return Err(Error::::InvalidAssetUnsupportedReserve.into()), - _ => (), - }; - - // execute fees transfer - do it in a separate asset transfer call to keep code logic - // simple: first send over fees, then assets with `jit_withdraw=true` - Self::build_and_execute_xcm_transfer_type( - origin_location, - dest, - beneficiary, - vec![fees.clone()], - fees_transfer_type, - fees.clone(), - false, - weight_limit.clone(), - )?; - // fees are deposited to beneficiary in call above, when transferring rest of assets, - // withdraw fee to holding on destination so it can be used for `BuyExecution` - explicit_withdraw_fee_on_dest = true; + }); }; // Fees have been prefunded/transferred (or batched together with assets to be transferred @@ -1334,7 +1325,7 @@ impl Pallet { assets, assets_transfer_type, fees, - explicit_withdraw_fee_on_dest, + prefund_fees_messages, weight_limit, ) } @@ -1372,114 +1363,242 @@ impl Pallet { assets, TransferType::Teleport, fees, - false, + None, weight_limit, ) } fn build_and_execute_xcm_transfer_type( - origin: impl Into, + origin: MultiLocation, dest: MultiLocation, beneficiary: MultiLocation, assets: Vec, transfer_type: TransferType, fees: MultiAsset, - explicit_withdraw_fee_on_dest: bool, + prefund_fees_messages: Option<(Xcm<::RuntimeCall>, Xcm<()>)>, weight_limit: WeightLimit, ) -> DispatchResult { - let mut message = match transfer_type { - TransferType::LocalReserve => Self::local_reserve_transfer_message( - dest, - beneficiary, - assets, - fees, - explicit_withdraw_fee_on_dest, - weight_limit, - ), - TransferType::DestinationReserve => Self::destination_reserve_transfer_message( - dest, - beneficiary, - assets, - fees, - explicit_withdraw_fee_on_dest, - weight_limit, - ), - TransferType::RemoteReserve(reserve) => Self::remote_reserve_transfer_message( - reserve, - dest, - beneficiary, - assets, - fees, - weight_limit, + let (mut local_xcm, remote_xcm) = match transfer_type { + TransferType::LocalReserve => { + let (local, remote) = Self::local_reserve_transfer_messages( + dest, + beneficiary, + assets, + fees, + prefund_fees_messages, + weight_limit, + )?; + (local, Some(remote)) + }, + TransferType::DestinationReserve => { + let (local, remote) = Self::destination_reserve_transfer_messages( + dest, + beneficiary, + assets, + fees, + prefund_fees_messages, + weight_limit, + )?; + (local, Some(remote)) + }, + TransferType::RemoteReserve(reserve) => ( + Self::remote_reserve_transfer_message( + reserve, + dest, + beneficiary, + assets, + fees, + weight_limit, + )?, + None, ), TransferType::Teleport => - Self::teleport_asset_message(dest, beneficiary, assets, fees, weight_limit), - }?; + (Self::teleport_asset_message(dest, beneficiary, assets, fees, weight_limit)?, None), + }; let weight = - T::Weigher::weight(&mut message).map_err(|()| Error::::UnweighableMessage)?; - let hash = message.using_encoded(sp_io::hashing::blake2_256); - let outcome = T::XcmExecutor::execute_xcm_in_credit(origin, message, hash, weight, weight); - Self::deposit_event(Event::Attempted { outcome }); + T::Weigher::weight(&mut local_xcm).map_err(|()| Error::::UnweighableMessage)?; + let hash = local_xcm.using_encoded(sp_io::hashing::blake2_256); + let outcome = + T::XcmExecutor::execute_xcm_in_credit(origin, local_xcm, hash, weight, weight); + Self::deposit_event(Event::Attempted { outcome: outcome.clone() }); + if let Some(remote_xcm) = remote_xcm { + outcome.ensure_complete().map_err(|_| Error::::FeesNotMet)?; + let interior: Junctions = origin.try_into().map_err(|_| Error::::InvalidOrigin)?; + let message_id = + Self::send_xcm(interior, dest, remote_xcm.clone()).map_err(Error::::from)?; + let e = Event::Sent { origin, destination: dest, message: remote_xcm, message_id }; + Self::deposit_event(e); + } Ok(()) } - fn local_reserve_transfer_message( + fn prefund_local_reserve_fees_messages( + dest: MultiLocation, + fees: MultiAsset, + ) -> Result<(Xcm<::RuntimeCall>, Xcm<()>), Error> { + let context = T::UniversalLocation::get(); + let reanchored_fees = fees + .clone() + .reanchored(&dest, context) + .map_err(|_| Error::::CannotReanchor)?; + + let local_execute_xcm = Xcm(vec![ + // move `fees` to `dest`s local sovereign account + TransferAsset { assets: fees.into(), beneficiary: dest }, + ]); + let xcm_on_dest = Xcm(vec![ + // let (dest) chain know `fees` are in its SA on reserve + ReserveAssetDeposited(reanchored_fees.into()), + ]); + Ok((local_execute_xcm, xcm_on_dest)) + } + + fn local_reserve_transfer_messages( dest: MultiLocation, beneficiary: MultiLocation, assets: Vec, - mut fees: MultiAsset, - explicit_withdraw_fee_on_dest: bool, + fees: MultiAsset, + prefund_fees_messages: Option<(Xcm<::RuntimeCall>, Xcm<()>)>, weight_limit: WeightLimit, - ) -> Result::RuntimeCall>, Error> { + ) -> Result<(Xcm<::RuntimeCall>, Xcm<()>), Error> { + // max assets is `assets` ( + potentially separately handled fee) + let max_assets = + assets.len() as u32 + prefund_fees_messages.as_ref().map(|_| 1).unwrap_or(0); + let assets: MultiAssets = assets.into(); let context = T::UniversalLocation::get(); - fees.reanchor(&dest, context).map_err(|_| Error::::CannotReanchor)?; - let mut max_assets = assets.len() as u32; - let mut xcm_on_dest = Vec::with_capacity(3); - if explicit_withdraw_fee_on_dest { - // also deposit `fees` which are not included in `assets` - max_assets += 1; - xcm_on_dest.push(WithdrawAsset(fees.clone().into())); - }; - xcm_on_dest.push(BuyExecution { fees, weight_limit }); - xcm_on_dest.push(DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }); - let xcm_on_dest = Xcm(xcm_on_dest); - Ok(Xcm(vec![ - SetFeesMode { jit_withdraw: true }, - TransferReserveAsset { assets: assets.into(), dest, xcm: xcm_on_dest }, - ])) + let reanchored_fees = + fees.reanchored(&dest, context).map_err(|_| Error::::CannotReanchor)?; + let mut reanchored_assets = assets.clone(); + reanchored_assets + .reanchor(&dest, context) + .map_err(|_| Error::::CannotReanchor)?; + + let (prefund_local_xcm, prefund_remote_xcm) = prefund_fees_messages + .map(|(local, remote)| (local.into_inner(), remote.into_inner())) + .unwrap_or_default(); + + let local_execute_xcm = Xcm( + // JIT withdraw fees for local execution + [SetFeesMode { jit_withdraw: true }] + .into_iter() + // run any necessary local prefund fees instructions + .chain(prefund_local_xcm.into_iter()) + // move `assets` to `dest`s local sovereign account + .chain([TransferAsset { assets, beneficiary: dest }].into_iter()) + .collect(), + ); + let xcm_on_dest = Xcm( + // run any necessary remote prefund fees instructions + prefund_remote_xcm + .into_iter() + .chain( + [ + // let (dest) chain know assets are in its SA on reserve + ReserveAssetDeposited(reanchored_assets), + // following instructions are not exec'ed on behalf of origin chain anymore + ClearOrigin, + // buy exec using `fees` in holding deposited in top instruction here + BuyExecution { fees: reanchored_fees, weight_limit }, + // deposit all assets in holding to `beneficiary` account(s) + DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, + ] + .into_iter(), + ) + .collect(), + ); + Ok((local_execute_xcm, xcm_on_dest)) } - fn destination_reserve_transfer_message( + fn prefund_destination_reserve_fees_messages( + dest: MultiLocation, + fees: MultiAsset, + ) -> Result<(Xcm<::RuntimeCall>, Xcm<()>), Error> { + let context = T::UniversalLocation::get(); + let reanchored_fees = fees + .clone() + .reanchored(&dest, context) + .map_err(|_| Error::::CannotReanchor)?; + let fees: MultiAssets = fees.into(); + + let local_execute_xcm = Xcm(vec![ + // withdraw reserve-based fees (derivatives) + WithdrawAsset(fees.clone()), + // burn derivatives + BurnAsset(fees), + ]); + let xcm_on_dest = Xcm(vec![ + // withdraw `fees` from origin chain's sovereign account + WithdrawAsset(reanchored_fees.into()), + ]); + Ok((local_execute_xcm, xcm_on_dest)) + } + + fn destination_reserve_transfer_messages( dest: MultiLocation, beneficiary: MultiLocation, assets: Vec, - mut fees: MultiAsset, - explicit_withdraw_fee_on_dest: bool, + fees: MultiAsset, + prefund_fees_messages: Option<(Xcm<::RuntimeCall>, Xcm<()>)>, weight_limit: WeightLimit, - ) -> Result::RuntimeCall>, Error> { + ) -> Result<(Xcm<::RuntimeCall>, Xcm<()>), Error> { + // max assets is `assets` ( + potentially separately handled fee) + let max_assets = + assets.len() as u32 + prefund_fees_messages.as_ref().map(|_| 1).unwrap_or(0); + let assets: MultiAssets = assets.into(); let context = T::UniversalLocation::get(); - fees.reanchor(&dest, context).map_err(|_| Error::::CannotReanchor)?; - let mut max_assets = assets.len() as u32; + let reanchored_fees = + fees.reanchored(&dest, context).map_err(|_| Error::::CannotReanchor)?; + let mut reanchored_assets = assets.clone(); + reanchored_assets + .reanchor(&dest, context) + .map_err(|_| Error::::CannotReanchor)?; - let mut xcm_on_dest = Vec::with_capacity(3); - if explicit_withdraw_fee_on_dest { - // also deposit `fees` which are not included in `assets` - max_assets += 1; - xcm_on_dest.push(WithdrawAsset(fees.clone().into())); - }; - xcm_on_dest.push(BuyExecution { fees, weight_limit }); - xcm_on_dest.push(DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }); - let xcm_on_dest = Xcm(xcm_on_dest); - Ok(Xcm(vec![ - WithdrawAsset(assets.into()), - InitiateReserveWithdraw { - assets: Wild(AllCounted(max_assets)), - reserve: dest, - xcm: xcm_on_dest, - }, - ])) + let (prefund_local_xcm, prefund_remote_xcm) = prefund_fees_messages + .map(|(local, remote)| (local.into_inner(), remote.into_inner())) + // default is empty vec, so no prefund instructions required + .unwrap_or_default(); + + let local_execute_xcm = Xcm( + // JIT withdraw fees for local execution + [SetFeesMode { jit_withdraw: true }] + .into_iter() + // run any necessary local prefund fees instructions + .chain(prefund_local_xcm.into_iter()) + // move `assets` to `dest`s local sovereign account + .chain( + [ + // withdraw reserve-based assets + WithdrawAsset(assets.clone()), + // burn reserve-based assets + BurnAsset(assets), + ] + .into_iter(), + ) + .collect(), + ); + let xcm_on_dest = Xcm( + // run any necessary remote prefund fees instructions + prefund_remote_xcm + .into_iter() + .chain( + [ + // withdraw `assets` from origin chain's sovereign account + WithdrawAsset(reanchored_assets), + // following instructions are not exec'ed on behalf of origin chain anymore + ClearOrigin, + // buy exec using `fees` in holding deposited in top instruction here + BuyExecution { fees: reanchored_fees, weight_limit }, + // deposit all assets in holding to `beneficiary` account(s) + DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, + ] + .into_iter(), + ) + .collect(), + ); + Ok((local_execute_xcm, xcm_on_dest)) } + // function assumes fees and assets have the same remote reserve fn remote_reserve_transfer_message( reserve: MultiLocation, dest: MultiLocation, @@ -1519,6 +1638,33 @@ impl Pallet { ])) } + fn prefund_teleport_fees_messages( + dest: MultiLocation, + fees: MultiAsset, + ) -> Result<(Xcm<::RuntimeCall>, Xcm<()>), Error> { + let context = T::UniversalLocation::get(); + let reanchored_fees = fees + .clone() + .reanchored(&dest, context) + .map_err(|_| Error::::CannotReanchor)?; + let fees: MultiAssets = fees.into(); + + // FIXME: this should also handle `checking_account` in `XcmExecutor::AssetTransactor` but + // we can't access it here rignt now. + + let local_execute_xcm = Xcm(vec![ + // withdraw fees + WithdrawAsset(fees.clone()), + // burn fees + BurnAsset(fees), + ]); + let xcm_on_dest = Xcm(vec![ + // (dest) chain receive teleported assets burned on origin chain + ReceiveTeleportedAsset(reanchored_fees.into()), + ]); + Ok((local_execute_xcm, xcm_on_dest)) + } + fn teleport_asset_message( dest: MultiLocation, beneficiary: MultiLocation, From ac3773eddc7b4a8b8a5ed56d039f8cab614541d5 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 25 Oct 2023 14:22:06 +0300 Subject: [PATCH 059/124] pallet-xcm: handle teleport checking account when custom burn+teleport --- polkadot/xcm/pallet-xcm/src/lib.rs | 26 ++++++++++++++++--- polkadot/xcm/xcm-executor/src/lib.rs | 1 + .../xcm-executor/src/traits/asset_transfer.rs | 4 +++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index f2d5779019ed..9fd233e37507 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -53,7 +53,7 @@ pub use pallet::*; use xcm_executor::{ traits::{ CheckSuspension, ClaimAssets, ConvertLocation, DropAssets, MatchesFungible, OnResponse, - QueryHandler, QueryResponseStatus, VersionChangeNotifier, WeightBounds, + QueryHandler, QueryResponseStatus, TransactAsset, VersionChangeNotifier, WeightBounds, }, Assets, }; @@ -429,6 +429,8 @@ pub mod pallet { DestinationNotInvertible, /// The assets to be sent are empty. Empty, + /// Could not check-out the assets for teleportation to the destination chain. + CannotCheckOutTeleport, /// Could not re-anchor the assets to declare the fees for the destination chain. CannotReanchor, /// Too many assets have been attempted for transfer. @@ -1647,11 +1649,27 @@ impl Pallet { .clone() .reanchored(&dest, context) .map_err(|_| Error::::CannotReanchor)?; - let fees: MultiAssets = fees.into(); - // FIXME: this should also handle `checking_account` in `XcmExecutor::AssetTransactor` but - // we can't access it here rignt now. + // XcmContext irrelevant in teleports checks + let dummy_context = + XcmContext { origin: None, message_id: Default::default(), topic: None }; + // We should check that the asset can actually be teleported out (for this to + // be in error, there would need to be an accounting violation by ourselves, + // so it's unlikely, but we don't want to allow that kind of bug to leak into + // a trusted chain. + ::AssetTransactor::can_check_out( + &dest, + &fees, + &dummy_context, + ) + .map_err(|_| Error::::CannotCheckOutTeleport)?; + ::AssetTransactor::check_out( + &dest, + &fees, + &dummy_context, + ); + let fees: MultiAssets = fees.into(); let local_execute_xcm = Xcm(vec![ // withdraw fees WithdrawAsset(fees.clone()), diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index d9a1123e00c2..b8e4c53c9889 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -258,6 +258,7 @@ impl ExecuteXcm for XcmExecutor AssetTransferSupport for XcmExecutor { type IsReserve = Config::IsReserve; type IsTeleporter = Config::IsTeleporter; + type AssetTransactor = Config::AssetTransactor; } #[derive(Debug)] diff --git a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs index 566b65739224..77b326052dcc 100644 --- a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs +++ b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . +use crate::traits::TransactAsset; use frame_support::traits::ContainsPair; use scale_info::TypeInfo; use sp_runtime::codec::{Decode, Encode}; @@ -52,6 +53,9 @@ pub trait AssetTransferSupport { /// to be used for assets matching this filter. type IsTeleporter: ContainsPair; + /// How to withdraw and deposit an asset. + type AssetTransactor: TransactAsset; + /// Determine transfer type to be used for transferring `asset` from local chain to `dest`. fn determine_for(asset: &MultiAsset, dest: &MultiLocation) -> Result { if Self::IsTeleporter::contains(asset, dest) { From cb6f53a6fdec12b10d06d543707eab469bd5f490 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 25 Oct 2023 15:50:04 +0300 Subject: [PATCH 060/124] fixes plus tests --- polkadot/xcm/pallet-xcm/src/lib.rs | 27 +-- polkadot/xcm/pallet-xcm/src/mock.rs | 14 +- .../pallet-xcm/src/tests/assets_transfer.rs | 161 +++++++++--------- 3 files changed, 103 insertions(+), 99 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 9fd233e37507..f97b6135d484 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -429,8 +429,6 @@ pub mod pallet { DestinationNotInvertible, /// The assets to be sent are empty. Empty, - /// Could not check-out the assets for teleportation to the destination chain. - CannotCheckOutTeleport, /// Could not re-anchor the assets to declare the fees for the destination chain. CannotReanchor, /// Too many assets have been attempted for transfer. @@ -446,12 +444,8 @@ pub mod pallet { NoSubscription, /// The location is invalid since it already has a subscription from us. AlreadySubscribed, - /// Invalid non-concrete asset. - InvalidAssetNotConcrete, - /// Invalid asset, reserve chain could not be determined for it. - InvalidAssetUnknownReserve, - /// Invalid asset, do not support remote asset reserves with different fees reserves. - InvalidAssetUnsupportedReserve, + /// Could not check-out the assets for teleportation to the destination chain. + CannotCheckOutTeleport, /// The owner does not own (all) of the asset that they wish to do the operation on. LowBalance, /// The asset owner has too many locks on the asset. @@ -464,6 +458,12 @@ pub mod pallet { LockNotFound, /// The unlock operation cannot succeed because there are still consumers of the lock. InUse, + /// Invalid non-concrete asset. + InvalidAssetNotConcrete, + /// Invalid asset, reserve chain could not be determined for it. + InvalidAssetUnknownReserve, + /// Invalid asset, do not support remote asset reserves with different fees reserves. + InvalidAssetUnsupportedReserve, /// Too many assets with different reserve locations have been attempted for transfer. TooManyReserves, } @@ -1425,9 +1425,14 @@ impl Pallet { Self::deposit_event(Event::Attempted { outcome: outcome.clone() }); if let Some(remote_xcm) = remote_xcm { outcome.ensure_complete().map_err(|_| Error::::FeesNotMet)?; - let interior: Junctions = origin.try_into().map_err(|_| Error::::InvalidOrigin)?; - let message_id = - Self::send_xcm(interior, dest, remote_xcm.clone()).map_err(Error::::from)?; + + let (ticket, price) = validate_send::(dest, remote_xcm.clone()) + .map_err(Error::::from)?; + if origin != Here.into_location() { + Self::charge_fees(origin, price).map_err(|_| Error::::FeesNotMet)?; + } + let message_id = T::XcmRouter::deliver(ticket).map_err(Error::::from)?; + let e = Event::Sent { origin, destination: dest, message: remote_xcm, message_id }; Self::deposit_event(e); } diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 7b74322e44ca..8fc980d04b80 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -186,13 +186,13 @@ impl SendXcm for TestSendXcmErrX8 { type Ticket = (MultiLocation, Xcm<()>); fn validate( dest: &mut Option, - msg: &mut Option>, + _: &mut Option>, ) -> SendResult<(MultiLocation, Xcm<()>)> { - let (dest, msg) = (dest.take().unwrap(), msg.take().unwrap()); - if dest.len() == 8 { + if dest.as_ref().unwrap().len() == 8 { + dest.take(); Err(SendError::Transport("Destination location full")) } else { - Ok(((dest, msg), MultiAssets::new())) + Err(SendError::NotApplicable) } } fn deliver(pair: (MultiLocation, Xcm<()>)) -> Result { @@ -439,10 +439,12 @@ pub type Barrier = ( AllowSubscriptionsFrom, ); +pub type XcmRouter = (TestPaidForPara3000SendXcm, TestSendXcmErrX8, TestSendXcm); + pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; - type XcmSender = (TestPaidForPara3000SendXcm, TestSendXcm); + type XcmSender = XcmRouter; type AssetTransactor = AssetTransactors; type OriginConverter = LocalOriginConverter; type IsReserve = (Case, Case); @@ -494,7 +496,7 @@ parameter_types! { impl pallet_xcm::Config for Test { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; - type XcmRouter = (TestSendXcmErrX8, TestPaidForPara3000SendXcm, TestSendXcm); + type XcmRouter = XcmRouter; type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; type XcmExecuteFilter = Everything; type XcmExecutor = XcmExecutor; diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index 44e41d641447..2f85fac7f840 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -145,27 +145,26 @@ fn reserve_transfer_assets_with_paid_router_works() { Box::new((Here, SEND_AMOUNT).into()), 0, )); - // check event - assert_eq!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) - ); // XCM_FEES_NOT_WAIVED_USER_ACCOUNT spent amount assert_eq!( Balances::free_balance(user_account), INITIAL_BALANCE - SEND_AMOUNT - xcm_router_fee_amount ); + // Destination account (parachain account) has amount let para_acc: AccountId = ParaId::from(paid_para_id).into_account_truncating(); assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT); + // XcmFeesTargetAccount where should lend xcm_router_fee_amount assert_eq!( Balances::free_balance(XcmFeesTargetAccount::get()), INITIAL_BALANCE + xcm_router_fee_amount ); + + let sent_xcm = sent_xcm(); assert_eq!( - sent_xcm(), + sent_xcm, vec![( Parachain(paid_para_id).into(), Xcm(vec![ @@ -176,10 +175,34 @@ fn reserve_transfer_assets_with_paid_router_works() { ]), )] ); + let inner_message = sent_xcm.into_iter().next().unwrap().1; + let mut last_events = last_events(5).into_iter(); assert_eq!( - last_event(), + last_events.next().unwrap(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) ); + // balances events + last_events.next().unwrap(); + last_events.next().unwrap(); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::FeesPaid { + paying: dest, + fees: Para3000PaymentMultiAssets::get(), + }) + ); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Sent { + origin: dest, + destination: Parachain(paid_para_id).into(), + message: inner_message, + message_id: [ + 55, 64, 13, 96, 90, 32, 133, 17, 152, 138, 167, 156, 159, 194, 154, 181, 130, + 98, 75, 249, 162, 253, 58, 246, 44, 117, 152, 11, 57, 102, 238, 131 + ], + }) + ); }); } @@ -248,8 +271,7 @@ fn into_multiassets_checked( (assets, fee_index, fee_asset, transfer_asset) } -/// Helper function to test `reserve_transfer_assets` with local asset reserve and local fee -/// reserve. +/// Test `limited_reserve_transfer_assets` with local asset reserve and local fee reserve. /// /// Transferring native asset (local reserve) to some `OTHER_PARA_ID` (no teleport trust). /// Using native asset for fees as well. @@ -263,27 +285,39 @@ fn into_multiassets_checked( /// | \--> sends `ReserveAssetDeposited(both), ClearOrigin, BuyExecution(fees), DepositAsset` /// \------------------------------------------> /// ``` -fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( - expected_beneficiary: MultiLocation, - call: Call, - expected_weight_limit: WeightLimit, -) { +#[test] +fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works() { let balances = vec![ (ALICE, INITIAL_BALANCE), (ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE), ]; + + let beneficiary: MultiLocation = + Junction::AccountId32 { network: None, id: ALICE.into() }.into(); + let weight_limit = WeightLimit::Limited(Weight::from_parts(5000, 5000)); + let expected_weight_limit = weight_limit.clone(); + let expected_beneficiary = beneficiary; + new_test_ext_with_balances(balances).execute_with(|| { let weight = BaseXcmWeight::get() * 2; assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); // call extrinsic - call(); + assert_ok!(XcmPallet::limited_reserve_transfer_assets( + RuntimeOrigin::signed(ALICE), + Box::new(Parachain(OTHER_PARA_ID).into()), + Box::new(beneficiary.into()), + Box::new((Here, SEND_AMOUNT).into()), + 0, + weight_limit, + )); // Alice spent amount assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE - SEND_AMOUNT); // Destination account (parachain account) has amount let para_acc: AccountId = ParaId::from(OTHER_PARA_ID).into_account_truncating(); assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT); + let sent_xcm = sent_xcm(); assert_eq!( - sent_xcm(), + sent_xcm, vec![( Parachain(OTHER_PARA_ID).into(), Xcm(vec![ @@ -297,71 +331,34 @@ fn do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( ]), )] ); + let inner_message = sent_xcm.into_iter().next().unwrap().1; + let mut last_events = last_events(3).into_iter(); assert_eq!( - last_event(), + last_events.next().unwrap(), RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) ); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::FeesPaid { + paying: expected_beneficiary, + fees: MultiAssets::new(), + }) + ); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Sent { + origin: expected_beneficiary, + destination: Parachain(OTHER_PARA_ID).into(), + message: inner_message, + message_id: [ + 53, 1, 255, 66, 147, 147, 39, 116, 107, 79, 145, 26, 237, 73, 0, 165, 70, 43, + 122, 224, 230, 68, 62, 15, 200, 250, 105, 14, 100, 65, 100, 204 + ], + }) + ); }); } -/// Test `reserve_transfer_assets` with local asset reserve and local fee reserve. -/// -/// Transferring native asset (local reserve) to some `OTHER_PARA_ID` (no teleport trust). -/// Using native asset for fees as well. -/// -/// ```nocompile -/// Here (source) OTHER_PARA_ID (destination) -/// | `assets` reserve -/// | `fees` reserve -/// | -/// | 1. execute `TransferReserveAsset(assets_and_fees_batched_together)` -/// | \--> sends `ReserveAssetDeposited(both), ClearOrigin, BuyExecution(fees), DepositAsset` -/// \------------------------------------------> -/// ``` -#[test] -fn reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works() { - let beneficiary: MultiLocation = - Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( - beneficiary, - || { - assert_ok!(XcmPallet::reserve_transfer_assets( - RuntimeOrigin::signed(ALICE), - Box::new(Parachain(OTHER_PARA_ID).into()), - Box::new(beneficiary.into()), - Box::new((Here, SEND_AMOUNT).into()), - 0, - )); - }, - Unlimited, - ); -} - -/// Test `limited_reserve_transfer_assets` with local asset reserve and local fee reserve. -/// -/// Same as test above but with limited weight. -#[test] -fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserve_works() { - let beneficiary: MultiLocation = - Junction::AccountId32 { network: None, id: ALICE.into() }.into(); - let weight_limit = WeightLimit::Limited(Weight::from_parts(5000, 5000)); - let expected_weight_limit = weight_limit.clone(); - do_test_and_verify_reserve_transfer_assets_local_ar_local_fr( - beneficiary, - || { - assert_ok!(XcmPallet::limited_reserve_transfer_assets( - RuntimeOrigin::signed(ALICE), - Box::new(Parachain(OTHER_PARA_ID).into()), - Box::new(beneficiary.into()), - Box::new((Here, SEND_AMOUNT).into()), - 0, - weight_limit, - )); - }, - expected_weight_limit, - ); -} - /// Test `reserve_transfer_assets` with destination asset reserve and local fee reserve. /// /// Transferring foreign asset (`FOREIGN_ASSET_RESERVE_PARA_ID` reserve) to @@ -527,7 +524,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_local_fee_reserve_disal result, Err(DispatchError::Module(ModuleError { index: 4, - error: [15, 0, 0, 0], + error: [22, 0, 0, 0], message: Some("InvalidAssetUnsupportedReserve") })) ); @@ -803,7 +800,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_destination_fee_reserve result, Err(DispatchError::Module(ModuleError { index: 4, - error: [15, 0, 0, 0], + error: [22, 0, 0, 0], message: Some("InvalidAssetUnsupportedReserve") })) ); @@ -868,7 +865,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_disal result, Err(DispatchError::Module(ModuleError { index: 4, - error: [15, 0, 0, 0], + error: [22, 0, 0, 0], message: Some("InvalidAssetUnsupportedReserve") })) ); @@ -890,7 +887,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_remote_fee_reserve_disal /// Transferring native asset (local reserve) to `OTHER_PARA_ID` (no teleport trust). Using foreign /// asset (`USDC_RESERVE_PARA_ID` remote reserve) for fees. #[test] -fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve_works() { +fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve_disallowed() { let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); @@ -942,7 +939,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_remote_fee_reserve result, Err(DispatchError::Module(ModuleError { index: 4, - error: [15, 0, 0, 0], + error: [22, 0, 0, 0], message: Some("InvalidAssetUnsupportedReserve") })) ); @@ -1313,7 +1310,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor /// Transferring foreign asset (reserve on `FOREIGN_ASSET_RESERVE_PARA_ID`) to `USDT_PARA_ID`. /// Using teleport-trusted USDT for fees. #[test] -fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() { +fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_disallowed() { let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); @@ -1359,7 +1356,7 @@ fn reserve_transfer_assets_with_remote_asset_reserve_and_teleported_fee_works() result, Err(DispatchError::Module(ModuleError { index: 4, - error: [15, 0, 0, 0], + error: [22, 0, 0, 0], message: Some("InvalidAssetUnsupportedReserve") })) ); From 560d78814291a2738f1ecb3893e7e527983d90f9 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 25 Oct 2023 16:20:59 +0300 Subject: [PATCH 061/124] fix pallet-xcm tests --- .../pallet-xcm/src/tests/assets_transfer.rs | 299 ++++++++---------- 1 file changed, 137 insertions(+), 162 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index 2f85fac7f840..d3df75708213 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -162,11 +162,11 @@ fn reserve_transfer_assets_with_paid_router_works() { INITIAL_BALANCE + xcm_router_fee_amount ); - let sent_xcm = sent_xcm(); + let dest_para: MultiLocation = Parachain(paid_para_id).into(); assert_eq!( - sent_xcm, + sent_xcm(), vec![( - Parachain(paid_para_id).into(), + dest_para, Xcm(vec![ ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), ClearOrigin, @@ -175,7 +175,6 @@ fn reserve_transfer_assets_with_paid_router_works() { ]), )] ); - let inner_message = sent_xcm.into_iter().next().unwrap().1; let mut last_events = last_events(5).into_iter(); assert_eq!( last_events.next().unwrap(), @@ -191,38 +190,13 @@ fn reserve_transfer_assets_with_paid_router_works() { fees: Para3000PaymentMultiAssets::get(), }) ); - assert_eq!( + assert!(matches!( last_events.next().unwrap(), - RuntimeEvent::XcmPallet(crate::Event::Sent { - origin: dest, - destination: Parachain(paid_para_id).into(), - message: inner_message, - message_id: [ - 55, 64, 13, 96, 90, 32, 133, 17, 152, 138, 167, 156, 159, 194, 154, 181, 130, - 98, 75, 249, 162, 253, 58, 246, 44, 117, 152, 11, 57, 102, 238, 131 - ], - }) - ); + RuntimeEvent::XcmPallet(crate::Event::Sent { .. }) + )); }); } -// For reserve-based transfers, we want to support: -// - non-fee assets reserve: -// - local reserve -// - destination reserve -// - remote reserve -// - fee assets: -// - reserve-transferred with reserve: -// - local reserve -// - destination reserve -// - remote reserve -// - teleported -// -// Bringing unique scenarios total to 3*4 = 12. So, following reserve-transfer testz try to cover -// the happy-case for each of these 12 scenarios. -// -// TODO: also add negative testz for testing various error conditions. - fn set_up_foreign_asset( reserve_para_id: u32, inner_junction: Option, @@ -297,6 +271,7 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv let weight_limit = WeightLimit::Limited(Weight::from_parts(5000, 5000)); let expected_weight_limit = weight_limit.clone(); let expected_beneficiary = beneficiary; + let dest: MultiLocation = Parachain(OTHER_PARA_ID).into(); new_test_ext_with_balances(balances).execute_with(|| { let weight = BaseXcmWeight::get() * 2; @@ -304,7 +279,7 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv // call extrinsic assert_ok!(XcmPallet::limited_reserve_transfer_assets( RuntimeOrigin::signed(ALICE), - Box::new(Parachain(OTHER_PARA_ID).into()), + Box::new(dest.into()), Box::new(beneficiary.into()), Box::new((Here, SEND_AMOUNT).into()), 0, @@ -315,11 +290,10 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv // Destination account (parachain account) has amount let para_acc: AccountId = ParaId::from(OTHER_PARA_ID).into_account_truncating(); assert_eq!(Balances::free_balance(para_acc), INITIAL_BALANCE + SEND_AMOUNT); - let sent_xcm = sent_xcm(); assert_eq!( - sent_xcm, + sent_xcm(), vec![( - Parachain(OTHER_PARA_ID).into(), + dest, Xcm(vec![ ReserveAssetDeposited((Parent, SEND_AMOUNT).into()), ClearOrigin, @@ -331,7 +305,6 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv ]), )] ); - let inner_message = sent_xcm.into_iter().next().unwrap().1; let mut last_events = last_events(3).into_iter(); assert_eq!( last_events.next().unwrap(), @@ -344,18 +317,10 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv fees: MultiAssets::new(), }) ); - assert_eq!( + assert!(matches!( last_events.next().unwrap(), - RuntimeEvent::XcmPallet(crate::Event::Sent { - origin: expected_beneficiary, - destination: Parachain(OTHER_PARA_ID).into(), - message: inner_message, - message_id: [ - 53, 1, 255, 66, 147, 147, 39, 116, 107, 79, 145, 26, 237, 73, 0, 165, 70, 43, - 122, 224, 230, 68, 62, 15, 200, 250, 105, 14, 100, 65, 100, 204 - ], - }) - ); + RuntimeEvent::XcmPallet(crate::Event::Sent { .. }) + )); }); } @@ -380,6 +345,7 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_works() { + let weight = BaseXcmWeight::get() * 4; let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); @@ -422,10 +388,12 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ fee_index as u32, Unlimited, )); - assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) - )); + + let mut last_events = last_events(3).into_iter(); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) + ); // Alice spent (transferred) amount assert_eq!( @@ -446,34 +414,30 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_ // Verify sent XCM program assert_eq!( sent_xcm(), - vec![ - ( - // first message is to prefund fees on `dest` - dest, - // fees are being sent through local-reserve transfer because fee reserve is - // local chain - Xcm(vec![ - ReserveAssetDeposited((Parent, FEE_AMOUNT).into()), - ClearOrigin, - buy_limited_execution((Parent, FEE_AMOUNT), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, - ]) - ), - ( - // second message is to transfer/deposit foreign assets on `dest` while paying - // using prefunded (transferred above) fees - // (dest is reserve location for `expected_asset`) - dest, - Xcm(vec![ - WithdrawAsset(expected_asset.into()), - ClearOrigin, - WithdrawAsset(expected_fee.clone().into()), - buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(2).into(), beneficiary }, - ]) - ) - ] + vec![( + dest, + // `fees` are being sent through local-reserve transfer because fee reserve is + // local chain; `assets` are burned on source and withdrawn from SA here + Xcm(vec![ + ReserveAssetDeposited((Parent, FEE_AMOUNT).into()), + WithdrawAsset(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(2).into(), beneficiary }, + ]) + )] ); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::FeesPaid { + paying: beneficiary, + fees: MultiAssets::new(), + }) + ); + assert!(matches!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Sent { .. }) + )); }); } @@ -600,9 +564,22 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ fee_index as u32, Unlimited, )); + let weight = BaseXcmWeight::get() * 4; + let mut last_events = last_events(3).into_iter(); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) + ); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::FeesPaid { + paying: beneficiary, + fees: MultiAssets::new(), + }) + ); assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Sent { .. }) )); // Alice spent (fees) amount @@ -623,34 +600,20 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ // Verify sent XCM program assert_eq!( sent_xcm(), - vec![ - ( - // first message is to prefund fees on `dest` - dest, + vec![( + dest, + Xcm(vec![ // fees are being sent through destination-reserve transfer because fee reserve // is destination chain - Xcm(vec![ - WithdrawAsset(expected_fee.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee.clone(), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, - ]) - ), - ( - // second message is to transfer/deposit (native) asset on `dest` while paying - // using prefunded (transferred above) fees - dest, + WithdrawAsset(expected_fee.clone().into()), // transfer is through local-reserve transfer because `assets` (native asset) // have local reserve - Xcm(vec![ - ReserveAssetDeposited(expected_asset.into()), - ClearOrigin, - WithdrawAsset(expected_fee.clone().into()), - buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(2).into(), beneficiary }, - ]) - ) - ] + ReserveAssetDeposited(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(2).into(), beneficiary }, + ]) + )] ); }); } @@ -705,9 +668,23 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re fee_index, Unlimited, )); + + let weight = BaseXcmWeight::get() * 3; + let mut last_events = last_events(3).into_iter(); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) + ); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::FeesPaid { + paying: beneficiary, + fees: MultiAssets::new(), + }) + ); assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Sent { .. }) )); // Alice spent (transferred) amount @@ -1121,9 +1098,22 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { fee_index as u32, Unlimited, )); + let weight = BaseXcmWeight::get() * 4; + let mut last_events = last_events(3).into_iter(); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) + ); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::FeesPaid { + paying: beneficiary, + fees: MultiAssets::new(), + }) + ); assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Sent { .. }) )); // Alice spent (fees) amount assert_eq!( @@ -1143,33 +1133,19 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { // Verify sent XCM program assert_eq!( sent_xcm(), - vec![ - ( - // first message is to prefund fees on `dest` - dest, + vec![( + dest, + Xcm(vec![ // fees are teleported to destination chain - Xcm(vec![ - ReceiveTeleportedAsset(expected_fee.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee.clone(), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, - ]) - ), - ( - // second message is to transfer/deposit (native) asset on `dest` while paying - // using prefunded (transferred above) fees - dest, - // transfer is through local-reserve transfer because `assets` (native asset) - // have local reserve - Xcm(vec![ - ReserveAssetDeposited(expected_asset.into()), - ClearOrigin, - WithdrawAsset(expected_fee.clone().into()), - buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(2).into(), beneficiary }, - ]) - ) - ] + ReceiveTeleportedAsset(expected_fee.clone().into()), + // transfer is through local-reserve transfer because `assets` (native + // asset) have local reserve + ReserveAssetDeposited(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(2).into(), beneficiary }, + ]) + )] ); }); } @@ -1240,9 +1216,22 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor fee_index as u32, Unlimited, )); + let weight = BaseXcmWeight::get() * 5; + let mut last_events = last_events(3).into_iter(); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(weight) }) + ); + assert_eq!( + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::FeesPaid { + paying: beneficiary, + fees: MultiAssets::new(), + }) + ); assert!(matches!( - last_event(), - RuntimeEvent::XcmPallet(crate::Event::Attempted { outcome: Outcome::Complete(_) }) + last_events.next().unwrap(), + RuntimeEvent::XcmPallet(crate::Event::Sent { .. }) )); // Alice native asset untouched assert_eq!(Balances::free_balance(ALICE), INITIAL_BALANCE); @@ -1275,32 +1264,18 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor // Verify sent XCM program assert_eq!( sent_xcm(), - vec![ - ( - // first message is to prefund fees on `dest` - dest, + vec![( + dest, + Xcm(vec![ // fees are teleported to destination chain - Xcm(vec![ - ReceiveTeleportedAsset(expected_fee.clone().into()), - ClearOrigin, - buy_limited_execution(expected_fee.clone(), Unlimited), - DepositAsset { assets: AllCounted(1).into(), beneficiary }, - ]) - ), - ( - // second message is to transfer/deposit foreign assets on `dest` while paying - // using prefunded (transferred above) fees (USDT) - // (dest is reserve location for `expected_asset`) - dest, - Xcm(vec![ - WithdrawAsset(expected_asset.into()), - ClearOrigin, - WithdrawAsset(expected_fee.clone().into()), - buy_limited_execution(expected_fee, Unlimited), - DepositAsset { assets: AllCounted(2).into(), beneficiary }, - ]) - ) - ] + ReceiveTeleportedAsset(expected_fee.clone().into()), + // assets are withdrawn from origin's local SA + WithdrawAsset(expected_asset.into()), + ClearOrigin, + buy_limited_execution(expected_fee, Unlimited), + DepositAsset { assets: AllCounted(2).into(), beneficiary }, + ]) + )] ); }); } From 3bc2d73d3af3f9d1f40d158c60ef627b04bb7d12 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 25 Oct 2023 17:07:00 +0300 Subject: [PATCH 062/124] fix AHs tests --- .../src/tests/reserve_transfer.rs | 2 +- .../asset-hub-rococo/src/tests/teleport.rs | 12 ++--- .../src/tests/reserve_transfer.rs | 10 ++-- .../asset-hub-westend/src/tests/teleport.rs | 12 ++--- .../emulated/common/src/macros.rs | 2 +- .../runtimes/assets/test-utils/src/lib.rs | 5 -- .../assets/test-utils/src/test_cases.rs | 4 +- .../test-utils/src/test_cases_over_bridge.rs | 3 +- .../assets/test-utils/src/xcm_helpers.rs | 50 +++---------------- 9 files changed, 31 insertions(+), 69 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index 0a55a609ecce..073c93ec254a 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -176,7 +176,7 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { let sender_balance_after = test.sender.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::reserve_transfer_localreserve_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs index e74e97dc3391..4b2ea0e160cb 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs @@ -174,7 +174,7 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Rococo::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -221,7 +221,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -262,7 +262,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -295,7 +295,7 @@ fn teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Rococo::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -342,7 +342,7 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -380,7 +380,7 @@ fn teleport_native_assets_from_system_para_to_relay_fails() { test.assert(); let delivery_fees = AssetHubRococo::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs index bc18daf35eb7..c7a25dde78d3 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -175,9 +175,13 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { let sender_balance_after = test.sender.balance; let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::reserve_transfer_localreserve_assets_delivery_fees::< - ::XcmSender, - >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + xcm_helpers::transfer_assets_delivery_fees::<::XcmSender>( + test.args.assets.clone(), + 0, + test.args.weight_limit, + test.args.beneficiary, + test.args.dest, + ) }); assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs index 7423f6f60eb1..4fe0062dafcd 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs @@ -176,7 +176,7 @@ fn limited_teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Westend::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -223,7 +223,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -264,7 +264,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -297,7 +297,7 @@ fn teleport_native_assets_from_relay_to_system_para_works() { test.assert(); let delivery_fees = Westend::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -341,7 +341,7 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() { test.assert(); let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); @@ -382,7 +382,7 @@ fn teleport_native_assets_from_system_para_to_relay_fails() { test.assert(); let delivery_fees = AssetHubWestend::execute_with(|| { - xcm_helpers::teleport_assets_delivery_fees::< + xcm_helpers::transfer_assets_delivery_fees::< ::XcmSender, >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); diff --git a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs index 52780a5c4a75..a65b2057afda 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/macros.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/macros.rs @@ -90,7 +90,7 @@ macro_rules! test_parachain_is_trusted_teleporter { let para_receiver_balance_after = <$receiver_para as $crate::Chain>::account_data_of(receiver.clone()).free; let delivery_fees = <$sender_para>::execute_with(|| { - asset_test_utils::xcm_helpers::teleport_assets_delivery_fees::< + asset_test_utils::xcm_helpers::transfer_assets_delivery_fees::< <$sender_xcm_config as xcm_executor::Config>::XcmSender, >($assets.clone(), fee_asset_item, weight_limit.clone(), beneficiary, para_destination) }); diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs index 2a1e72dc002f..872ad06ddd5b 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs @@ -67,11 +67,6 @@ pub(crate) fn assert_matches_reserve_asset_deposited_instructions Err(ProcessMessageError::BadFormat), }) .expect("expected instruction ClearOrigin") - .match_next_inst(|instr| match instr { - SetFeesMode { .. } => Ok(()), - _ => Err(ProcessMessageError::BadFormat), - }) - .expect("expected instruction SetFeesMode") .match_next_inst(|instr| match instr { BuyExecution { .. } => Ok(()), _ => Err(ProcessMessageError::BadFormat), diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 97f68269c81a..2900ec6f308b 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -181,7 +181,7 @@ pub fn teleports_for_native_asset_works< // Mint funds into account to ensure it has enough balance to pay delivery fees let delivery_fees = - xcm_helpers::teleport_assets_delivery_fees::( + xcm_helpers::transfer_assets_delivery_fees::( (native_asset_id, native_asset_to_teleport_away.into()).into(), 0, Unlimited, @@ -560,7 +560,7 @@ pub fn teleports_for_foreign_assets_works< // Make sure the target account has enough native asset to pay for delivery fees let delivery_fees = - xcm_helpers::teleport_assets_delivery_fees::( + xcm_helpers::transfer_assets_delivery_fees::( (foreign_asset_id_multilocation, asset_to_teleport_away).into(), 0, Unlimited, diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index 547d4dfcec7c..16ad63532ab2 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -170,7 +170,7 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< // Make sure sender has enough funds for paying delivery fees // TODO: Get this fee via weighing the corresponding message - let delivery_fees = 1324173226; + let delivery_fees = 1324039894; >::mint_into(&alice_account, delivery_fees.into()) .unwrap(); @@ -434,7 +434,6 @@ pub fn receive_reserve_asset_deposited_from_different_consensus_works< DescendOrigin(descend_origin), ReserveAssetDeposited(expected_assets.clone()), ClearOrigin, - SetFeesMode { jit_withdraw: false }, BuyExecution { fees: MultiAsset { id: Concrete(foreign_asset_id_multilocation), diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs b/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs index ca92c469df80..0aebe38fef53 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/xcm_helpers.rs @@ -18,10 +18,11 @@ use xcm::latest::prelude::*; -/// Returns the delivery fees amount for pallet xcm's `teleport_assets` extrinsic. -/// Because it returns only a `u128`, it assumes delivery fees are only paid in one asset and that -/// asset is known. -pub fn teleport_assets_delivery_fees( +/// Returns the delivery fees amount for pallet xcm's `teleport_assets` and +/// `reserve_transfer_assets` extrinsics. +/// Because it returns only a `u128`, it assumes delivery fees are only paid +/// in one asset and that asset is known. +pub fn transfer_assets_delivery_fees( assets: MultiAssets, fee_asset_item: u32, weight_limit: WeightLimit, @@ -32,25 +33,6 @@ pub fn teleport_assets_delivery_fees( get_fungible_delivery_fees::(destination, message) } -/// Returns the delivery fees amount for pallet xcm's `reserve_transfer_assets` extrinsics. -/// Because it returns only a `u128`, it assumes delivery fees are only paid in one asset and that -/// asset is known. -pub fn reserve_transfer_localreserve_assets_delivery_fees( - assets: MultiAssets, - fee_asset_item: u32, - weight_limit: WeightLimit, - beneficiary: MultiLocation, - destination: MultiLocation, -) -> u128 { - let message = reserve_transfer_localreserve_assets_dummy_message( - assets, - fee_asset_item, - weight_limit, - beneficiary, - ); - get_fungible_delivery_fees::(destination, message) -} - /// Returns the delivery fees amount for a query response as a result of the execution /// of a `ExpectError` instruction with no error. pub fn query_response_delivery_fees(querier: MultiLocation) -> u128 { @@ -94,6 +76,7 @@ pub fn pay_over_xcm_delivery_fees( /// Approximates the actual message sent by the teleport extrinsic. /// The assets are not reanchored and the topic is a dummy one. /// However, it should have the same encoded size, which is what matters for delivery fees. +/// Also has same encoded size as the one created by the reserve transfer assets extrinsic. fn teleport_assets_dummy_message( assets: MultiAssets, fee_asset_item: u32, @@ -101,27 +84,8 @@ fn teleport_assets_dummy_message( beneficiary: MultiLocation, ) -> Xcm<()> { Xcm(vec![ - ReceiveTeleportedAsset(assets.clone()), - ClearOrigin, - BuyExecution { fees: assets.get(fee_asset_item as usize).unwrap().clone(), weight_limit }, - DepositAsset { assets: Wild(AllCounted(assets.len() as u32)), beneficiary }, - SetTopic([0u8; 32]), // Dummy topic - ]) -} - -/// Approximates the actual message sent by the reserve-transfer of local reserve asset extrinsic. -/// The assets are not reanchored and the topic is a dummy one. -/// However, it should have the same encoded size, which is what matters for delivery fees. -fn reserve_transfer_localreserve_assets_dummy_message( - assets: MultiAssets, - fee_asset_item: u32, - weight_limit: WeightLimit, - beneficiary: MultiLocation, -) -> Xcm<()> { - Xcm(vec![ - ReserveAssetDeposited(assets.clone()), + ReceiveTeleportedAsset(assets.clone()), // Same encoded size as `ReserveAssetDeposited` ClearOrigin, - SetFeesMode { jit_withdraw: false }, BuyExecution { fees: assets.get(fee_asset_item as usize).unwrap().clone(), weight_limit }, DepositAsset { assets: Wild(AllCounted(assets.len() as u32)), beneficiary }, SetTopic([0u8; 32]), // Dummy topic From 12177238a39127638624ba978b4a2be939e5f4e2 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 26 Oct 2023 05:59:51 +0200 Subject: [PATCH 063/124] attempts to fix xcm config --- .../runtimes/assets/asset-hub-rococo/src/xcm_config.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index ee294dac2c96..d7f2b5261bef 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -903,6 +903,11 @@ pub mod bridging { AssetHubRococo::get() ); + pub EtherFromEthereum: (MultiAssetFilter, MultiLocation) = ( + Wild(AllOf { fun: WildFungible, id: Concrete(EthereumLocation::get()) }), + EthereumLocation::get() + ); + /// Set up exporters configuration. /// `Option` represents static "base fee" which is used for total delivery fee calculation. pub BridgeTable: sp_std::vec::Vec = sp_std::vec![ @@ -962,6 +967,7 @@ pub mod bridging { ( // allow receive ROC from AssetHubRococo xcm_builder::Case, + xcm_builder::Case, // and nothing else ), >; From 5e480ddc18267dcc41aba82b6ab27907d30cc154 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 26 Oct 2023 15:36:35 +0200 Subject: [PATCH 064/124] fixes send token --- .../assets/asset-hub-rococo/src/xcm_config.rs | 23 +++++++++------- .../runtimes/assets/common/src/matching.rs | 27 ++++++++++++++++--- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 8 +++--- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index d7f2b5261bef..c124d49e8586 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -574,6 +574,7 @@ impl xcm_executor::Config for XcmConfig { type IsReserve = ( bridging::to_wococo::IsTrustedBridgedReserveLocationForConcreteAsset, bridging::to_rococo::IsTrustedBridgedReserveLocationForConcreteAsset, + bridging::to_rococo::IsTrustedBridgedReserveLocationForForeignAsset, ); type IsTeleporter = TrustedTeleporters; type UniversalLocation = UniversalLocation; @@ -678,7 +679,7 @@ impl pallet_xcm::Config for Runtime { type XcmReserveTransferFilter = ( LocationWithAssetFilters, bridging::to_rococo::AllowedReserveTransferAssets, - bridging::to_rococo::AllowedReserveTransferAssetsEthereum, + //bridging::to_rococo::AllowedReserveTransferAssetsEthereum, bridging::to_wococo::AllowedReserveTransferAssets, ); @@ -872,6 +873,7 @@ pub mod bridging { pub mod to_rococo { use super::*; + use assets_common::matching::FromNetwork; parameter_types! { pub SiblingBridgeHubWithBridgeHubRococoInstance: MultiLocation = MultiLocation::new( @@ -903,10 +905,10 @@ pub mod bridging { AssetHubRococo::get() ); - pub EtherFromEthereum: (MultiAssetFilter, MultiLocation) = ( - Wild(AllOf { fun: WildFungible, id: Concrete(EthereumLocation::get()) }), - EthereumLocation::get() - ); + /*pub EtherFromEthereum: (MultiAssetFilter, MultiLocation) = ( + EthereumGatewayLocation::get().into(), + EthereumGatewayLocation::get() + );*/ /// Set up exporters configuration. /// `Option` represents static "base fee" which is used for total delivery fee calculation. @@ -941,14 +943,14 @@ pub mod bridging { ]; pub AllowedReserveTransferAssetsToEthereum: sp_std::vec::Vec = sp_std::vec![ - Wild(AllOf { fun: WildFungible, id: Concrete(EthereumGatewayLocation::get()) }), // TODO check + Wild(AllOf { fun: WildFungible, id: Concrete(EthereumGatewayLocation::get()) }), ]; /// Universal aliases pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( sp_std::vec![ (SiblingBridgeHubWithBridgeHubRococoInstance::get(), GlobalConsensus(RococoNetwork::get())), - (SiblingBridgeHub::get(), GlobalConsensus(EthereumNetwork::get())), // TODO check + (SiblingBridgeHub::get(), GlobalConsensus(EthereumNetwork::get())), ] ); } @@ -967,21 +969,24 @@ pub mod bridging { ( // allow receive ROC from AssetHubRococo xcm_builder::Case, - xcm_builder::Case, // and nothing else ), >; + pub type IsTrustedBridgedReserveLocationForForeignAsset = + matching::IsForeignConcreteAsset>; + /// Allows to reserve transfer assets to `AssetHubRococo`. pub type AllowedReserveTransferAssets = LocationWithAssetFilters< Equals, AllowedReserveTransferAssetsToAssetHubRococo, >; + /* pub type AllowedReserveTransferAssetsEthereum = LocationWithAssetFilters< StartsWithExplicitGlobalConsensus, // TODO check AllowedReserveTransferAssetsToEthereum, - >; + >;*/ impl Contains for ToRococoXcmRouter { fn contains(call: &RuntimeCall) -> bool { diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index 914972812521..ba0012b20cc1 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -46,18 +46,37 @@ impl> ContainsPair fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool { // `a` needs to be from `b` at least if !a.starts_with(b) { - return false + return false; } // here we check if sibling match a { - MultiLocation { parents: 1, interior } => - matches!(interior.first(), Some(Parachain(sibling_para_id)) if sibling_para_id.ne(&u32::from(SelfParaId::get()))), + MultiLocation { parents: 1, interior } => { + matches!(interior.first(), Some(Parachain(sibling_para_id)) if sibling_para_id.ne(&u32::from(SelfParaId::get()))) + }, _ => false, } } } +pub struct FromNetwork(sp_std::marker::PhantomData); +impl> ContainsPair + for FromNetwork +{ + fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool { + // `a` needs to be from `b` at least + if !a.starts_with(b) { + return false; + } + + match a { + MultiLocation { parents: 2, interior } => { + matches!(interior.first(), Some(GlobalConsensus(network)) if *network == SelfNetworkId::get()) + }, + _ => false, + } + } +} /// Adapter verifies if it is allowed to receive `MultiAsset` from `MultiLocation`. /// /// Note: `MultiLocation` has to be from a different global consensus. @@ -87,7 +106,7 @@ impl< "IsTrustedBridgedReserveLocationForConcreteAsset origin: {:?} is not remote to the universal_source: {:?}", origin, universal_source ); - return false + return false; }, }; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 9c52962b4a4d..a257042233d9 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -480,16 +480,14 @@ impl pallet_utility::Config for Runtime { parameter_types! { /// Amount of weight that can be spent per block to service messages. - pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000); - pub const MessageQueueHeapSize: u32 = 65_536; - pub const MessageQueueMaxStale: u32 = 16; + pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; } impl pallet_message_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Size = u32; - type HeapSize = MessageQueueHeapSize; - type MaxStale = MessageQueueMaxStale; + type HeapSize = ConstU32<{ 64 * 1024 }>; + type MaxStale = ConstU32<8>; type ServiceWeight = MessageQueueServiceWeight; type MessageProcessor = EthereumOutboundQueue; type QueueChangeHandler = (); From bd60203a1a1ac1384d150c8cf20cbc200aa47dac Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 26 Oct 2023 18:12:41 +0300 Subject: [PATCH 065/124] remove unused SetFeesMode instruction --- polkadot/xcm/pallet-xcm/src/lib.rs | 12 ++++-------- .../xcm/pallet-xcm/src/tests/assets_transfer.rs | 14 +++++++------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index f97b6135d484..8d9bc7373c6c 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1485,11 +1485,9 @@ impl Pallet { .unwrap_or_default(); let local_execute_xcm = Xcm( - // JIT withdraw fees for local execution - [SetFeesMode { jit_withdraw: true }] + // run any necessary local prefund fees instructions + prefund_local_xcm .into_iter() - // run any necessary local prefund fees instructions - .chain(prefund_local_xcm.into_iter()) // move `assets` to `dest`s local sovereign account .chain([TransferAsset { assets, beneficiary: dest }].into_iter()) .collect(), @@ -1566,11 +1564,9 @@ impl Pallet { .unwrap_or_default(); let local_execute_xcm = Xcm( - // JIT withdraw fees for local execution - [SetFeesMode { jit_withdraw: true }] + // run any necessary local prefund fees instructions + prefund_local_xcm .into_iter() - // run any necessary local prefund fees instructions - .chain(prefund_local_xcm.into_iter()) // move `assets` to `dest`s local sovereign account .chain( [ diff --git a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs index d3df75708213..7a9b7be8dff2 100644 --- a/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs +++ b/polkadot/xcm/pallet-xcm/src/tests/assets_transfer.rs @@ -134,7 +134,7 @@ fn reserve_transfer_assets_with_paid_router_works() { ]; new_test_ext_with_balances(balances).execute_with(|| { let xcm_router_fee_amount = Para3000PaymentAmount::get(); - let weight = BaseXcmWeight::get() * 2; + let weight = BaseXcmWeight::get(); let dest: MultiLocation = Junction::AccountId32 { network: None, id: user_account.clone().into() }.into(); assert_eq!(Balances::total_balance(&user_account), INITIAL_BALANCE); @@ -274,7 +274,7 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv let dest: MultiLocation = Parachain(OTHER_PARA_ID).into(); new_test_ext_with_balances(balances).execute_with(|| { - let weight = BaseXcmWeight::get() * 2; + let weight = BaseXcmWeight::get(); assert_eq!(Balances::total_balance(&ALICE), INITIAL_BALANCE); // call extrinsic assert_ok!(XcmPallet::limited_reserve_transfer_assets( @@ -345,7 +345,7 @@ fn limited_reserve_transfer_assets_with_local_asset_reserve_and_local_fee_reserv /// is increased. Verifies the correct message is sent and event is emitted. #[test] fn reserve_transfer_assets_with_destination_asset_reserve_and_local_fee_reserve_works() { - let weight = BaseXcmWeight::get() * 4; + let weight = BaseXcmWeight::get() * 3; let balances = vec![(ALICE, INITIAL_BALANCE)]; let beneficiary: MultiLocation = Junction::AccountId32 { network: None, id: ALICE.into() }.into(); @@ -564,7 +564,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_destination_fee_reserve_ fee_index as u32, Unlimited, )); - let weight = BaseXcmWeight::get() * 4; + let weight = BaseXcmWeight::get() * 3; let mut last_events = last_events(3).into_iter(); assert_eq!( last_events.next().unwrap(), @@ -669,7 +669,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_destination_fee_re Unlimited, )); - let weight = BaseXcmWeight::get() * 3; + let weight = BaseXcmWeight::get() * 2; let mut last_events = last_events(3).into_iter(); assert_eq!( last_events.next().unwrap(), @@ -1098,7 +1098,7 @@ fn reserve_transfer_assets_with_local_asset_reserve_and_teleported_fee_works() { fee_index as u32, Unlimited, )); - let weight = BaseXcmWeight::get() * 4; + let weight = BaseXcmWeight::get() * 3; let mut last_events = last_events(3).into_iter(); assert_eq!( last_events.next().unwrap(), @@ -1216,7 +1216,7 @@ fn reserve_transfer_assets_with_destination_asset_reserve_and_teleported_fee_wor fee_index as u32, Unlimited, )); - let weight = BaseXcmWeight::get() * 5; + let weight = BaseXcmWeight::get() * 4; let mut last_events = last_events(3).into_iter(); assert_eq!( last_events.next().unwrap(), From 7b658d648a65395407568a5dda7e35ca95330d34 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Fri, 27 Oct 2023 09:44:29 +0200 Subject: [PATCH 066/124] add missing import --- .../runtimes/assets/asset-hub-rococo/src/xcm_config.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 30e48cdd1de6..014dd1cbfb10 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -889,6 +889,7 @@ pub mod bridging { pub mod to_rococo { use super::*; + use assets_common::matching::FromNetwork; parameter_types! { pub SiblingBridgeHubWithBridgeHubRococoInstance: MultiLocation = MultiLocation::new( From bae3b6257cb66c1e2b909f489bd8bc924ed2604b Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Fri, 27 Oct 2023 09:56:24 +0200 Subject: [PATCH 067/124] allows all networks --- cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 5b548017b8b5..bbbecbbbe032 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -875,7 +875,7 @@ impl pallet_xcm_bridge_hub_router::Config for Runtime type WeightInfo = weights::pallet_xcm_bridge_hub_router_to_rococo::WeightInfo; type UniversalLocation = xcm_config::UniversalLocation; - type BridgedNetworkId = xcm_config::bridging::to_rococo::RococoNetwork; + type BridgedNetworkId = (); type Bridges = xcm_config::bridging::NetworkExportTable; #[cfg(not(feature = "runtime-benchmarks"))] From 4f5d693317234a9281d9a1789caffb4aa94ccef9 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Fri, 27 Oct 2023 11:07:03 +0200 Subject: [PATCH 068/124] fmt --- cumulus/pallets/dmp-queue/src/lib.rs | 21 +- .../assets/asset-hub-rococo/src/lib.rs | 149 ++++--- .../assets/asset-hub-rococo/src/xcm_config.rs | 362 +++++++++--------- .../runtimes/assets/common/src/matching.rs | 6 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 3 +- .../bridge-hub-rococo/src/xcm_config.rs | 35 +- 6 files changed, 288 insertions(+), 288 deletions(-) diff --git a/cumulus/pallets/dmp-queue/src/lib.rs b/cumulus/pallets/dmp-queue/src/lib.rs index 9ec84ca7fe7b..740722b05699 100644 --- a/cumulus/pallets/dmp-queue/src/lib.rs +++ b/cumulus/pallets/dmp-queue/src/lib.rs @@ -56,8 +56,9 @@ impl Default for ConfigData { Self { // For beacon checkpoint to work require a bigger default max_individual: Weight::from_parts( - 20u64 * 10u64 * WEIGHT_REF_TIME_PER_MILLIS, // 200 ms of execution time maximum by default - 10u64 * DEFAULT_POV_SIZE, // 640 KB of proof size by default + 20u64 * 10u64 * WEIGHT_REF_TIME_PER_MILLIS, /* 200 ms of execution time maximum + * by default */ + 10u64 * DEFAULT_POV_SIZE, // 640 KB of proof size by default ), } } @@ -231,7 +232,7 @@ pub mod pallet { if *messages_processed >= MAX_MESSAGES_PER_BLOCK { // Exceeded block message limit - put the remaining messages back and bail Pages::::insert(page_index.begin_used, &page[i..]); - return used; + return used } *messages_processed += 1; match Self::try_service_message(limit.saturating_sub(used), sent_at, &data[..]) @@ -240,7 +241,7 @@ pub mod pallet { Err(..) => { // Too much weight needed - put the remaining messages back and bail Pages::::insert(page_index.begin_used, &page[i..]); - return used; + return used }, } } @@ -289,9 +290,8 @@ pub mod pallet { Weight::zero(), ); match outcome { - Outcome::Error(XcmError::WeightLimitReached(required_weight)) => { - Err(ServiceMessageError { message_hash, message_id, required_weight }) - }, + Outcome::Error(XcmError::WeightLimitReached(required_weight)) => + Err(ServiceMessageError { message_hash, message_id, required_weight }), outcome => { let weight_used = outcome.weight_used(); Self::deposit_event(Event::ExecutedDownward { @@ -372,7 +372,7 @@ pub mod pallet { // Not needed for control flow, but only to ensure that the // compiler understands that we won't attempt to re-use `data` // later. - continue; + continue } else { // not overweight. stop executing inline and enqueue normally // from here on. @@ -519,9 +519,8 @@ mod tests { ) -> Outcome { let message = prepared.0; let o = match (message.0.len(), &message.0.first()) { - (1, Some(Transact { require_weight_at_most, .. })) => { - Outcome::Complete(*require_weight_at_most) - }, + (1, Some(Transact { require_weight_at_most, .. })) => + Outcome::Complete(*require_weight_at_most), // use 1000 to decide that it's not supported. _ => Outcome::Incomplete(Weight::from_parts(1, 1), XcmError::Unimplemented), }; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 308b5b219da1..aba226b3baab 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -491,98 +491,97 @@ impl InstanceFilter for ProxyType { ProxyType::Any => true, ProxyType::NonTransfer => !matches!( c, - RuntimeCall::Balances { .. } - | RuntimeCall::Assets { .. } - | RuntimeCall::NftFractionalization { .. } - | RuntimeCall::Nfts { .. } - | RuntimeCall::Uniques { .. } + RuntimeCall::Balances { .. } | + RuntimeCall::Assets { .. } | + RuntimeCall::NftFractionalization { .. } | + RuntimeCall::Nfts { .. } | + RuntimeCall::Uniques { .. } ), ProxyType::CancelProxy => matches!( c, - RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), ProxyType::Assets => { matches!( c, - RuntimeCall::Assets { .. } - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } - | RuntimeCall::NftFractionalization { .. } - | RuntimeCall::Nfts { .. } - | RuntimeCall::Uniques { .. } + RuntimeCall::Assets { .. } | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } | + RuntimeCall::NftFractionalization { .. } | + RuntimeCall::Nfts { .. } | RuntimeCall::Uniques { .. } ) }, ProxyType::AssetOwner => matches!( c, - RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::create { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::destroy { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::transfer_ownership { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::set_team { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::set_metadata { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::set_attribute { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::set_collection_metadata { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::clear_metadata { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::clear_attribute { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::clear_collection_metadata { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::set_collection_max_supply { .. }) - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::Assets(TrustBackedAssetsCall::create { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::start_destroy { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::destroy_accounts { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::destroy_approvals { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::finish_destroy { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::transfer_ownership { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::set_team { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::set_metadata { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::clear_metadata { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::set_min_balance { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::create { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::destroy { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::redeposit { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::transfer_ownership { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_team { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_collection_max_supply { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::lock_collection { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::create { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::destroy { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::transfer_ownership { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::set_team { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::set_metadata { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::set_attribute { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::set_collection_metadata { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::clear_metadata { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::clear_attribute { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::clear_collection_metadata { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::set_collection_max_supply { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), ProxyType::AssetManager => matches!( c, - RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) - | RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) - | RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::mint { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::burn { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::freeze { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::thaw { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::freeze_collection { .. }) - | RuntimeCall::Uniques(pallet_uniques::Call::thaw_collection { .. }) - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::Assets(TrustBackedAssetsCall::mint { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::burn { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::freeze { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::block { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::thaw { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::freeze_asset { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::thaw_asset { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::touch_other { .. }) | + RuntimeCall::Assets(TrustBackedAssetsCall::refund_other { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::force_mint { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::update_mint_settings { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::mint_pre_signed { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_attributes_pre_signed { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::lock_item_transfer { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::unlock_item_transfer { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::lock_item_properties { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_metadata { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::clear_metadata { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::set_collection_metadata { .. }) | + RuntimeCall::Nfts(pallet_nfts::Call::clear_collection_metadata { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::mint { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::burn { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::freeze { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::thaw { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::freeze_collection { .. }) | + RuntimeCall::Uniques(pallet_uniques::Call::thaw_collection { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), ProxyType::Collator => matches!( c, - RuntimeCall::CollatorSelection { .. } - | RuntimeCall::Utility { .. } - | RuntimeCall::Multisig { .. } + RuntimeCall::CollatorSelection { .. } | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } ), } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index c124d49e8586..7b2b97dfe716 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -282,205 +282,203 @@ impl Contains for SafeCallFilter { #[cfg(feature = "runtime-benchmarks")] { if matches!(call, RuntimeCall::System(frame_system::Call::remark_with_event { .. })) { - return true; + return true } } // Allow to change dedicated storage items (called by governance-like) match call { RuntimeCall::System(frame_system::Call::set_storage { items }) - if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) - || items.iter().all(|(k, _)| k.eq(&Flavor::key())) => - { - return true - }, + if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) || + items.iter().all(|(k, _)| k.eq(&Flavor::key())) => + return true, _ => (), }; matches!( call, - RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) - | RuntimeCall::System( - frame_system::Call::set_heap_pages { .. } - | frame_system::Call::set_code { .. } - | frame_system::Call::set_code_without_checks { .. } - | frame_system::Call::kill_prefix { .. }, - ) | RuntimeCall::ParachainSystem(..) - | RuntimeCall::Timestamp(..) - | RuntimeCall::Balances(..) - | RuntimeCall::CollatorSelection( - pallet_collator_selection::Call::set_desired_candidates { .. } - | pallet_collator_selection::Call::set_candidacy_bond { .. } - | pallet_collator_selection::Call::register_as_candidate { .. } - | pallet_collator_selection::Call::leave_intent { .. } - | pallet_collator_selection::Call::set_invulnerables { .. } - | pallet_collator_selection::Call::add_invulnerable { .. } - | pallet_collator_selection::Call::remove_invulnerable { .. }, - ) | RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) - | RuntimeCall::XcmpQueue(..) - | RuntimeCall::DmpQueue(..) - | RuntimeCall::Assets( - pallet_assets::Call::create { .. } - | pallet_assets::Call::force_create { .. } - | pallet_assets::Call::start_destroy { .. } - | pallet_assets::Call::destroy_accounts { .. } - | pallet_assets::Call::destroy_approvals { .. } - | pallet_assets::Call::finish_destroy { .. } - | pallet_assets::Call::block { .. } - | pallet_assets::Call::mint { .. } - | pallet_assets::Call::burn { .. } - | pallet_assets::Call::transfer { .. } - | pallet_assets::Call::transfer_keep_alive { .. } - | pallet_assets::Call::force_transfer { .. } - | pallet_assets::Call::freeze { .. } - | pallet_assets::Call::thaw { .. } - | pallet_assets::Call::freeze_asset { .. } - | pallet_assets::Call::thaw_asset { .. } - | pallet_assets::Call::transfer_ownership { .. } - | pallet_assets::Call::set_team { .. } - | pallet_assets::Call::set_metadata { .. } - | pallet_assets::Call::clear_metadata { .. } - | pallet_assets::Call::force_set_metadata { .. } - | pallet_assets::Call::force_clear_metadata { .. } - | pallet_assets::Call::force_asset_status { .. } - | pallet_assets::Call::approve_transfer { .. } - | pallet_assets::Call::cancel_approval { .. } - | pallet_assets::Call::force_cancel_approval { .. } - | pallet_assets::Call::transfer_approved { .. } - | pallet_assets::Call::touch { .. } - | pallet_assets::Call::touch_other { .. } - | pallet_assets::Call::refund { .. } - | pallet_assets::Call::refund_other { .. }, + RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | + RuntimeCall::System( + frame_system::Call::set_heap_pages { .. } | + frame_system::Call::set_code { .. } | + frame_system::Call::set_code_without_checks { .. } | + frame_system::Call::kill_prefix { .. }, + ) | RuntimeCall::ParachainSystem(..) | + RuntimeCall::Timestamp(..) | + RuntimeCall::Balances(..) | + RuntimeCall::CollatorSelection( + pallet_collator_selection::Call::set_desired_candidates { .. } | + pallet_collator_selection::Call::set_candidacy_bond { .. } | + pallet_collator_selection::Call::register_as_candidate { .. } | + pallet_collator_selection::Call::leave_intent { .. } | + pallet_collator_selection::Call::set_invulnerables { .. } | + pallet_collator_selection::Call::add_invulnerable { .. } | + pallet_collator_selection::Call::remove_invulnerable { .. }, + ) | RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) | + RuntimeCall::XcmpQueue(..) | + RuntimeCall::DmpQueue(..) | + RuntimeCall::Assets( + pallet_assets::Call::create { .. } | + pallet_assets::Call::force_create { .. } | + pallet_assets::Call::start_destroy { .. } | + pallet_assets::Call::destroy_accounts { .. } | + pallet_assets::Call::destroy_approvals { .. } | + pallet_assets::Call::finish_destroy { .. } | + pallet_assets::Call::block { .. } | + pallet_assets::Call::mint { .. } | + pallet_assets::Call::burn { .. } | + pallet_assets::Call::transfer { .. } | + pallet_assets::Call::transfer_keep_alive { .. } | + pallet_assets::Call::force_transfer { .. } | + pallet_assets::Call::freeze { .. } | + pallet_assets::Call::thaw { .. } | + pallet_assets::Call::freeze_asset { .. } | + pallet_assets::Call::thaw_asset { .. } | + pallet_assets::Call::transfer_ownership { .. } | + pallet_assets::Call::set_team { .. } | + pallet_assets::Call::set_metadata { .. } | + pallet_assets::Call::clear_metadata { .. } | + pallet_assets::Call::force_set_metadata { .. } | + pallet_assets::Call::force_clear_metadata { .. } | + pallet_assets::Call::force_asset_status { .. } | + pallet_assets::Call::approve_transfer { .. } | + pallet_assets::Call::cancel_approval { .. } | + pallet_assets::Call::force_cancel_approval { .. } | + pallet_assets::Call::transfer_approved { .. } | + pallet_assets::Call::touch { .. } | + pallet_assets::Call::touch_other { .. } | + pallet_assets::Call::refund { .. } | + pallet_assets::Call::refund_other { .. }, ) | RuntimeCall::ForeignAssets( - pallet_assets::Call::create { .. } - | pallet_assets::Call::force_create { .. } - | pallet_assets::Call::start_destroy { .. } - | pallet_assets::Call::destroy_accounts { .. } - | pallet_assets::Call::destroy_approvals { .. } - | pallet_assets::Call::finish_destroy { .. } - | pallet_assets::Call::block { .. } - | pallet_assets::Call::mint { .. } - | pallet_assets::Call::burn { .. } - | pallet_assets::Call::transfer { .. } - | pallet_assets::Call::transfer_keep_alive { .. } - | pallet_assets::Call::force_transfer { .. } - | pallet_assets::Call::freeze { .. } - | pallet_assets::Call::thaw { .. } - | pallet_assets::Call::freeze_asset { .. } - | pallet_assets::Call::thaw_asset { .. } - | pallet_assets::Call::transfer_ownership { .. } - | pallet_assets::Call::set_team { .. } - | pallet_assets::Call::set_metadata { .. } - | pallet_assets::Call::clear_metadata { .. } - | pallet_assets::Call::force_set_metadata { .. } - | pallet_assets::Call::force_clear_metadata { .. } - | pallet_assets::Call::force_asset_status { .. } - | pallet_assets::Call::approve_transfer { .. } - | pallet_assets::Call::cancel_approval { .. } - | pallet_assets::Call::force_cancel_approval { .. } - | pallet_assets::Call::transfer_approved { .. } - | pallet_assets::Call::touch { .. } - | pallet_assets::Call::touch_other { .. } - | pallet_assets::Call::refund { .. } - | pallet_assets::Call::refund_other { .. }, + pallet_assets::Call::create { .. } | + pallet_assets::Call::force_create { .. } | + pallet_assets::Call::start_destroy { .. } | + pallet_assets::Call::destroy_accounts { .. } | + pallet_assets::Call::destroy_approvals { .. } | + pallet_assets::Call::finish_destroy { .. } | + pallet_assets::Call::block { .. } | + pallet_assets::Call::mint { .. } | + pallet_assets::Call::burn { .. } | + pallet_assets::Call::transfer { .. } | + pallet_assets::Call::transfer_keep_alive { .. } | + pallet_assets::Call::force_transfer { .. } | + pallet_assets::Call::freeze { .. } | + pallet_assets::Call::thaw { .. } | + pallet_assets::Call::freeze_asset { .. } | + pallet_assets::Call::thaw_asset { .. } | + pallet_assets::Call::transfer_ownership { .. } | + pallet_assets::Call::set_team { .. } | + pallet_assets::Call::set_metadata { .. } | + pallet_assets::Call::clear_metadata { .. } | + pallet_assets::Call::force_set_metadata { .. } | + pallet_assets::Call::force_clear_metadata { .. } | + pallet_assets::Call::force_asset_status { .. } | + pallet_assets::Call::approve_transfer { .. } | + pallet_assets::Call::cancel_approval { .. } | + pallet_assets::Call::force_cancel_approval { .. } | + pallet_assets::Call::transfer_approved { .. } | + pallet_assets::Call::touch { .. } | + pallet_assets::Call::touch_other { .. } | + pallet_assets::Call::refund { .. } | + pallet_assets::Call::refund_other { .. }, ) | RuntimeCall::PoolAssets( - pallet_assets::Call::force_create { .. } - | pallet_assets::Call::block { .. } - | pallet_assets::Call::burn { .. } - | pallet_assets::Call::transfer { .. } - | pallet_assets::Call::transfer_keep_alive { .. } - | pallet_assets::Call::force_transfer { .. } - | pallet_assets::Call::freeze { .. } - | pallet_assets::Call::thaw { .. } - | pallet_assets::Call::freeze_asset { .. } - | pallet_assets::Call::thaw_asset { .. } - | pallet_assets::Call::transfer_ownership { .. } - | pallet_assets::Call::set_team { .. } - | pallet_assets::Call::set_metadata { .. } - | pallet_assets::Call::clear_metadata { .. } - | pallet_assets::Call::force_set_metadata { .. } - | pallet_assets::Call::force_clear_metadata { .. } - | pallet_assets::Call::force_asset_status { .. } - | pallet_assets::Call::approve_transfer { .. } - | pallet_assets::Call::cancel_approval { .. } - | pallet_assets::Call::force_cancel_approval { .. } - | pallet_assets::Call::transfer_approved { .. } - | pallet_assets::Call::touch { .. } - | pallet_assets::Call::touch_other { .. } - | pallet_assets::Call::refund { .. } - | pallet_assets::Call::refund_other { .. }, + pallet_assets::Call::force_create { .. } | + pallet_assets::Call::block { .. } | + pallet_assets::Call::burn { .. } | + pallet_assets::Call::transfer { .. } | + pallet_assets::Call::transfer_keep_alive { .. } | + pallet_assets::Call::force_transfer { .. } | + pallet_assets::Call::freeze { .. } | + pallet_assets::Call::thaw { .. } | + pallet_assets::Call::freeze_asset { .. } | + pallet_assets::Call::thaw_asset { .. } | + pallet_assets::Call::transfer_ownership { .. } | + pallet_assets::Call::set_team { .. } | + pallet_assets::Call::set_metadata { .. } | + pallet_assets::Call::clear_metadata { .. } | + pallet_assets::Call::force_set_metadata { .. } | + pallet_assets::Call::force_clear_metadata { .. } | + pallet_assets::Call::force_asset_status { .. } | + pallet_assets::Call::approve_transfer { .. } | + pallet_assets::Call::cancel_approval { .. } | + pallet_assets::Call::force_cancel_approval { .. } | + pallet_assets::Call::transfer_approved { .. } | + pallet_assets::Call::touch { .. } | + pallet_assets::Call::touch_other { .. } | + pallet_assets::Call::refund { .. } | + pallet_assets::Call::refund_other { .. }, ) | RuntimeCall::AssetConversion( - pallet_asset_conversion::Call::create_pool { .. } - | pallet_asset_conversion::Call::add_liquidity { .. } - | pallet_asset_conversion::Call::remove_liquidity { .. } - | pallet_asset_conversion::Call::swap_tokens_for_exact_tokens { .. } - | pallet_asset_conversion::Call::swap_exact_tokens_for_tokens { .. }, + pallet_asset_conversion::Call::create_pool { .. } | + pallet_asset_conversion::Call::add_liquidity { .. } | + pallet_asset_conversion::Call::remove_liquidity { .. } | + pallet_asset_conversion::Call::swap_tokens_for_exact_tokens { .. } | + pallet_asset_conversion::Call::swap_exact_tokens_for_tokens { .. }, ) | RuntimeCall::NftFractionalization( - pallet_nft_fractionalization::Call::fractionalize { .. } - | pallet_nft_fractionalization::Call::unify { .. }, + pallet_nft_fractionalization::Call::fractionalize { .. } | + pallet_nft_fractionalization::Call::unify { .. }, ) | RuntimeCall::Nfts( - pallet_nfts::Call::create { .. } - | pallet_nfts::Call::force_create { .. } - | pallet_nfts::Call::destroy { .. } - | pallet_nfts::Call::mint { .. } - | pallet_nfts::Call::force_mint { .. } - | pallet_nfts::Call::burn { .. } - | pallet_nfts::Call::transfer { .. } - | pallet_nfts::Call::lock_item_transfer { .. } - | pallet_nfts::Call::unlock_item_transfer { .. } - | pallet_nfts::Call::lock_collection { .. } - | pallet_nfts::Call::transfer_ownership { .. } - | pallet_nfts::Call::set_team { .. } - | pallet_nfts::Call::force_collection_owner { .. } - | pallet_nfts::Call::force_collection_config { .. } - | pallet_nfts::Call::approve_transfer { .. } - | pallet_nfts::Call::cancel_approval { .. } - | pallet_nfts::Call::clear_all_transfer_approvals { .. } - | pallet_nfts::Call::lock_item_properties { .. } - | pallet_nfts::Call::set_attribute { .. } - | pallet_nfts::Call::force_set_attribute { .. } - | pallet_nfts::Call::clear_attribute { .. } - | pallet_nfts::Call::approve_item_attributes { .. } - | pallet_nfts::Call::cancel_item_attributes_approval { .. } - | pallet_nfts::Call::set_metadata { .. } - | pallet_nfts::Call::clear_metadata { .. } - | pallet_nfts::Call::set_collection_metadata { .. } - | pallet_nfts::Call::clear_collection_metadata { .. } - | pallet_nfts::Call::set_accept_ownership { .. } - | pallet_nfts::Call::set_collection_max_supply { .. } - | pallet_nfts::Call::update_mint_settings { .. } - | pallet_nfts::Call::set_price { .. } - | pallet_nfts::Call::buy_item { .. } - | pallet_nfts::Call::pay_tips { .. } - | pallet_nfts::Call::create_swap { .. } - | pallet_nfts::Call::cancel_swap { .. } - | pallet_nfts::Call::claim_swap { .. }, + pallet_nfts::Call::create { .. } | + pallet_nfts::Call::force_create { .. } | + pallet_nfts::Call::destroy { .. } | + pallet_nfts::Call::mint { .. } | + pallet_nfts::Call::force_mint { .. } | + pallet_nfts::Call::burn { .. } | + pallet_nfts::Call::transfer { .. } | + pallet_nfts::Call::lock_item_transfer { .. } | + pallet_nfts::Call::unlock_item_transfer { .. } | + pallet_nfts::Call::lock_collection { .. } | + pallet_nfts::Call::transfer_ownership { .. } | + pallet_nfts::Call::set_team { .. } | + pallet_nfts::Call::force_collection_owner { .. } | + pallet_nfts::Call::force_collection_config { .. } | + pallet_nfts::Call::approve_transfer { .. } | + pallet_nfts::Call::cancel_approval { .. } | + pallet_nfts::Call::clear_all_transfer_approvals { .. } | + pallet_nfts::Call::lock_item_properties { .. } | + pallet_nfts::Call::set_attribute { .. } | + pallet_nfts::Call::force_set_attribute { .. } | + pallet_nfts::Call::clear_attribute { .. } | + pallet_nfts::Call::approve_item_attributes { .. } | + pallet_nfts::Call::cancel_item_attributes_approval { .. } | + pallet_nfts::Call::set_metadata { .. } | + pallet_nfts::Call::clear_metadata { .. } | + pallet_nfts::Call::set_collection_metadata { .. } | + pallet_nfts::Call::clear_collection_metadata { .. } | + pallet_nfts::Call::set_accept_ownership { .. } | + pallet_nfts::Call::set_collection_max_supply { .. } | + pallet_nfts::Call::update_mint_settings { .. } | + pallet_nfts::Call::set_price { .. } | + pallet_nfts::Call::buy_item { .. } | + pallet_nfts::Call::pay_tips { .. } | + pallet_nfts::Call::create_swap { .. } | + pallet_nfts::Call::cancel_swap { .. } | + pallet_nfts::Call::claim_swap { .. }, ) | RuntimeCall::Uniques( - pallet_uniques::Call::create { .. } - | pallet_uniques::Call::force_create { .. } - | pallet_uniques::Call::destroy { .. } - | pallet_uniques::Call::mint { .. } - | pallet_uniques::Call::burn { .. } - | pallet_uniques::Call::transfer { .. } - | pallet_uniques::Call::freeze { .. } - | pallet_uniques::Call::thaw { .. } - | pallet_uniques::Call::freeze_collection { .. } - | pallet_uniques::Call::thaw_collection { .. } - | pallet_uniques::Call::transfer_ownership { .. } - | pallet_uniques::Call::set_team { .. } - | pallet_uniques::Call::approve_transfer { .. } - | pallet_uniques::Call::cancel_approval { .. } - | pallet_uniques::Call::force_item_status { .. } - | pallet_uniques::Call::set_attribute { .. } - | pallet_uniques::Call::clear_attribute { .. } - | pallet_uniques::Call::set_metadata { .. } - | pallet_uniques::Call::clear_metadata { .. } - | pallet_uniques::Call::set_collection_metadata { .. } - | pallet_uniques::Call::clear_collection_metadata { .. } - | pallet_uniques::Call::set_accept_ownership { .. } - | pallet_uniques::Call::set_collection_max_supply { .. } - | pallet_uniques::Call::set_price { .. } - | pallet_uniques::Call::buy_item { .. } + pallet_uniques::Call::create { .. } | + pallet_uniques::Call::force_create { .. } | + pallet_uniques::Call::destroy { .. } | + pallet_uniques::Call::mint { .. } | + pallet_uniques::Call::burn { .. } | + pallet_uniques::Call::transfer { .. } | + pallet_uniques::Call::freeze { .. } | + pallet_uniques::Call::thaw { .. } | + pallet_uniques::Call::freeze_collection { .. } | + pallet_uniques::Call::thaw_collection { .. } | + pallet_uniques::Call::transfer_ownership { .. } | + pallet_uniques::Call::set_team { .. } | + pallet_uniques::Call::approve_transfer { .. } | + pallet_uniques::Call::cancel_approval { .. } | + pallet_uniques::Call::force_item_status { .. } | + pallet_uniques::Call::set_attribute { .. } | + pallet_uniques::Call::clear_attribute { .. } | + pallet_uniques::Call::set_metadata { .. } | + pallet_uniques::Call::clear_metadata { .. } | + pallet_uniques::Call::set_collection_metadata { .. } | + pallet_uniques::Call::clear_collection_metadata { .. } | + pallet_uniques::Call::set_accept_ownership { .. } | + pallet_uniques::Call::set_collection_max_supply { .. } | + pallet_uniques::Call::set_price { .. } | + pallet_uniques::Call::buy_item { .. } ) | RuntimeCall::ToWococoXcmRouter( pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } ) | RuntimeCall::ToRococoXcmRouter( diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index ba0012b20cc1..2f61a2824b09 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -46,7 +46,7 @@ impl> ContainsPair fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool { // `a` needs to be from `b` at least if !a.starts_with(b) { - return false; + return false } // here we check if sibling @@ -66,7 +66,7 @@ impl> ContainsPair fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool { // `a` needs to be from `b` at least if !a.starts_with(b) { - return false; + return false } match a { @@ -106,7 +106,7 @@ impl< "IsTrustedBridgedReserveLocationForConcreteAsset origin: {:?} is not remote to the universal_source: {:?}", origin, universal_source ); - return false; + return false }, }; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index a257042233d9..63d96692fe52 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -42,10 +42,9 @@ use snowbridge_beacon_primitives::{Fork, ForkVersions}; use snowbridge_router_primitives::inbound::MessageToXcm; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160}; -use sp_runtime::traits::AccountIdConversion; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, Keccak256}, + traits::{AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Keccak256}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, }; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index d2a41ab6d580..989410ce7bd2 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -41,23 +41,24 @@ use parachains_common::{ use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; use rococo_runtime_constants::system_parachain::SystemParachains; +use snowbridge_router_primitives::outbound::EthereumBlobExporter; use sp_core::{Get, H256}; use sp_runtime::traits::AccountIdConversion; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, - DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, IsConcrete, ParentAsSuperuser, - ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily, + EnsureXcmOrigin, HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, - XcmFeesToAccount, HashedDescription, DescribeFamily, DescribeAllTerminal + XcmFeesToAccount, }; use xcm_executor::{ traits::{ExportXcm, WithOriginFilter}, XcmExecutor, }; -use snowbridge_router_primitives::outbound::EthereumBlobExporter; parameter_types! { pub storage Flavor: RuntimeFlavor = RuntimeFlavor::default(); @@ -222,12 +223,12 @@ impl Contains for SafeCallFilter { BridgeGrandpaWococoInstance, >::initialize { .. }) | RuntimeCall::EthereumBeaconClient( - snowbridge_ethereum_beacon_client::Call::force_checkpoint { .. } - | snowbridge_ethereum_beacon_client::Call::set_owner { .. } - | snowbridge_ethereum_beacon_client::Call::set_operating_mode { .. }, + snowbridge_ethereum_beacon_client::Call::force_checkpoint { .. } | + snowbridge_ethereum_beacon_client::Call::set_owner { .. } | + snowbridge_ethereum_beacon_client::Call::set_operating_mode { .. }, ) | RuntimeCall::EthereumInboundQueue( - snowbridge_inbound_queue::Call::set_owner { .. } - | snowbridge_inbound_queue::Call::set_operating_mode { .. }, + snowbridge_inbound_queue::Call::set_owner { .. } | + snowbridge_inbound_queue::Call::set_operating_mode { .. }, ) | RuntimeCall::EthereumOutboundQueue( snowbridge_outbound_queue::Call::set_owner { .. } | snowbridge_outbound_queue::Call::set_operating_mode { .. }, @@ -335,12 +336,17 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] pub(crate) mod benchmark_helper { - use crate::xcm_config::{MultiAssets, MultiLocation, SendError, SendResult, SendXcm, Xcm, XcmHash}; + use crate::xcm_config::{ + MultiAssets, MultiLocation, SendError, SendResult, SendXcm, Xcm, XcmHash, + }; pub struct DoNothingRouter; impl SendXcm for DoNothingRouter { type Ticket = (); - fn validate(_dest: &mut Option, _msg: &mut Option>) -> SendResult<()> { + fn validate( + _dest: &mut Option, + _msg: &mut Option>, + ) -> SendResult<()> { Ok(((), MultiAssets::new())) } fn deliver(_: ()) -> Result { @@ -440,7 +446,7 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { destination, message, ) - .map(|result| ((Ethereum {chain_id: 15}, result.0), result.1)) // TODO get network ID + .map(|result| ((Ethereum { chain_id: 15 }, result.0), result.1)) // TODO get network ID }, _ => unimplemented!("Unsupported network: {:?}", network), } @@ -451,9 +457,8 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { match network { Rococo => ToBridgeHubRococoHaulBlobExporter::deliver(ticket), Wococo => ToBridgeHubWococoHaulBlobExporter::deliver(ticket), - location if location == EthereumNetwork::get() && network == Rococo => { - SnowbridgeExporter::deliver(ticket) - }, + location if location == EthereumNetwork::get() && network == Rococo => + SnowbridgeExporter::deliver(ticket), _ => unimplemented!("Unsupported network: {:?}", network), } } From 371ac2d798f74a42510e58682a22879235e839c8 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 26 Oct 2023 18:20:11 +0300 Subject: [PATCH 069/124] pallet-xcm: fix broken reserve_transfer_assets benchmark --- polkadot/xcm/pallet-xcm/Cargo.toml | 7 +- polkadot/xcm/pallet-xcm/src/benchmarking.rs | 86 +++++++++++++++++++-- polkadot/xcm/pallet-xcm/src/mock.rs | 8 +- 3 files changed, 88 insertions(+), 13 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/Cargo.toml b/polkadot/xcm/pallet-xcm/Cargo.toml index eedf3041cb37..67c54f8d9bc4 100644 --- a/polkadot/xcm/pallet-xcm/Cargo.toml +++ b/polkadot/xcm/pallet-xcm/Cargo.toml @@ -13,7 +13,6 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive serde = { version = "1.0.188", optional = true, features = ["derive"] } log = { version = "0.4.17", default-features = false } -frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-support = { path = "../../../substrate/frame/support", default-features = false} frame-system = { path = "../../../substrate/frame/system", default-features = false} sp-core = { path = "../../../substrate/primitives/core", default-features = false} @@ -24,8 +23,11 @@ sp-std = { path = "../../../substrate/primitives/std", default-features = false} xcm = { package = "staging-xcm", path = "..", default-features = false } xcm-executor = { package = "staging-xcm-executor", path = "../xcm-executor", default-features = false } +# marked optional, used in benchmarking +frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } +pallet-assets = { path = "../../../substrate/frame/assets", default-features = false, optional = true } + [dev-dependencies] -pallet-assets = { path = "../../../substrate/frame/assets" } pallet-balances = { path = "../../../substrate/frame/balances" } polkadot-runtime-parachains = { path = "../../runtime/parachains" } polkadot-parachain-primitives = { path = "../../parachain" } @@ -40,6 +42,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", + "pallet-assets/std", "scale-info/std", "serde", "sp-core/std", diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index f567691b5092..4f61d34feeca 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -16,15 +16,58 @@ use super::*; use bounded_collections::{ConstU32, WeakBoundedVec}; -use frame_benchmarking::{benchmarks, BenchmarkError, BenchmarkResult}; -use frame_support::weights::Weight; +use frame_benchmarking::{benchmarks, whitelisted_caller, BenchmarkError, BenchmarkResult}; +use frame_support::{assert_ok, traits::Currency, weights::Weight}; use frame_system::RawOrigin; +use pallet_assets::Pallet as AssetsPallet; +use sp_runtime::traits::StaticLookup; use sp_std::prelude::*; use xcm::{latest::prelude::*, v2}; type RuntimeOrigin = ::RuntimeOrigin; +fn create_default_asset( + asset_id: T::AssetIdParameter, + is_sufficient: bool, + caller: T::AccountId, +) { + let beneficiary = T::Lookup::unlookup(caller); + let root = frame_system::RawOrigin::Root.into(); + assert_ok!(AssetsPallet::::force_create( + root, + asset_id, + beneficiary, + is_sufficient, + 1u32.into(), + )); +} + +fn create_default_minted_asset( + asset_id: T::AssetIdParameter, + is_sufficient: bool, + amount: T::Balance, + caller: T::AccountId, +) { + create_default_asset::(asset_id, is_sufficient, caller.clone()); + if !is_sufficient { + T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance()); + } + let beneficiary = T::Lookup::unlookup(caller.clone()); + assert_ok!(AssetsPallet::::mint( + frame_system::RawOrigin::Signed(caller).into(), + asset_id, + beneficiary, + amount, + )); +} + benchmarks! { + where_clause { + where + T: pallet_assets::Config, + ::AssetIdParameter: From, + ::Balance: From + Into, + } send { let send_origin = T::SendXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; @@ -62,9 +105,23 @@ benchmarks! { let (assets, destination) = T::ReserveTransferableAssets::get().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; - let send_origin = - T::ExecuteXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone()) + let caller: T::AccountId = whitelisted_caller(); + for asset in assets.inner() { + let amount = match &asset.fun { + Fungible(amount) => *amount, + _ => return Err(BenchmarkError::Stop("AssetNotFungible")), + }; + let id = match &asset.id { + Concrete(location) => *location, + _ => return Err(BenchmarkError::Stop("AssetNotFungible")), + }; + let asset_id: T::AssetIdParameter = id.into(); + create_default_minted_asset::(asset_id.clone(), true, amount.into(), caller.clone()); + // verify initial balance + assert_eq!(AssetsPallet::::balance(asset_id.into(), caller.clone()), amount.into()); + } + let send_origin = RawOrigin::Signed(caller.clone()); + let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into()) .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; if !T::XcmReserveTransferFilter::contains(&(origin_location, assets.clone().into_inner())) { return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) @@ -74,8 +131,23 @@ benchmarks! { let versioned_dest: VersionedMultiLocation = destination.into(); let versioned_beneficiary: VersionedMultiLocation = AccountId32 { network: None, id: recipient.into() }.into(); - let versioned_assets: VersionedMultiAssets = assets.into(); - }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) + let versioned_assets: VersionedMultiAssets = assets.clone().into(); + }: _>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) + verify { + for asset in assets.inner() { + let amount = match &asset.fun { + Fungible(amount) => *amount, + _ => return Err(BenchmarkError::Stop("AssetNotFungible")), + }; + let id = match &asset.id { + Concrete(location) => *location, + _ => return Err(BenchmarkError::Stop("AssetNotFungible")), + }; + let asset_id: T::AssetIdParameter = id.into(); + // verify balance after transfer + assert_eq!(AssetsPallet::::balance(asset_id.into(), caller.clone()), 0.into()); + } + } execute { let execute_origin = diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 984b359617f2..43974545ec45 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -35,9 +35,9 @@ use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, Case, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, CurrencyAdapter as XcmCurrencyAdapter, DescribeAllTerminal, - DescribeFamily, FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, HashedDescription, - IsConcrete, MatchedConvertedConcreteId, NoChecking, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, XcmFeesToAccount, + FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, HashedDescription, IsConcrete, + MatchedConvertedConcreteId, NoChecking, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, XcmFeesToAccount, }; use xcm_executor::{ traits::{Identity, JustTry}, @@ -382,7 +382,7 @@ parameter_types! { pub type SovereignAccountOf = ( ChildParachainConvertsVia, AccountId32Aliases, - HashedDescription>, + HashedDescription, ); pub type ForeignAssetsConvertedConcreteId = MatchedConvertedConcreteId< From 9b58ff0e877f3ec7214183da7cf31d9b5b6625b8 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 27 Oct 2023 12:33:08 +0300 Subject: [PATCH 070/124] try add pallet-assets for benchmarking to rococo --- Cargo.lock | 1 + polkadot/runtime/rococo/Cargo.toml | 4 ++++ polkadot/runtime/rococo/src/lib.rs | 36 ++++++++++++++++++++++++++---- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 843083beb9ae..fd94c08a3a79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14221,6 +14221,7 @@ dependencies = [ "hex-literal", "log", "pallet-asset-rate", + "pallet-assets", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml index 6d0dee3e4343..337bb4142047 100644 --- a/polkadot/runtime/rococo/Cargo.toml +++ b/polkadot/runtime/rococo/Cargo.toml @@ -90,6 +90,7 @@ pallet-xcm-benchmarks = { path = "../../xcm/pallet-xcm-benchmarks", default-feat frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-try-runtime = { path = "../../../substrate/frame/try-runtime", default-features = false, optional = true } frame-system-benchmarking = { path = "../../../substrate/frame/system/benchmarking", default-features = false, optional = true } +pallet-assets = { path = "../../../substrate/frame/assets", default-features = false, optional = true } hex-literal = { version = "0.4.1" } runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false } @@ -134,6 +135,7 @@ std = [ "log/std", "offchain-primitives/std", "pallet-asset-rate/std", + "pallet-assets/std", "pallet-authority-discovery/std", "pallet-authorship/std", "pallet-babe/std", @@ -211,6 +213,7 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-asset-rate/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", "pallet-babe/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-bounties/runtime-benchmarks", @@ -263,6 +266,7 @@ try-runtime = [ "frame-try-runtime", "frame-try-runtime/try-runtime", "pallet-asset-rate/try-runtime", + "pallet-assets/try-runtime", "pallet-authority-discovery/try-runtime", "pallet-authorship/try-runtime", "pallet-babe/try-runtime", diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index e6ad061ce069..439e010f50ff 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -67,14 +67,14 @@ use frame_support::{ genesis_builder_helper::{build_config, create_default_config}, parameter_types, traits::{ - fungible::HoldConsideration, EitherOf, EitherOfDiverse, Everything, InstanceFilter, - KeyOwnerProofSystem, LinearStoragePrice, PrivilegeCmp, ProcessMessage, ProcessMessageError, - StorageMapShim, WithdrawReasons, + fungible::HoldConsideration, AsEnsureOriginWithArg, EitherOf, EitherOfDiverse, Everything, + InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, PrivilegeCmp, ProcessMessage, + ProcessMessageError, StorageMapShim, WithdrawReasons, }, weights::{ConstantMultiplier, WeightMeter}, PalletId, }; -use frame_system::EnsureRoot; +use frame_system::{EnsureRoot, EnsureSigned}; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId}; use pallet_identity::simple::IdentityInfo; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; @@ -302,6 +302,30 @@ impl pallet_balances::Config for Runtime { type MaxHolds = ConstU32<2>; } +// only used in benchmarks +#[cfg(feature = "runtime-benchmarks")] +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = MultiLocationForAssetId; + type AssetIdParameter = MultiLocationForAssetId; + type Currency = Balances; + type CreateOrigin = AsEnsureOriginWithArg>; + type ForceOrigin = EnsureRoot; + type AssetDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; + type MetadataDepositBase = ConstU128<1>; + type MetadataDepositPerByte = ConstU128<1>; + type ApprovalDeposit = ConstU128<1>; + type StringLimit = ConstU32<50>; + type Freezer = (); + type WeightInfo = (); + type CallbackHandle = (); + type Extra = (); + type RemoveItemsLimit = ConstU32<5>; + type BenchmarkHelper = (); +} + parameter_types! { pub const TransactionByteFee: Balance = 10 * MILLICENTS; /// This value increases the priority of `Operational` transactions by adding @@ -1359,6 +1383,10 @@ construct_runtime! { // Pallet for sending XCM. XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, + // Assets pallet only used in benchmarks. + #[cfg(feature = "runtime-benchmarks")] + Assets: pallet_assets::{Pallet, Call, Storage, Config, Event} = 100, + ParasSudoWrapper: paras_sudo_wrapper::{Pallet, Call} = 250, AssignedSlots: assigned_slots::{Pallet, Call, Storage, Event, Config} = 251, From 942977e64fb9918e6c383a22e60ac565818c2dff Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 27 Oct 2023 13:06:36 +0300 Subject: [PATCH 071/124] Revert "try add pallet-assets for benchmarking to rococo" This reverts commit c82330b614df352a0e25a8f18dbd43bc356aed4b. --- Cargo.lock | 1 - polkadot/runtime/rococo/Cargo.toml | 4 ---- polkadot/runtime/rococo/src/lib.rs | 36 ++++-------------------------- 3 files changed, 4 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fd94c08a3a79..843083beb9ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14221,7 +14221,6 @@ dependencies = [ "hex-literal", "log", "pallet-asset-rate", - "pallet-assets", "pallet-authority-discovery", "pallet-authorship", "pallet-babe", diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml index 337bb4142047..6d0dee3e4343 100644 --- a/polkadot/runtime/rococo/Cargo.toml +++ b/polkadot/runtime/rococo/Cargo.toml @@ -90,7 +90,6 @@ pallet-xcm-benchmarks = { path = "../../xcm/pallet-xcm-benchmarks", default-feat frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } frame-try-runtime = { path = "../../../substrate/frame/try-runtime", default-features = false, optional = true } frame-system-benchmarking = { path = "../../../substrate/frame/system/benchmarking", default-features = false, optional = true } -pallet-assets = { path = "../../../substrate/frame/assets", default-features = false, optional = true } hex-literal = { version = "0.4.1" } runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false } @@ -135,7 +134,6 @@ std = [ "log/std", "offchain-primitives/std", "pallet-asset-rate/std", - "pallet-assets/std", "pallet-authority-discovery/std", "pallet-authorship/std", "pallet-babe/std", @@ -213,7 +211,6 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-asset-rate/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", "pallet-babe/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-bounties/runtime-benchmarks", @@ -266,7 +263,6 @@ try-runtime = [ "frame-try-runtime", "frame-try-runtime/try-runtime", "pallet-asset-rate/try-runtime", - "pallet-assets/try-runtime", "pallet-authority-discovery/try-runtime", "pallet-authorship/try-runtime", "pallet-babe/try-runtime", diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 439e010f50ff..e6ad061ce069 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -67,14 +67,14 @@ use frame_support::{ genesis_builder_helper::{build_config, create_default_config}, parameter_types, traits::{ - fungible::HoldConsideration, AsEnsureOriginWithArg, EitherOf, EitherOfDiverse, Everything, - InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, PrivilegeCmp, ProcessMessage, - ProcessMessageError, StorageMapShim, WithdrawReasons, + fungible::HoldConsideration, EitherOf, EitherOfDiverse, Everything, InstanceFilter, + KeyOwnerProofSystem, LinearStoragePrice, PrivilegeCmp, ProcessMessage, ProcessMessageError, + StorageMapShim, WithdrawReasons, }, weights::{ConstantMultiplier, WeightMeter}, PalletId, }; -use frame_system::{EnsureRoot, EnsureSigned}; +use frame_system::EnsureRoot; use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId}; use pallet_identity::simple::IdentityInfo; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; @@ -302,30 +302,6 @@ impl pallet_balances::Config for Runtime { type MaxHolds = ConstU32<2>; } -// only used in benchmarks -#[cfg(feature = "runtime-benchmarks")] -impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type AssetId = MultiLocationForAssetId; - type AssetIdParameter = MultiLocationForAssetId; - type Currency = Balances; - type CreateOrigin = AsEnsureOriginWithArg>; - type ForceOrigin = EnsureRoot; - type AssetDeposit = ConstU128<1>; - type AssetAccountDeposit = ConstU128<10>; - type MetadataDepositBase = ConstU128<1>; - type MetadataDepositPerByte = ConstU128<1>; - type ApprovalDeposit = ConstU128<1>; - type StringLimit = ConstU32<50>; - type Freezer = (); - type WeightInfo = (); - type CallbackHandle = (); - type Extra = (); - type RemoveItemsLimit = ConstU32<5>; - type BenchmarkHelper = (); -} - parameter_types! { pub const TransactionByteFee: Balance = 10 * MILLICENTS; /// This value increases the priority of `Operational` transactions by adding @@ -1383,10 +1359,6 @@ construct_runtime! { // Pallet for sending XCM. XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config} = 99, - // Assets pallet only used in benchmarks. - #[cfg(feature = "runtime-benchmarks")] - Assets: pallet_assets::{Pallet, Call, Storage, Config, Event} = 100, - ParasSudoWrapper: paras_sudo_wrapper::{Pallet, Call} = 250, AssignedSlots: assigned_slots::{Pallet, Call, Storage, Event, Config} = 251, From 3b9965b2b6b99d44fef881dfe638f4e07d1f04ef Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 27 Oct 2023 13:07:20 +0300 Subject: [PATCH 072/124] pallet-xcm benchmarking: most chains do not have pallet-assets, use pallet-balances instead --- polkadot/xcm/pallet-xcm/Cargo.toml | 6 +- polkadot/xcm/pallet-xcm/src/benchmarking.rs | 95 ++++++--------------- polkadot/xcm/pallet-xcm/src/mock.rs | 7 +- 3 files changed, 36 insertions(+), 72 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/Cargo.toml b/polkadot/xcm/pallet-xcm/Cargo.toml index 67c54f8d9bc4..2005fc0375ef 100644 --- a/polkadot/xcm/pallet-xcm/Cargo.toml +++ b/polkadot/xcm/pallet-xcm/Cargo.toml @@ -25,10 +25,10 @@ xcm-executor = { package = "staging-xcm-executor", path = "../xcm-executor", def # marked optional, used in benchmarking frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true } -pallet-assets = { path = "../../../substrate/frame/assets", default-features = false, optional = true } +pallet-balances = { path = "../../../substrate/frame/balances", default-features = false, optional = true } [dev-dependencies] -pallet-balances = { path = "../../../substrate/frame/balances" } +pallet-assets = { path = "../../../substrate/frame/assets" } polkadot-runtime-parachains = { path = "../../runtime/parachains" } polkadot-parachain-primitives = { path = "../../parachain" } xcm-builder = { package = "staging-xcm-builder", path = "../xcm-builder" } @@ -42,7 +42,7 @@ std = [ "frame-support/std", "frame-system/std", "log/std", - "pallet-assets/std", + "pallet-balances/std", "scale-info/std", "serde", "sp-core/std", diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index 4f61d34feeca..c44307f9891d 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -17,56 +17,21 @@ use super::*; use bounded_collections::{ConstU32, WeakBoundedVec}; use frame_benchmarking::{benchmarks, whitelisted_caller, BenchmarkError, BenchmarkResult}; -use frame_support::{assert_ok, traits::Currency, weights::Weight}; +use frame_support::{traits::Currency, weights::Weight}; use frame_system::RawOrigin; -use pallet_assets::Pallet as AssetsPallet; -use sp_runtime::traits::StaticLookup; use sp_std::prelude::*; use xcm::{latest::prelude::*, v2}; type RuntimeOrigin = ::RuntimeOrigin; -fn create_default_asset( - asset_id: T::AssetIdParameter, - is_sufficient: bool, - caller: T::AccountId, -) { - let beneficiary = T::Lookup::unlookup(caller); - let root = frame_system::RawOrigin::Root.into(); - assert_ok!(AssetsPallet::::force_create( - root, - asset_id, - beneficiary, - is_sufficient, - 1u32.into(), - )); -} - -fn create_default_minted_asset( - asset_id: T::AssetIdParameter, - is_sufficient: bool, - amount: T::Balance, - caller: T::AccountId, -) { - create_default_asset::(asset_id, is_sufficient, caller.clone()); - if !is_sufficient { - T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance()); - } - let beneficiary = T::Lookup::unlookup(caller.clone()); - assert_ok!(AssetsPallet::::mint( - frame_system::RawOrigin::Signed(caller).into(), - asset_id, - beneficiary, - amount, - )); -} +// existential deposit multiplier +const ED_MULTIPLIER: u32 = 10; benchmarks! { where_clause { where - T: pallet_assets::Config, - ::AssetIdParameter: From, - ::Balance: From + Into, + T: pallet_balances::Config, + ::Balance: From + Into, } send { let send_origin = @@ -105,21 +70,28 @@ benchmarks! { let (assets, destination) = T::ReserveTransferableAssets::get().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; - let caller: T::AccountId = whitelisted_caller(); - for asset in assets.inner() { - let amount = match &asset.fun { - Fungible(amount) => *amount, - _ => return Err(BenchmarkError::Stop("AssetNotFungible")), - }; - let id = match &asset.id { - Concrete(location) => *location, - _ => return Err(BenchmarkError::Stop("AssetNotFungible")), - }; - let asset_id: T::AssetIdParameter = id.into(); - create_default_minted_asset::(asset_id.clone(), true, amount.into(), caller.clone()); - // verify initial balance - assert_eq!(AssetsPallet::::balance(asset_id.into(), caller.clone()), amount.into()); + + // most chains deploying `pallet-xcm` don't have `pallet-assets` so we're + // stuck with using native token and `pallet-balances`. + if assets.len() != 1 { + return Err(BenchmarkError::Stop("Generic benchmark supports only single native asset")) } + let asset = assets.inner().clone().pop().unwrap(); + let transferred_amount = match &asset.fun { + Fungible(amount) => *amount, + _ => return Err(BenchmarkError::Stop("Benchmark asset not fungible")), + }.into(); + + let existential_deposit = T::ExistentialDeposit::get(); + let caller = whitelisted_caller(); + + // Give some multiple of the existential deposit + let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); + assert!(balance >= transferred_amount); + let _ = as Currency<_>>::make_free_balance_be(&caller, balance); + // verify initial balance + assert_eq!(pallet_balances::Pallet::::free_balance(&caller), balance); + let send_origin = RawOrigin::Signed(caller.clone()); let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into()) .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; @@ -134,19 +106,8 @@ benchmarks! { let versioned_assets: VersionedMultiAssets = assets.clone().into(); }: _>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) verify { - for asset in assets.inner() { - let amount = match &asset.fun { - Fungible(amount) => *amount, - _ => return Err(BenchmarkError::Stop("AssetNotFungible")), - }; - let id = match &asset.id { - Concrete(location) => *location, - _ => return Err(BenchmarkError::Stop("AssetNotFungible")), - }; - let asset_id: T::AssetIdParameter = id.into(); - // verify balance after transfer - assert_eq!(AssetsPallet::::balance(asset_id.into(), caller.clone()), 0.into()); - } + // verify balance after transfer + assert_eq!(pallet_balances::Pallet::::free_balance(&caller), balance - transferred_amount); } execute { diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 43974545ec45..7afa9f581f44 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -489,8 +489,11 @@ parameter_types! { UsdtTeleportLocation::get(), )); pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - vec![ForeignAsset::get()].into(), - ForeignReserveLocation::get(), + MultiAsset { + fun: Fungible(10), + id: Concrete(Here.into_location()), + }.into(), + Parachain(OTHER_PARA_ID).into(), )); } From adcd6889b33ac7597bf9aa3ec9e22fec94294589 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 27 Oct 2023 14:38:10 +0300 Subject: [PATCH 073/124] pallet-xcm: fix teleport_assets benchmark --- polkadot/runtime/rococo/src/xcm_config.rs | 4 +-- polkadot/xcm/pallet-xcm/src/benchmarking.rs | 39 +++++++++++++++++---- polkadot/xcm/pallet-xcm/src/mock.rs | 31 ++++++++++++---- 3 files changed, 58 insertions(+), 16 deletions(-) diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index 65661b3e9334..da0aabfbaea5 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -212,12 +212,12 @@ parameter_types! { pub ReachableDest: Option = Some(Parachain(ASSET_HUB_ID).into()); // Relay/native token can be teleported to/from AH. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }.into(), AssetHub::get(), )); // We can reserve transfer native token to some random parachain. pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }.into(), Parachain(4321).into(), )); } diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index c44307f9891d..b0a37db6a783 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -51,9 +51,30 @@ benchmarks! { let (assets, destination) = T::TeleportableAssets::get().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; - let send_origin = - T::ExecuteXcmOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?; - let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone()) + + // most chains deploying `pallet-xcm` don't have `pallet-assets` so we're + // stuck with using native token and `pallet-balances`. + if assets.len() != 1 { + return Err(BenchmarkError::Stop("Generic benchmark supports only single native asset")) + } + let asset = assets.inner().clone().pop().unwrap(); + let transferred_amount = match &asset.fun { + Fungible(amount) => *amount, + _ => return Err(BenchmarkError::Stop("Benchmark asset not fungible")), + }.into(); + + let existential_deposit = T::ExistentialDeposit::get(); + let caller = whitelisted_caller(); + + // Give some multiple of the existential deposit + let balance = existential_deposit.saturating_mul(ED_MULTIPLIER.into()); + assert!(balance >= transferred_amount); + let _ = as Currency<_>>::make_free_balance_be(&caller, balance); + // verify initial balance + assert_eq!(pallet_balances::Pallet::::free_balance(&caller), balance); + + let send_origin = RawOrigin::Signed(caller.clone()); + let origin_location = T::ExecuteXcmOrigin::try_origin(send_origin.clone().into()) .map_err(|_| BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)))?; if !T::XcmTeleportFilter::contains(&(origin_location, assets.clone().into_inner())) { return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) @@ -64,7 +85,11 @@ benchmarks! { let versioned_beneficiary: VersionedMultiLocation = AccountId32 { network: None, id: recipient.into() }.into(); let versioned_assets: VersionedMultiAssets = assets.into(); - }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) + }: _>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) + verify { + // verify balance after transfer, decreased by transferred amount (+ maybe XCM delivery fees) + assert!(pallet_balances::Pallet::::free_balance(&caller) <= balance - transferred_amount); + } reserve_transfer_assets { let (assets, destination) = T::ReserveTransferableAssets::get().ok_or( @@ -103,11 +128,11 @@ benchmarks! { let versioned_dest: VersionedMultiLocation = destination.into(); let versioned_beneficiary: VersionedMultiLocation = AccountId32 { network: None, id: recipient.into() }.into(); - let versioned_assets: VersionedMultiAssets = assets.clone().into(); + let versioned_assets: VersionedMultiAssets = assets.into(); }: _>(send_origin.into(), Box::new(versioned_dest), Box::new(versioned_beneficiary), Box::new(versioned_assets), 0) verify { - // verify balance after transfer - assert_eq!(pallet_balances::Pallet::::free_balance(&caller), balance - transferred_amount); + // verify balance after transfer, decreased by transferred amount (+ maybe XCM delivery fees) + assert!(pallet_balances::Pallet::::free_balance(&caller) <= balance - transferred_amount); } execute { diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index 7afa9f581f44..e421d46f206b 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -320,6 +320,9 @@ impl pallet_assets::Config for Test { type BenchmarkHelper = XcmBenchmarkHelper; } +// This child parachain is a system parachain trusted to teleport native token. +pub const SOME_SYSTEM_PARA: u32 = 1001; + // This child parachain acts as trusted reserve for its assets in tests. // USDT allowed to teleport to/from here. pub const FOREIGN_ASSET_RESERVE_PARA_ID: u32 = 2001; @@ -340,6 +343,14 @@ pub const OTHER_PARA_ID: u32 = 2009; parameter_types! { pub const RelayLocation: MultiLocation = Here.into_location(); + pub const NativeAsset: MultiAsset = MultiAsset { + fun: Fungible(10), + id: Concrete(Here.into_location()), + }; + pub const SystemParachainLocation: MultiLocation = MultiLocation { + parents: 0, + interior: X1(Parachain(SOME_SYSTEM_PARA)) + }; pub const ForeignReserveLocation: MultiLocation = MultiLocation { parents: 0, interior: X1(Parachain(FOREIGN_ASSET_RESERVE_PARA_ID)) @@ -417,10 +428,11 @@ parameter_types! { pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000); pub CurrencyPerSecondPerByte: (AssetId, u128, u128) = (Concrete(RelayLocation::get()), 1, 1); pub TrustedLocal: (MultiAssetFilter, MultiLocation) = (All.into(), Here.into()); - pub TrustedUsdt: (MultiAssetFilter, MultiLocation) = (vec![Usdt::get()].into(), UsdtTeleportLocation::get()); - pub TeleportUsdtToForeign: (MultiAssetFilter, MultiLocation) = (vec![Usdt::get()].into(), ForeignReserveLocation::get()); - pub TrustedForeign: (MultiAssetFilter, MultiLocation) = (vec![ForeignAsset::get()].into(), ForeignReserveLocation::get()); - pub TrustedUsdc: (MultiAssetFilter, MultiLocation) = (vec![Usdc::get()].into(), UsdcReserveLocation::get()); + pub TrustedSystemPara: (MultiAssetFilter, MultiLocation) = (NativeAsset::get().into(), SystemParachainLocation::get()); + pub TrustedUsdt: (MultiAssetFilter, MultiLocation) = (Usdt::get().into(), UsdtTeleportLocation::get()); + pub TeleportUsdtToForeign: (MultiAssetFilter, MultiLocation) = (Usdt::get().into(), ForeignReserveLocation::get()); + pub TrustedForeign: (MultiAssetFilter, MultiLocation) = (ForeignAsset::get().into(), ForeignReserveLocation::get()); + pub TrustedUsdc: (MultiAssetFilter, MultiLocation) = (Usdc::get().into(), UsdcReserveLocation::get()); pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; pub XcmFeesTargetAccount: AccountId = AccountId::new([167u8; 32]); @@ -449,7 +461,12 @@ impl xcm_executor::Config for XcmConfig { type AssetTransactor = AssetTransactors; type OriginConverter = LocalOriginConverter; type IsReserve = (Case, Case); - type IsTeleporter = (Case, Case, Case); + type IsTeleporter = ( + Case, + Case, + Case, + Case, + ); type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; @@ -485,8 +502,8 @@ parameter_types! { parameter_types! { pub ReachableDest: Option = Some(Parachain(1000).into()); pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - vec![Usdt::get()].into(), - UsdtTeleportLocation::get(), + NativeAsset::get().into(), + SystemParachainLocation::get(), )); pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( MultiAsset { From eca0c3ef19cb4e5bb6651eeee069705009675f0c Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 27 Oct 2023 14:54:18 +0300 Subject: [PATCH 074/124] fix runtimes benchmarks for pallet-xcm --- cumulus/parachain-template/runtime/src/xcm_config.rs | 7 ++----- .../assets/asset-hub-kusama/src/xcm_config.rs | 8 ++++---- .../assets/asset-hub-polkadot/src/xcm_config.rs | 8 ++++---- .../assets/asset-hub-rococo/src/xcm_config.rs | 8 ++++---- .../assets/asset-hub-westend/src/xcm_config.rs | 8 ++++---- .../bridge-hubs/bridge-hub-kusama/src/xcm_config.rs | 2 +- .../bridge-hub-polkadot/src/xcm_config.rs | 2 +- .../bridge-hubs/bridge-hub-rococo/src/xcm_config.rs | 2 +- .../collectives-polkadot/src/xcm_config.rs | 2 +- .../contracts/contracts-rococo/src/xcm_config.rs | 9 +++------ .../runtimes/testing/penpal/src/xcm_config.rs | 2 +- .../runtimes/testing/rococo-parachain/src/lib.rs | 12 ++---------- polkadot/runtime/rococo/src/xcm_config.rs | 2 +- polkadot/runtime/westend/src/xcm_config.rs | 6 +++--- 14 files changed, 32 insertions(+), 46 deletions(-) diff --git a/cumulus/parachain-template/runtime/src/xcm_config.rs b/cumulus/parachain-template/runtime/src/xcm_config.rs index 0b82dba25f28..9f7de9895fae 100644 --- a/cumulus/parachain-template/runtime/src/xcm_config.rs +++ b/cumulus/parachain-template/runtime/src/xcm_config.rs @@ -155,11 +155,8 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Teleports are disabled pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - // We can reserve transfer relay/native token between us and Relay. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); + // Reserve transfers are disabled. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index 5cd821fe9aa8..ea28ec91832a 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -557,13 +557,13 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported between AH and Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); - // We can reserve transfer some local token to Relay. + // We can reserve transfer native token to some random parachain. pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), - Parent.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), + Parachain(43211234).into(), )); } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index d23e209adcef..71dc71f477e1 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -481,13 +481,13 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported between AH and Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); - // We can reserve transfer some local token to Relay. + // We can reserve transfer native token to some random parachain. pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), - Parent.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), + Parachain(43211234).into(), )); } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 8127dbfb87f7..441589aa8641 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -660,13 +660,13 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported between AH and Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); - // We can reserve transfer some local token to Relay. + // We can reserve transfer native token to some random parachain. pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), - Parent.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), + Parachain(43211234).into(), )); } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 08d27d7de573..dc4e4372816d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -590,13 +590,13 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported between AH and Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); - // We can reserve transfer some local token to Relay. + // We can reserve transfer native token to some random parachain. pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), - Parent.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), + Parachain(43211234).into(), )); } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs index 99b00c641e27..e65f346137bf 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs @@ -246,7 +246,7 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported between BH and Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); // Reserve transfers are disabled on BH. diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs index c4827268362c..1a3d4a938a97 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs @@ -250,7 +250,7 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported between BH and Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); // Reserve transfers are disabled on BH. diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 03909a68f7dc..6646e5edf94f 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -319,7 +319,7 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported between BH and Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); // Reserve transfers are disabled on BH. diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs index b6496ddc5056..1f673a1ee29b 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs @@ -298,7 +298,7 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported between BH and Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); // Reserve transfers are disabled on Collectives. diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs index d02bcff4150c..fc55fc6a4cb4 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs @@ -228,14 +228,11 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported to Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); - // Act as reserve for native token when sending to random parachain. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), - Parachain(4321).into(), - )); + // Reserve transfers are disabled on Contracts. + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index 289f920253b6..a17f8e5b99ac 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -317,7 +317,7 @@ parameter_types! { pub ReachableDest: Option = Some(Parent.into()); // Relay/native token can be teleported to Relay. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), Parent.into(), )); // Disable reserve transfers benchmarks for penpal. diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 78cefad66372..84181b1da31d 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -470,16 +470,8 @@ pub type XcmRouter = WithUniqueTopic<( #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported to/from Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // We can reserve transfer some AH local token to/from AH. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(SystemAssetHubLocation::get()) }.into(), - SystemAssetHubLocation::get(), - )); + pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; + pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; } impl pallet_xcm::Config for Runtime { diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index da0aabfbaea5..24333aea9d91 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -218,7 +218,7 @@ parameter_types! { // We can reserve transfer native token to some random parachain. pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }.into(), - Parachain(4321).into(), + Parachain(43211234).into(), )); } diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index fe61725bd6d8..9e90b5640fb9 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -124,13 +124,13 @@ parameter_types! { pub ReachableDest: Option = Some(Parachain(ASSET_HUB_ID).into()); // Relay/native token can be teleported to/from AH. pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }.into(), AssetHub::get(), )); // We can reserve transfer native token to some random parachain. pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Here.into()) }.into(), - Parachain(4321).into(), + MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }.into(), + Parachain(43211234).into(), )); } From b648df2ba4b31e2bf45b2e1da2596de2ff6bee1a Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 27 Oct 2023 16:07:37 +0300 Subject: [PATCH 075/124] AHs simplify test_cases_over_bridge --- .../test-utils/src/test_cases_over_bridge.rs | 87 +++++-------------- 1 file changed, 21 insertions(+), 66 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index 9d8ca0e0042a..2cb304d22388 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -16,7 +16,7 @@ //! Module contains predefined test-case scenarios for `Runtime` with various assets transferred //! over a bridge. -use crate::assert_matches_reserve_asset_deposited_instructions; +use crate::{assert_matches_reserve_asset_deposited_instructions, get_fungible_delivery_fees}; use codec::Encode; use cumulus_primitives_core::XcmpMessageSource; use frame_support::{ @@ -32,10 +32,7 @@ use parachains_runtimes_test_utils::{ use sp_runtime::{traits::StaticLookup, Saturating}; use xcm::{latest::prelude::*, VersionedMultiAssets}; use xcm_builder::{CreateMatcher, MatchXcm}; -use xcm_executor::{ - traits::{ConvertLocation, TransactAsset}, - XcmExecutor, -}; +use xcm_executor::{traits::ConvertLocation, XcmExecutor}; pub struct TestBridgingConfig { pub bridged_network: NetworkId, @@ -129,9 +126,13 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< &alice, ); - // drip ED to account + // we calculate exact delivery fees _after_ sending the message by weighing the sent + // xcm, and this delivery fee varies for different runtimes, so just add enough buffer, + // then verify the arithmetics check out on final balance. + let delivery_fees_buffer = 40_000_000_000u128; + // drip ED + transfer_amount + delivery_fees_buffer to Alice account let alice_account_init_balance = - existential_deposit.saturating_mul(2.into()) + balance_to_transfer.into(); + existential_deposit + balance_to_transfer.into() + delivery_fees_buffer.into(); let _ = >::deposit_creating( &alice_account, alice_account_init_balance, @@ -184,56 +185,6 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< let expected_beneficiary = target_destination_account; - // Make sure sender has enough funds for paying delivery fees - let handling_delivery_fees = { - // Probable XCM with `ReserveAssetDeposited`. - let mut expected_reserve_asset_deposited_message = Xcm(vec![ - ReserveAssetDeposited(MultiAssets::from(expected_assets.clone())), - ClearOrigin, - BuyExecution { - fees: MultiAsset { - id: Concrete(Default::default()), - fun: Fungible(balance_to_transfer), - }, - weight_limit: Unlimited, - }, - DepositAsset { assets: Wild(AllCounted(1)), beneficiary: expected_beneficiary }, - SetTopic([ - 220, 188, 144, 32, 213, 83, 111, 175, 44, 210, 111, 19, 90, 165, 191, 112, - 140, 247, 192, 124, 42, 17, 153, 141, 114, 34, 189, 20, 83, 69, 237, 173, - ]), - ]); - assert_matches_reserve_asset_deposited_instructions( - &mut expected_reserve_asset_deposited_message, - &expected_assets, - &expected_beneficiary, - ); - - // Call `SendXcm::validate` to get delivery fees. - let (_, delivery_fees): (_, MultiAssets) = XcmConfig::XcmSender::validate( - &mut Some(target_location_from_different_consensus), - &mut Some(expected_reserve_asset_deposited_message), - ) - .expect("validate passes"); - // Drip delivery fee to Alice account. - let mut delivery_fees_added = false; - for delivery_fee in delivery_fees.inner() { - assert_ok!(::deposit_asset( - &delivery_fee, - &MultiLocation { - parents: 0, - interior: X1(AccountId32 { - network: None, - id: alice_account.clone().into(), - }), - }, - None, - )); - delivery_fees_added = true; - } - delivery_fees_added - }; - // do pallet_xcm call reserve transfer assert_ok!(>::limited_reserve_transfer_assets( RuntimeHelper::::origin_of(alice_account.clone()), @@ -276,6 +227,7 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< // check sent XCM ExportMessage to BridgeHub + let mut delivery_fees = 0; // 1. check paid or unpaid if let Some(expected_fee_asset_id) = maybe_paid_export_message { xcm_sent @@ -316,6 +268,10 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< .split_global() .expect("split works"); assert_eq!(destination, &target_location_junctions_without_global_consensus); + // Call `SendXcm::validate` to get delivery fees. + delivery_fees = get_fungible_delivery_fees::< + ::XcmSender, + >(target_location_from_different_consensus, inner_xcm.clone()); assert_matches_reserve_asset_deposited_instructions( inner_xcm, &expected_assets, @@ -331,8 +287,8 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< assert_eq!( >::free_balance(&alice_account), alice_account_init_balance - .saturating_sub(existential_deposit) .saturating_sub(balance_to_transfer.into()) + .saturating_sub(delivery_fees.into()) ); // check reserve account increased by balance_to_transfer @@ -342,14 +298,13 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< ); // check dedicated account increased by delivery fees (if configured) - if handling_delivery_fees { - if let Some(delivery_fees_account) = delivery_fees_account { - let delivery_fees_account_balance_after = - >::free_balance(&delivery_fees_account); - assert!( - delivery_fees_account_balance_after > delivery_fees_account_balance_before - ); - } + if let Some(delivery_fees_account) = delivery_fees_account { + let delivery_fees_account_balance_after = + >::free_balance(&delivery_fees_account); + assert!( + delivery_fees_account_balance_after - delivery_fees.into() >= + delivery_fees_account_balance_before + ); } }) } From da7d8ff110fe9ee1aca3df47e438c42dc232165e Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 27 Oct 2023 18:04:18 +0300 Subject: [PATCH 076/124] runtimes: add dedicated benchmarking config for pallet-xcm --- .../runtime/src/xcm_config.rs | 15 ---- .../assets/asset-hub-kusama/src/lib.rs | 36 +++++++++- .../assets/asset-hub-kusama/src/xcm_config.rs | 21 ------ .../assets/asset-hub-polkadot/src/lib.rs | 36 +++++++++- .../asset-hub-polkadot/src/xcm_config.rs | 21 ------ .../assets/asset-hub-rococo/src/lib.rs | 36 +++++++++- .../assets/asset-hub-rococo/src/xcm_config.rs | 21 ------ .../assets/asset-hub-westend/src/lib.rs | 36 +++++++++- .../asset-hub-westend/src/xcm_config.rs | 21 ------ .../bridge-hubs/bridge-hub-kusama/src/lib.rs | 26 ++++++- .../bridge-hub-kusama/src/xcm_config.rs | 18 ----- .../bridge-hub-polkadot/src/lib.rs | 26 ++++++- .../bridge-hub-polkadot/src/xcm_config.rs | 18 ----- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 26 ++++++- .../bridge-hub-rococo/src/xcm_config.rs | 18 ----- .../collectives-polkadot/src/lib.rs | 26 ++++++- .../collectives-polkadot/src/xcm_config.rs | 18 ----- .../contracts/contracts-rococo/src/lib.rs | 27 +++++++- .../contracts-rococo/src/xcm_config.rs | 18 ----- .../runtimes/testing/penpal/src/xcm_config.rs | 18 ----- .../testing/rococo-parachain/src/lib.rs | 13 ---- polkadot/runtime/rococo/src/lib.rs | 32 ++++++++- polkadot/runtime/rococo/src/xcm_config.rs | 21 ------ .../runtime/test-runtime/src/xcm_config.rs | 13 ---- polkadot/runtime/westend/src/lib.rs | 31 ++++++++- polkadot/runtime/westend/src/xcm_config.rs | 21 ------ polkadot/xcm/pallet-xcm/src/benchmarking.rs | 69 ++++++++++++++----- polkadot/xcm/pallet-xcm/src/lib.rs | 22 +----- polkadot/xcm/pallet-xcm/src/mock.rs | 40 +++++------ .../xcm/xcm-builder/src/tests/pay/mock.rs | 13 ---- polkadot/xcm/xcm-builder/tests/mock/mod.rs | 13 ---- .../xcm-simulator/example/src/parachain.rs | 13 ---- .../xcm-simulator/example/src/relay_chain.rs | 13 ---- .../xcm/xcm-simulator/fuzzer/src/parachain.rs | 13 ---- .../xcm-simulator/fuzzer/src/relay_chain.rs | 13 ---- 35 files changed, 397 insertions(+), 425 deletions(-) diff --git a/cumulus/parachain-template/runtime/src/xcm_config.rs b/cumulus/parachain-template/runtime/src/xcm_config.rs index 9f7de9895fae..752137c96f18 100644 --- a/cumulus/parachain-template/runtime/src/xcm_config.rs +++ b/cumulus/parachain-template/runtime/src/xcm_config.rs @@ -150,15 +150,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Teleports are disabled - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - // Reserve transfers are disabled. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = EnsureXcmOrigin; @@ -187,12 +178,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index bc17fcada23f..f83ed416f327 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -929,7 +929,7 @@ mod benches { [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] // XCM - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] @@ -1167,6 +1167,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -1210,6 +1211,39 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported between AH and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parent.into(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // AH can reserve transfer native token to some random parachain. + let random_para_id = 43211234; + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( + random_para_id.into() + ); + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parachain(random_para_id).into(), + )) + } + } + use xcm::latest::prelude::*; use xcm_config::{KsmLocation, MaxAssetsIntoHolding}; use pallet_xcm_benchmarks::asset_instance_from; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index ea28ec91832a..176a6d023178 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -552,21 +552,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported between AH and Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // We can reserve transfer native token to some random parachain. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parachain(43211234).into(), - )); -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // We want to disallow users sending (arbitrary) XCMs from this chain. @@ -599,12 +584,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index 7033e1c2dcac..d2f318ab11e7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -833,7 +833,7 @@ mod benches { [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] // XCM - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] @@ -1047,6 +1047,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -1089,6 +1090,39 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported between AH and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parent.into(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // AH can reserve transfer native token to some random parachain. + let random_para_id = 43211234; + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( + random_para_id.into() + ); + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parachain(random_para_id).into(), + )) + } + } + use xcm::latest::prelude::*; use xcm_config::{DotLocation, MaxAssetsIntoHolding}; use pallet_xcm_benchmarks::asset_instance_from; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index 71dc71f477e1..3910e68bf206 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -476,21 +476,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported between AH and Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // We can reserve transfer native token to some random parachain. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parachain(43211234).into(), - )); -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // We want to disallow users sending (arbitrary) XCMs from this chain. @@ -523,12 +508,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 1ce504d6704f..44fa05b9924e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1008,7 +1008,7 @@ mod benches { [pallet_xcm_bridge_hub_router, ToWococo] [pallet_xcm_bridge_hub_router, ToRococo] // XCM - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] @@ -1246,6 +1246,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; // This is defined once again in dispatch_benchmark, because list_benchmarks! @@ -1298,6 +1299,39 @@ impl_runtime_apis! { Config as XcmBridgeHubRouterConfig, }; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported between AH and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parent.into(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // AH can reserve transfer native token to some random parachain. + let random_para_id = 43211234; + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( + random_para_id.into() + ); + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parachain(random_para_id).into(), + )) + } + } + impl XcmBridgeHubRouterConfig for Runtime { fn make_congested() { cumulus_pallet_xcmp_queue::bridging::suspend_channel_for_benchmarks::( diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 441589aa8641..6aebaf9be6d2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -655,21 +655,6 @@ pub type XcmRouter = WithUniqueTopic<( ToRococoXcmRouter, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported between AH and Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // We can reserve transfer native token to some random parachain. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parachain(43211234).into(), - )); -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // We want to disallow users sending (arbitrary) XCMs from this chain. @@ -709,12 +694,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index 30d384222422..af7e41f81236 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -947,7 +947,7 @@ mod benches { [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] // XCM - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] @@ -1231,6 +1231,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -1274,6 +1275,39 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported between AH and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parent.into(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // AH can reserve transfer native token to some random parachain. + let random_para_id = 43211234; + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( + random_para_id.into() + ); + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parachain(random_para_id).into(), + )) + } + } + use xcm::latest::prelude::*; use xcm_config::{MaxAssetsIntoHolding, WestendLocation}; use pallet_xcm_benchmarks::asset_instance_from; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index dc4e4372816d..373d6dc3b588 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -585,21 +585,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported between AH and Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // We can reserve transfer native token to some random parachain. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parachain(43211234).into(), - )); -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = EnsureXcmOrigin; @@ -628,12 +613,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs index 9fdf8380bc3a..7ff1e1cdb356 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs @@ -456,7 +456,7 @@ mod benches { [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] // XCM - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] @@ -636,6 +636,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -671,6 +672,29 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported between BH and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parent.into(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Reserve transfers are disabled on BH. + None + } + } + use xcm::latest::prelude::*; use xcm_config::KsmRelayLocation; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs index e65f346137bf..218da1a9bb61 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs @@ -241,18 +241,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported between BH and Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // Reserve transfers are disabled on BH. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // We want to disallow users sending (arbitrary) XCMs from this chain. @@ -284,12 +272,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs index 6ce1df992957..39238689d458 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs @@ -456,7 +456,7 @@ mod benches { [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] // XCM - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] @@ -636,6 +636,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -671,6 +672,29 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported between BH and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parent.into(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Reserve transfers are disabled on BH. + None + } + } + use xcm::latest::prelude::*; use xcm_config::DotRelayLocation; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs index 1a3d4a938a97..727990d85f49 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs @@ -245,18 +245,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported between BH and Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // Reserve transfers are disabled on BH. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // We want to disallow users sending (arbitrary) XCMs from this chain. @@ -288,12 +276,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 326acc812a27..77f6d8cdd1ea 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -535,7 +535,7 @@ mod benches { [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] // XCM - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] @@ -816,6 +816,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -860,6 +861,29 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported between BH and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parent.into(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Reserve transfers are disabled on BH. + None + } + } + use xcm::latest::prelude::*; use xcm_config::TokenLocation; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 6646e5edf94f..01624c574344 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -314,18 +314,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported between BH and Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // Reserve transfers are disabled on BH. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type XcmRouter = XcmRouter; @@ -356,12 +344,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs index edfbfa851fe3..258ecd54f901 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs @@ -719,7 +719,7 @@ mod benches { [cumulus_pallet_xcmp_queue, XcmpQueue] [pallet_alliance, Alliance] [pallet_collective, AllianceMotion] - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] [pallet_preimage, Preimage] [pallet_scheduler, Scheduler] [pallet_referenda, FellowshipReferenda] @@ -907,6 +907,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -936,6 +937,29 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported between Collectives and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parent.into(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Reserve transfers are disabled on Collectives. + None + } + } + let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs index 1f673a1ee29b..cab853741ded 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/xcm_config.rs @@ -293,18 +293,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported between BH and Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // Reserve transfers are disabled on Collectives. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - /// Type to convert the Fellows origin to a Plurality `MultiLocation` value. pub type FellowsToPlurality = OriginToPluralityVoice; @@ -335,12 +323,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 71733d48e815..4353d209fe21 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -405,7 +405,7 @@ mod benches { [pallet_timestamp, Timestamp] [pallet_collator_selection, CollatorSelection] [pallet_contracts, Contracts] - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] ); } @@ -650,6 +650,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -679,6 +680,30 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use xcm::latest::prelude::*; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported between Contracts-System-Para and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }.into(), + Parent.into(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Reserve transfers are disabled on Contracts-System-Para. + None + } + } + let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs index fc55fc6a4cb4..ef52ac002412 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/xcm_config.rs @@ -223,18 +223,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported to Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // Reserve transfers are disabled on Contracts. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; // We want to disallow users sending (arbitrary) XCMs from this chain. @@ -264,12 +252,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index a17f8e5b99ac..542d07fbed95 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -312,18 +312,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - // Relay/native token can be teleported to Relay. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parent.into(), - )); - // Disable reserve transfers benchmarks for penpal. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = EnsureXcmOrigin; @@ -352,12 +340,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs index 84181b1da31d..01fcd4d3c1d5 100644 --- a/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/rococo-parachain/src/lib.rs @@ -467,13 +467,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = EnsureXcmOrigin; @@ -498,12 +491,6 @@ impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index e6ad061ce069..6171576d30c0 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -1572,7 +1572,7 @@ mod benches { [pallet_asset_rate, AssetRate] [pallet_whitelist, Whitelist] // XCM - [pallet_xcm, XcmPallet] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] [pallet_xcm_benchmarks::fungible, pallet_xcm_benchmarks::fungible::Pallet::] [pallet_xcm_benchmarks::generic, pallet_xcm_benchmarks::generic::Pallet::] ); @@ -2048,6 +2048,8 @@ sp_api::impl_runtime_apis! { use frame_system_benchmarking::Pallet as SystemBench; use frame_benchmarking::baseline::Pallet as Baseline; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -2065,6 +2067,7 @@ sp_api::impl_runtime_apis! { use frame_benchmarking::{Benchmarking, BenchmarkBatch, BenchmarkError}; use frame_system_benchmarking::Pallet as SystemBench; use frame_benchmarking::baseline::Pallet as Baseline; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; use sp_storage::TrackedStorageKey; use xcm::latest::prelude::*; use xcm_config::{ @@ -2081,6 +2084,33 @@ sp_api::impl_runtime_apis! { impl frame_system_benchmarking::Config for Runtime {} impl frame_benchmarking::baseline::Config for Runtime {} + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(crate::xcm_config::AssetHub::get()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported to/from AH. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Here.into()) + }.into(), + crate::xcm_config::AssetHub::get(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay can reserve transfer native token to some random parachain. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Here.into()) + }.into(), + Parachain(43211234).into(), + )) + } + } impl pallet_xcm_benchmarks::Config for Runtime { type XcmConfig = XcmConfig; type AccountIdConverter = LocationConverter; diff --git a/polkadot/runtime/rococo/src/xcm_config.rs b/polkadot/runtime/rococo/src/xcm_config.rs index 24333aea9d91..54828e0b8a60 100644 --- a/polkadot/runtime/rococo/src/xcm_config.rs +++ b/polkadot/runtime/rococo/src/xcm_config.rs @@ -207,21 +207,6 @@ parameter_types! { pub const FellowsBodyId: BodyId = BodyId::Technical; } -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parachain(ASSET_HUB_ID).into()); - // Relay/native token can be teleported to/from AH. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }.into(), - AssetHub::get(), - )); - // We can reserve transfer native token to some random parachain. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }.into(), - Parachain(43211234).into(), - )); -} - /// Type to convert an `Origin` type value into a `MultiLocation` value which represents an interior /// location of this chain. pub type LocalOriginToLocation = ( @@ -276,10 +261,4 @@ impl pallet_xcm::Config for Runtime { type RemoteLockConsumerIdentifier = (); type WeightInfo = crate::weights::pallet_xcm::WeightInfo; type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } diff --git a/polkadot/runtime/test-runtime/src/xcm_config.rs b/polkadot/runtime/test-runtime/src/xcm_config.rs index aa9e29795fcb..ae4faecf7001 100644 --- a/polkadot/runtime/test-runtime/src/xcm_config.rs +++ b/polkadot/runtime/test-runtime/src/xcm_config.rs @@ -127,13 +127,6 @@ impl xcm_executor::Config for XcmConfig { type Aliasers = Nothing; } -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(xcm::latest::Junctions::Here.into()); - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for crate::Runtime { // The config types here are entirely configurable, since the only one that is sorely needed // is `XcmExecutor`, which will be used in unit tests located in xcm-executor. @@ -160,10 +153,4 @@ impl pallet_xcm::Config for crate::Runtime { type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 9ee4f3cf23e5..79145855d71a 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -1616,7 +1616,7 @@ mod benches { [pallet_whitelist, Whitelist] [pallet_asset_rate, AssetRate] // XCM - [pallet_xcm, XcmPallet] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] @@ -2131,6 +2131,7 @@ sp_api::impl_runtime_apis! { use pallet_session_benchmarking::Pallet as SessionBench; use pallet_offences_benchmarking::Pallet as OffencesBench; use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; use frame_system_benchmarking::Pallet as SystemBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; @@ -2158,12 +2159,40 @@ sp_api::impl_runtime_apis! { use pallet_session_benchmarking::Pallet as SessionBench; use pallet_offences_benchmarking::Pallet as OffencesBench; use pallet_election_provider_support_benchmarking::Pallet as ElectionProviderBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; use frame_system_benchmarking::Pallet as SystemBench; use pallet_nomination_pools_benchmarking::Pallet as NominationPoolsBench; impl pallet_session_benchmarking::Config for Runtime {} impl pallet_offences_benchmarking::Config for Runtime {} impl pallet_election_provider_support_benchmarking::Config for Runtime {} + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(crate::xcm_config::AssetHub::get()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay/native token can be teleported to/from AH. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Here.into()) + }.into(), + crate::xcm_config::AssetHub::get(), + )) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + // Relay can reserve transfer native token to some random parachain. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Here.into()) + }.into(), + crate::Junction::Parachain(43211234).into(), + )) + } + } impl frame_system_benchmarking::Config for Runtime {} impl pallet_nomination_pools_benchmarking::Config for Runtime {} impl runtime_parachains::disputes::slashing::benchmarking::Config for Runtime {} diff --git a/polkadot/runtime/westend/src/xcm_config.rs b/polkadot/runtime/westend/src/xcm_config.rs index 9e90b5640fb9..470f1252b191 100644 --- a/polkadot/runtime/westend/src/xcm_config.rs +++ b/polkadot/runtime/westend/src/xcm_config.rs @@ -119,21 +119,6 @@ parameter_types! { pub const MaxAssetsIntoHolding: u32 = 64; } -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parachain(ASSET_HUB_ID).into()); - // Relay/native token can be teleported to/from AH. - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }.into(), - AssetHub::get(), - )); - // We can reserve transfer native token to some random parachain. - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { fun: Fungible(crate::EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }.into(), - Parachain(43211234).into(), - )); -} - pub type TrustedTeleporters = ( xcm_builder::Case, xcm_builder::Case, @@ -273,10 +258,4 @@ impl pallet_xcm::Config for Runtime { type RemoteLockConsumerIdentifier = (); type WeightInfo = crate::weights::pallet_xcm::WeightInfo; type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index b0a37db6a783..ab2941b10de3 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -25,7 +25,40 @@ use xcm::{latest::prelude::*, v2}; type RuntimeOrigin = ::RuntimeOrigin; // existential deposit multiplier -const ED_MULTIPLIER: u32 = 10; +const ED_MULTIPLIER: u32 = 100; + +/// Pallet we're benchmarking here. +pub struct Pallet(crate::Pallet); + +/// Trait that must be implemented by runtime to be able to benchmark pallet properly. +pub trait Config: crate::Config { + /// A `MultiLocation` that can be reached via `XcmRouter`. Used only in benchmarks. + /// + /// If `None`, the benchmarks that depend on a reachable destination will be skipped. + fn reachable_dest() -> Option { + None + } + + /// A `(MultiAssets, MultiLocation)` pair representing assets and the destination they can + /// be teleported to. Used only in benchmarks. + /// + /// Implementation should also make sure `dest` is reachable/connected. + /// + /// If `None`, the benchmarks that depend on this will be skipped. + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + None + } + + /// A `(MultiAssets, MultiLocation)` pair representing assets and the destination they can + /// be reserve-transferred to. Used only in benchmarks. + /// + /// Implementation should also make sure `dest` is reachable/connected. + /// + /// If `None`, the benchmarks that depend on this will be skipped. + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + None + } +} benchmarks! { where_clause { @@ -40,7 +73,7 @@ benchmarks! { return Err(BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX))) } let msg = Xcm(vec![ClearOrigin]); - let versioned_dest: VersionedMultiLocation = T::ReachableDest::get().ok_or( + let versioned_dest: VersionedMultiLocation = T::reachable_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )? .into(); @@ -48,7 +81,7 @@ benchmarks! { }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_msg)) teleport_assets { - let (assets, destination) = T::TeleportableAssets::get().ok_or( + let (assets, destination) = T::teleportable_assets_and_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; @@ -92,7 +125,7 @@ benchmarks! { } reserve_transfer_assets { - let (assets, destination) = T::ReserveTransferableAssets::get().ok_or( + let (assets, destination) = T::reserve_transferable_assets_and_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; @@ -148,7 +181,7 @@ benchmarks! { }: _>(execute_origin, Box::new(versioned_msg), Weight::zero()) force_xcm_version { - let loc = T::ReachableDest::get().ok_or( + let loc = T::reachable_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; let xcm_version = 2; @@ -157,18 +190,18 @@ benchmarks! { force_default_xcm_version {}: _(RawOrigin::Root, Some(2)) force_subscribe_version_notify { - let versioned_loc: VersionedMultiLocation = T::ReachableDest::get().ok_or( + let versioned_loc: VersionedMultiLocation = T::reachable_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )? .into(); }: _(RawOrigin::Root, Box::new(versioned_loc)) force_unsubscribe_version_notify { - let loc = T::ReachableDest::get().ok_or( + let loc = T::reachable_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; let versioned_loc: VersionedMultiLocation = loc.into(); - let _ = Pallet::::request_version_notify(loc); + let _ = crate::Pallet::::request_version_notify(loc); }: _(RawOrigin::Root, Box::new(versioned_loc)) force_suspension {}: _(RawOrigin::Root, true) @@ -178,7 +211,7 @@ benchmarks! { let loc = VersionedMultiLocation::from(MultiLocation::from(Parent)); SupportedVersion::::insert(old_version, loc, old_version); }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateSupportedVersion, Weight::zero()); + crate::Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateSupportedVersion, Weight::zero()); } migrate_version_notifiers { @@ -186,22 +219,22 @@ benchmarks! { let loc = VersionedMultiLocation::from(MultiLocation::from(Parent)); VersionNotifiers::::insert(old_version, loc, 0); }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateVersionNotifiers, Weight::zero()); + crate::Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateVersionNotifiers, Weight::zero()); } already_notified_target { - let loc = T::ReachableDest::get().ok_or( + let loc = T::reachable_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(T::DbWeight::get().reads(1))), )?; let loc = VersionedMultiLocation::from(loc); let current_version = T::AdvertisedXcmVersion::get(); VersionNotifyTargets::::insert(current_version, loc, (0, Weight::zero(), current_version)); }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero()); + crate::Pallet::::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero()); } notify_current_targets { - let loc = T::ReachableDest::get().ok_or( + let loc = T::reachable_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(T::DbWeight::get().reads_writes(1, 3))), )?; let loc = VersionedMultiLocation::from(loc); @@ -209,7 +242,7 @@ benchmarks! { let old_version = current_version - 1; VersionNotifyTargets::::insert(current_version, loc, (0, Weight::zero(), old_version)); }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero()); + crate::Pallet::::check_xcm_version_change(VersionMigrationStage::NotifyCurrentTargets(None), Weight::zero()); } notify_target_migration_fail { @@ -223,7 +256,7 @@ benchmarks! { let current_version = T::AdvertisedXcmVersion::get(); VersionNotifyTargets::::insert(current_version, bad_loc, (0, Weight::zero(), current_version)); }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); + crate::Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); } migrate_version_notify_targets { @@ -232,18 +265,18 @@ benchmarks! { let loc = VersionedMultiLocation::from(MultiLocation::from(Parent)); VersionNotifyTargets::::insert(old_version, loc, (0, Weight::zero(), current_version)); }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); + crate::Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); } migrate_and_notify_old_targets { - let loc = T::ReachableDest::get().ok_or( + let loc = T::reachable_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(T::DbWeight::get().reads_writes(1, 3))), )?; let loc = VersionedMultiLocation::from(loc); let old_version = T::AdvertisedXcmVersion::get() - 1; VersionNotifyTargets::::insert(old_version, loc, (0, Weight::zero(), old_version)); }: { - Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); + crate::Pallet::::check_xcm_version_change(VersionMigrationStage::MigrateAndNotifyOldTargets, Weight::zero()); } impl_benchmark_test_suite!( diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 8d9bc7373c6c..186dd2d51197 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -19,7 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "runtime-benchmarks")] -mod benchmarking; +pub mod benchmarking; #[cfg(test)] mod mock; #[cfg(test)] @@ -261,26 +261,6 @@ pub mod pallet { /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; - - /// A `MultiLocation` that can be reached via `XcmRouter`. Used only in benchmarks. - /// - /// If `None`, the benchmarks that depend on a reachable destination will be skipped. - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest: Get>; - - /// A `(MultiAssets, MultiLocation)` pair representing assets and the destination they can - /// be teleported to. Used only in benchmarks. - /// - /// If `None`, the benchmarks that depend on `TeleportableAssets` will be skipped. - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets: Get>; - - /// A `(MultiAssets, MultiLocation)` pair representing assets and the destination they can - /// be reserve-transferred to. Used only in benchmarks. - /// - /// If `None`, the benchmarks that depend on `ReserveTransferableAssets` will be skipped. - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets: Get>; } #[pallet::event] diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index e421d46f206b..b88734b9abfb 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -498,22 +498,6 @@ parameter_types! { pub static AdvertisedXcmVersion: pallet_xcm::XcmVersion = 3; } -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parachain(1000).into()); - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - NativeAsset::get().into(), - SystemParachainLocation::get(), - )); - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = Some(( - MultiAsset { - fun: Fungible(10), - id: Concrete(Here.into_location()), - }.into(), - Parachain(OTHER_PARA_ID).into(), - )); -} - impl pallet_xcm::Config for Test { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; @@ -538,12 +522,6 @@ impl pallet_xcm::Config for Test { type MaxRemoteLockConsumers = frame_support::traits::ConstU32<0>; type RemoteLockConsumerIdentifier = (); type WeightInfo = TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl origin::Config for Test {} @@ -554,6 +532,24 @@ impl pallet_test_notifier::Config for Test { type RuntimeCall = RuntimeCall; } +#[cfg(feature = "runtime-benchmarks")] +impl super::benchmarking::Config for Test { + fn reachable_dest() -> Option { + Some(Parachain(1000).into()) + } + + fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + Some((NativeAsset::get().into(), SystemParachainLocation::get())) + } + + fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + Some(( + MultiAsset { fun: Fungible(10), id: Concrete(Here.into_location()) }.into(), + Parachain(OTHER_PARA_ID).into(), + )) + } +} + pub(crate) fn last_event() -> RuntimeEvent { System::events().pop().expect("RuntimeEvent expected").event } diff --git a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs index b4c2d9ae3dc7..78b9284c689f 100644 --- a/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs +++ b/polkadot/xcm/xcm-builder/src/tests/pay/mock.rs @@ -246,13 +246,6 @@ type SovereignAccountOf = ( HashedDescription>, ); -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parachain(1000).into()); - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Test { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = EnsureXcmOrigin; @@ -277,12 +270,6 @@ impl pallet_xcm::Config for Test { type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } pub const UNITS: Balance = 1_000_000_000_000; diff --git a/polkadot/xcm/xcm-builder/tests/mock/mod.rs b/polkadot/xcm/xcm-builder/tests/mock/mod.rs index c9c57d8bf7ad..4f183c7a15b6 100644 --- a/polkadot/xcm/xcm-builder/tests/mock/mod.rs +++ b/polkadot/xcm/xcm-builder/tests/mock/mod.rs @@ -210,13 +210,6 @@ impl xcm_executor::Config for XcmConfig { pub type LocalOriginToLocation = SignedToAccountId32; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Here.into()); - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type UniversalLocation = UniversalLocation; @@ -242,12 +235,6 @@ impl pallet_xcm::Config for Runtime { type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } impl origin::Config for Runtime {} diff --git a/polkadot/xcm/xcm-simulator/example/src/parachain.rs b/polkadot/xcm/xcm-simulator/example/src/parachain.rs index 0e1e3fd8f89f..9f0411970ce7 100644 --- a/polkadot/xcm/xcm-simulator/example/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/parachain.rs @@ -399,13 +399,6 @@ impl mock_msg_queue::Config for Runtime { pub type LocalOriginToLocation = SignedToAccountId32; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - pub struct TrustedLockerCase(PhantomData); impl> ContainsPair for TrustedLockerCase @@ -446,12 +439,6 @@ impl pallet_xcm::Config for Runtime { type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } type Block = frame_system::mocking::MockBlock; diff --git a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs index f68e94df1fa0..bdd7ff6d3eaf 100644 --- a/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/example/src/relay_chain.rs @@ -199,13 +199,6 @@ impl Config for XcmConfig { pub type LocalOriginToLocation = SignedToAccountId32; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parachain(1).into()); - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; @@ -231,12 +224,6 @@ impl pallet_xcm::Config for Runtime { type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } parameter_types! { diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs index f47476dcb615..41234837aca0 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/parachain.rs @@ -313,13 +313,6 @@ impl mock_msg_queue::Config for Runtime { pub type LocalOriginToLocation = SignedToAccountId32; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = EnsureXcmOrigin; @@ -344,12 +337,6 @@ impl pallet_xcm::Config for Runtime { type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } type Block = frame_system::mocking::MockBlock; diff --git a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs index 2a843acf62c1..c9a57db970a7 100644 --- a/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs +++ b/polkadot/xcm/xcm-simulator/fuzzer/src/relay_chain.rs @@ -163,13 +163,6 @@ impl Config for XcmConfig { pub type LocalOriginToLocation = SignedToAccountId32; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parachain(1).into()); - pub TeleportableAssets: Option<(MultiAssets, MultiLocation)> = None; - pub ReserveTransferableAssets: Option<(MultiAssets, MultiLocation)> = None; -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; @@ -195,12 +188,6 @@ impl pallet_xcm::Config for Runtime { type RemoteLockConsumerIdentifier = (); type WeightInfo = pallet_xcm::TestWeightInfo; type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - #[cfg(feature = "runtime-benchmarks")] - type TeleportableAssets = TeleportableAssets; - #[cfg(feature = "runtime-benchmarks")] - type ReserveTransferableAssets = ReserveTransferableAssets; } parameter_types! { From 8d85faa3e65c2eb29533d43ae8795e4c991df7b7 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Sat, 28 Oct 2023 11:49:51 +0300 Subject: [PATCH 077/124] AHs benchmarks: fix transfer to sibling parachain --- cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs | 2 +- .../parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs | 2 +- cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs | 2 +- cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index f83ed416f327..25d5712f4dfb 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -1239,7 +1239,7 @@ impl_runtime_apis! { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parachain(random_para_id).into(), + ParentThen(Parachain(random_para_id).into()).into(), )) } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index d2f318ab11e7..dd111355c02b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -1118,7 +1118,7 @@ impl_runtime_apis! { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parachain(random_para_id).into(), + ParentThen(Parachain(random_para_id).into()).into(), )) } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 44fa05b9924e..1f54c3ca997b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1327,7 +1327,7 @@ impl_runtime_apis! { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parachain(random_para_id).into(), + ParentThen(Parachain(random_para_id).into()).into(), )) } } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index af7e41f81236..cc04db22785b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1303,7 +1303,7 @@ impl_runtime_apis! { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) }.into(), - Parachain(random_para_id).into(), + ParentThen(Parachain(random_para_id).into()).into(), )) } } From fd8f5f3ca9930ccfa39651eb9be41391d0b5a6d9 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Sun, 29 Oct 2023 20:36:58 +0200 Subject: [PATCH 078/124] fixed token transfer test --- .../runtimes/assets/asset-hub-rococo/src/xcm_config.rs | 9 +++++---- .../parachains/runtimes/assets/common/src/matching.rs | 5 ----- .../bridge-hubs/bridge-hub-rococo/src/xcm_config.rs | 4 ++-- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 014dd1cbfb10..ef398deea83e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -938,11 +938,12 @@ pub mod bridging { ), NetworkExportTableItem::new( EthereumNetwork::get(), - Some(sp_std::vec![ - EthereumLocation::get().interior.split_global().expect("invalid configuration for AssetHubRococo").1, - ]), + None, // no remote location filter SiblingBridgeHub::get(), // TODO check - None // TODO check + Some(( + XcmBridgeHubRouterFeeAssetId::get(), + bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get(), + ).into()) // TODO check ), ]; diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index ba0012b20cc1..e863e91678c5 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -64,11 +64,6 @@ impl> ContainsPair for FromNetwork { fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool { - // `a` needs to be from `b` at least - if !a.starts_with(b) { - return false; - } - match a { MultiLocation { parents: 2, interior } => { matches!(interior.first(), Some(GlobalConsensus(network)) if *network == SelfNetworkId::get()) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 671de1f27a20..de605eda73de 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -450,7 +450,7 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { message, ) .map(|result| ((Wococo, result.0), result.1)), - location if location == EthereumNetwork::get() && network == Rococo => { + location if location == EthereumNetwork::get() && network == EthereumNetwork::get() => { // TODO check SnowbridgeExporter::validate( network, channel, @@ -469,7 +469,7 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { match network { Rococo => ToBridgeHubRococoHaulBlobExporter::deliver(ticket), Wococo => ToBridgeHubWococoHaulBlobExporter::deliver(ticket), - location if location == EthereumNetwork::get() && network == Rococo => { + location if location == EthereumNetwork::get() && network == EthereumNetwork::get() => { // TODO check SnowbridgeExporter::deliver(ticket) }, _ => unimplemented!("Unsupported network: {:?}", network), From 506b6b1c6518b6c86ad4b7ec56de94c86796d3da Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Sun, 29 Oct 2023 22:02:38 +0200 Subject: [PATCH 079/124] fixes after rebase --- Cargo.lock | 3 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 7 ++++- .../src/weights/snowbridge_outbound_queue.rs | 28 ++++++++++++------- .../bridge-hub-rococo/src/xcm_config.rs | 3 -- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa41280a104a..b2a716856b2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16853,7 +16853,6 @@ dependencies = [ name = "snowbridge-inbound-queue" version = "0.1.1" dependencies = [ - "bp-runtime", "ethabi-decode", "frame-benchmarking", "frame-support", @@ -16880,7 +16879,6 @@ dependencies = [ name = "snowbridge-outbound-queue" version = "0.1.1" dependencies = [ - "bp-runtime", "ethabi-decode", "frame-benchmarking", "frame-support", @@ -16914,6 +16912,7 @@ dependencies = [ name = "snowbridge-outbound-queue-runtime-api" version = "0.1.0" dependencies = [ + "frame-support", "parity-scale-codec", "snowbridge-core", "snowbridge-outbound-queue-merkle-tree", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 63d96692fe52..b0e77e1e6e43 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -550,6 +550,7 @@ impl snowbridge_outbound_queue::Config for Runtime { type DeliveryFeePerGas = DeliveryFeePerGas; type DeliveryRefundPerGas = DeliveryRefundPerGas; type DeliveryReward = DeliveryReward; + type WeightToFee = WeightToFee; type WeightInfo = weights::snowbridge_outbound_queue::WeightInfo; } @@ -981,10 +982,14 @@ impl_runtime_apis! { } } - impl snowbridge_outbound_queue_runtime_api::OutboundQueueApi for Runtime { + impl snowbridge_outbound_queue_runtime_api::OutboundQueueApi for Runtime { fn prove_message(leaf_index: u64) -> Option { snowbridge_outbound_queue::api::prove_message::(leaf_index) } + + fn calculate_fee(message: Message) -> Option { + snowbridge_outbound_queue::api::calculate_fee::(message) + } } #[cfg(feature = "try-runtime")] diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs index ef2ab1d4f53f..4836c0f830f5 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs @@ -41,24 +41,32 @@ impl snowbridge_outbound_queue::WeightInfo for WeightIn // Proof Size summary in bytes: // Measured: `42` // Estimated: `3485` - // Minimum execution time: 38_000_000 picoseconds. - Weight::from_parts(38_000_000, 0) - .saturating_add(Weight::from_parts(0, 3485)) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(4)) + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(39_000_000, 3485) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: EthereumOutboundQueue MessageLeaves (r:1 w:0) /// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured) /// Storage: System Digest (r:1 w:1) /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - fn on_finalize() -> Weight { + fn commit_messages() -> Weight { // Proof Size summary in bytes: // Measured: `1094` // Estimated: `2579` // Minimum execution time: 28_000_000 picoseconds. - Weight::from_parts(28_000_000, 0) - .saturating_add(Weight::from_parts(0, 2579)) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) + Weight::from_parts(28_000_000, 2579) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + + fn commit_one_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `1094` + // Estimated: `2579` + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(9_000_000, 1586) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 989410ce7bd2..3ab91d011cfb 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -224,13 +224,10 @@ impl Contains for SafeCallFilter { >::initialize { .. }) | RuntimeCall::EthereumBeaconClient( snowbridge_ethereum_beacon_client::Call::force_checkpoint { .. } | - snowbridge_ethereum_beacon_client::Call::set_owner { .. } | snowbridge_ethereum_beacon_client::Call::set_operating_mode { .. }, ) | RuntimeCall::EthereumInboundQueue( - snowbridge_inbound_queue::Call::set_owner { .. } | snowbridge_inbound_queue::Call::set_operating_mode { .. }, ) | RuntimeCall::EthereumOutboundQueue( - snowbridge_outbound_queue::Call::set_owner { .. } | snowbridge_outbound_queue::Call::set_operating_mode { .. }, ) | RuntimeCall::EthereumControl(..) ) From ea063f7d3f6b2199d7f8e90f252b7562c1432d5a Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Mon, 30 Oct 2023 08:56:39 +0200 Subject: [PATCH 080/124] fixes after rebase --- Cargo.lock | 13 +++++++++++++ .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 3 +++ .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 9 +++++++++ 3 files changed, 25 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index b2a716856b2a..f36db27fbbb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2100,6 +2100,7 @@ dependencies = [ "smallvec", "snowbridge-beacon-primitives", "snowbridge-control", + "snowbridge-control-runtime-api", "snowbridge-core", "snowbridge-ethereum-beacon-client", "snowbridge-inbound-queue", @@ -16780,6 +16781,18 @@ dependencies = [ "staging-xcm-executor", ] +[[package]] +name = "snowbridge-control-runtime-api" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "snowbridge-core", + "sp-api", + "sp-core", + "sp-std", + "staging-xcm", +] + [[package]] name = "snowbridge-core" version = "0.1.1" diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 7738967b1a54..ce786a727f62 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -101,6 +101,7 @@ snowbridge-inbound-queue = { path = "../../../../../../parachain/pallets/inbound snowbridge-outbound-queue = { path = "../../../../../../parachain/pallets/outbound-queue", default-features = false } snowbridge-outbound-queue-runtime-api = { path = "../../../../../../parachain/pallets/outbound-queue/runtime-api", default-features = false } snowbridge-control = { path = "../../../../../../parachain/pallets/control", default-features = false } +snowbridge-control-runtime-api = { path = "../../../../../../parachain/pallets/control/runtime-api", default-features = false } [dev-dependencies] static_assertions = "1.1" @@ -192,6 +193,8 @@ std = [ "snowbridge-outbound-queue/std", "snowbridge-outbound-queue-runtime-api/std", "snowbridge-control/std", + "snowbridge-control-runtime-api/std", + "substrate-wasm-builder", ] runtime-benchmarks = [ diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index b0e77e1e6e43..c1c4ca880826 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -39,6 +39,7 @@ pub mod xcm_config; use codec::{Decode, Encode}; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use snowbridge_beacon_primitives::{Fork, ForkVersions}; +use snowbridge_core::{outbound::Message, AgentId}; use snowbridge_router_primitives::inbound::MessageToXcm; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160}; @@ -84,6 +85,7 @@ use pallet_xcm::EnsureXcm; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; pub use sp_runtime::{MultiAddress, Perbill, Permill}; +use xcm::VersionedMultiLocation; use xcm_config::{EthereumGatewayAddress, XcmConfig, XcmOriginToTransactDispatchOrigin}; use bp_runtime::HeaderId; @@ -992,6 +994,13 @@ impl_runtime_apis! { } } + impl snowbridge_control_runtime_api::ControlApi for Runtime { + fn agent_id(location: VersionedMultiLocation) -> Option { + snowbridge_control::api::agent_id::(location) + } + } + + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { From 0356361ec7e6ae65605611f5ef66ea0d1af533d4 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Mon, 30 Oct 2023 10:29:03 +0200 Subject: [PATCH 081/124] fixes after rebase --- .../runtimes/assets/asset-hub-rococo/src/xcm_config.rs | 6 +++--- .../bridge-hubs/bridge-hub-rococo/src/xcm_config.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index ef398deea83e..5239b8cf05c1 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -938,12 +938,12 @@ pub mod bridging { ), NetworkExportTableItem::new( EthereumNetwork::get(), - None, // no remote location filter - SiblingBridgeHub::get(), // TODO check + None, // TODO add Ethereum network / gateway contract + SiblingBridgeHub::get(), Some(( XcmBridgeHubRouterFeeAssetId::get(), bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get(), - ).into()) // TODO check + ).into()) // TODO calculate fee factor ), ]; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index d958a76e10b4..97932241fb0f 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -40,7 +40,7 @@ use parachains_common::{ }; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; -use rococo_runtime_constants::system_parachain::SystemParachains; +use rococo_runtime_constants::system_parachain; use snowbridge_router_primitives::outbound::EthereumBlobExporter; use sp_core::{Get, H256}; use sp_runtime::traits::AccountIdConversion; From 37552fd5ca94bfb72ff09e6c1a5045a039b6371d Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 30 Oct 2023 13:24:22 +0200 Subject: [PATCH 082/124] Update polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs Co-authored-by: Francisco Aguirre --- polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs index 77b326052dcc..a35c6555c96c 100644 --- a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs +++ b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs @@ -74,7 +74,8 @@ pub trait AssetTransferSupport { if asset_location == MultiLocation::here() || Self::IsTeleporter::contains(asset, &asset_location) { - // if local asset, or remote location that allows local teleports => local reserve + // if the asset is local, then it's a local reserve + // it's also a local reserve if the asset's location is not `here` but it's a location where it can be teleported to `here` => local reserve Ok(TransferType::LocalReserve) } else if Self::IsReserve::contains(asset, &asset_location) { // remote location that is recognized as reserve location for asset From 6714d39146e80c8d8559e12b8af57fef1ef4f38f Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 30 Oct 2023 13:25:55 +0200 Subject: [PATCH 083/124] Update polkadot/xcm/pallet-xcm/src/lib.rs Co-authored-by: Francisco Aguirre --- polkadot/xcm/pallet-xcm/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 186dd2d51197..fcd51fd7b0f2 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1484,7 +1484,7 @@ impl Pallet { ClearOrigin, // buy exec using `fees` in holding deposited in top instruction here BuyExecution { fees: reanchored_fees, weight_limit }, - // deposit all assets in holding to `beneficiary` account(s) + // deposit all assets in holding to `beneficiary` location DepositAsset { assets: Wild(AllCounted(max_assets)), beneficiary }, ] .into_iter(), From 7a61129cb91a05d7aacb4f378151aa6c303a15e6 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Mon, 30 Oct 2023 13:31:38 +0200 Subject: [PATCH 084/124] fmt --- polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs index a35c6555c96c..980554f2dce2 100644 --- a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs +++ b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs @@ -75,7 +75,8 @@ pub trait AssetTransferSupport { Self::IsTeleporter::contains(asset, &asset_location) { // if the asset is local, then it's a local reserve - // it's also a local reserve if the asset's location is not `here` but it's a location where it can be teleported to `here` => local reserve + // it's also a local reserve if the asset's location is not `here` but it's a location + // where it can be teleported to `here` => local reserve Ok(TransferType::LocalReserve) } else if Self::IsReserve::contains(asset, &asset_location) { // remote location that is recognized as reserve location for asset From f0e267ac677d5c35a2ceb645d9881247a8181cc3 Mon Sep 17 00:00:00 2001 From: Clara van Staden Date: Mon, 30 Oct 2023 14:56:01 +0200 Subject: [PATCH 085/124] Polkadot sdk update v2 (#3) * adds message queue pallet * adds outbound queue * fix compiler errors * adds snowbridge to rococo bridgehub * asset hub rococo * asset hub rococo * finishing up applying changes * fix incorrect pallet-xcm imports * fixing tests * adds upstream changes * cleanup comments, fix upgrade gateway test * attempts to fix xcm config * fixes send token * fmt * fixes after rebase * fixes after rebase * correct relay network check --------- Co-authored-by: claravanstaden --- Cargo.lock | 309 ++++++++++++++++++ cumulus/pallets/dmp-queue/src/lib.rs | 6 +- .../parachain-template/node/src/chain_spec.rs | 6 +- .../pallets/template/Cargo.toml | 7 + .../pallets/template/src/lib.rs | 37 ++- .../bridges/bridge-hub-rococo/Cargo.toml | 3 + .../bridge-hub-rococo/src/tests/mod.rs | 1 + .../bridge-hub-rococo/src/tests/snowbridge.rs | 126 +++++++ .../emulated/common/src/lib.rs | 1 + .../assets/asset-hub-rococo/Cargo.toml | 2 + .../assets/asset-hub-rococo/src/lib.rs | 11 +- .../assets/asset-hub-rococo/src/xcm_config.rs | 51 ++- .../runtimes/assets/common/src/matching.rs | 23 +- .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 32 +- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 223 ++++++++++++- .../bridge-hub-rococo/src/weights/mod.rs | 4 + .../src/weights/snowbridge_control.rs | 202 ++++++++++++ .../snowbridge_ethereum_beacon_client.rs | 137 ++++++++ .../src/weights/snowbridge_inbound_queue.rs | 55 ++++ .../src/weights/snowbridge_outbound_queue.rs | 72 ++++ .../bridge-hub-rococo/src/xcm_config.rs | 88 ++++- cumulus/polkadot-parachain/Cargo.toml | 1 + substrate/frame/nomination-pools/src/lib.rs | 1 + 23 files changed, 1376 insertions(+), 22 deletions(-) create mode 100644 cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs diff --git a/Cargo.lock b/Cargo.lock index a8d679c6ce8b..f36db27fbbb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,6 +197,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4436e0292ab1bb631b42973c61205e704475fe8126af845c8d923c0996328127" +[[package]] +name = "amcl" +version = "0.3.0" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -877,6 +886,7 @@ dependencies = [ "rococo-runtime-constants", "scale-info", "smallvec", + "snowbridge-router-primitives", "sp-api", "sp-block-builder", "sp-consensus-aura", @@ -2020,6 +2030,7 @@ dependencies = [ "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-runtime-parachains", + "snowbridge-control", "staging-xcm", "staging-xcm-executor", "xcm-emulator", @@ -2068,6 +2079,7 @@ dependencies = [ "pallet-bridge-parachains", "pallet-bridge-relayers", "pallet-collator-selection", + "pallet-message-queue", "pallet-multisig", "pallet-session", "pallet-timestamp", @@ -2086,6 +2098,15 @@ dependencies = [ "scale-info", "serde", "smallvec", + "snowbridge-beacon-primitives", + "snowbridge-control", + "snowbridge-control-runtime-api", + "snowbridge-core", + "snowbridge-ethereum-beacon-client", + "snowbridge-inbound-queue", + "snowbridge-outbound-queue", + "snowbridge-outbound-queue-runtime-api", + "snowbridge-router-primitives", "sp-api", "sp-block-builder", "sp-consensus-aura", @@ -4870,6 +4891,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ethabi-decode" +version = "1.4.0" +source = "git+https://github.com/Snowfork/ethabi-decode.git?branch=master#7d215837b626650bd9a076821e57ad488101301f" +dependencies = [ + "ethereum-types", + "tiny-keccak", +] + [[package]] name = "ethbloom" version = "0.13.0" @@ -4878,8 +4908,10 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "tiny-keccak", ] @@ -4891,9 +4923,11 @@ checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", "primitive-types", + "scale-info", "uint", ] @@ -7921,6 +7955,20 @@ dependencies = [ "thrift", ] +[[package]] +name = "milagro_bls" +version = "1.5.0" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" +dependencies = [ + "amcl", + "hex", + "lazy_static", + "parity-scale-codec", + "rand 0.8.5", + "scale-info", + "zeroize", +] + [[package]] name = "mime" version = "0.3.17" @@ -10273,12 +10321,15 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "pallet-xcm", "parity-scale-codec", "scale-info", "serde", "sp-core", "sp-io", "sp-runtime", + "sp-std", + "staging-xcm", ] [[package]] @@ -11161,6 +11212,12 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "parity-bytes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b56e3a2420138bdb970f84dfb9c774aea80fa0e7371549eedec0d80c209c67" + [[package]] name = "parity-db" version = "0.4.10" @@ -16233,6 +16290,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd31f59f6fe2b0c055371bb2f16d7f0aa7d8881676c04a55b1596d1a17cd10a4" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.188" @@ -16671,6 +16737,226 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "snowbridge-beacon-primitives" +version = "0.0.1" +dependencies = [ + "byte-slice-cast", + "frame-support", + "frame-system", + "hex", + "milagro_bls", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-ethereum", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "ssz_rs", + "ssz_rs_derive", + "static_assertions", +] + +[[package]] +name = "snowbridge-control" +version = "4.0.0-dev" +dependencies = [ + "ethabi-decode", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "snowbridge-core", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + +[[package]] +name = "snowbridge-control-runtime-api" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "snowbridge-core", + "sp-api", + "sp-core", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "snowbridge-core" +version = "0.1.1" +dependencies = [ + "derivative", + "ethabi-decode", + "frame-support", + "frame-system", + "parity-scale-codec", + "polkadot-parachain-primitives", + "scale-info", + "serde", + "snowbridge-beacon-primitives", + "snowbridge-ethereum", + "sp-core", + "sp-runtime", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "snowbridge-ethereum" +version = "0.1.0" +dependencies = [ + "ethabi-decode", + "ethbloom", + "ethereum-types", + "hex-literal", + "parity-bytes", + "parity-scale-codec", + "rlp", + "rustc-hex", + "scale-info", + "serde", + "serde-big-array", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "snowbridge-ethereum-beacon-client" +version = "0.0.1" +dependencies = [ + "bp-runtime", + "byte-slice-cast", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex-literal", + "log", + "pallet-timestamp", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-ethereum", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "ssz_rs", + "ssz_rs_derive", + "static_assertions", +] + +[[package]] +name = "snowbridge-inbound-queue" +version = "0.1.1" +dependencies = [ + "ethabi-decode", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex-literal", + "pallet-balances", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-ethereum", + "snowbridge-router-primitives", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", +] + +[[package]] +name = "snowbridge-outbound-queue" +version = "0.1.1" +dependencies = [ + "ethabi-decode", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex-literal", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-core", + "snowbridge-outbound-queue-merkle-tree", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "snowbridge-outbound-queue-merkle-tree" +version = "0.1.1" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "snowbridge-outbound-queue-runtime-api" +version = "0.1.0" +dependencies = [ + "frame-support", + "parity-scale-codec", + "snowbridge-core", + "snowbridge-outbound-queue-merkle-tree", + "sp-api", + "sp-core", + "sp-std", + "staging-xcm", +] + +[[package]] +name = "snowbridge-router-primitives" +version = "0.1.1" +dependencies = [ + "ethabi-decode", + "frame-support", + "frame-system", + "hex-literal", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "snowbridge-core", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + [[package]] name = "socket2" version = "0.4.9" @@ -17648,6 +17934,29 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ssz_rs" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057291e5631f280978fa9c8009390663ca4613359fc1318e36a8c24c392f6d1f" +dependencies = [ + "bitvec", + "num-bigint", + "sha2 0.9.9", + "ssz_rs_derive", +] + +[[package]] +name = "ssz_rs_derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f07d54c4d01a1713eb363b55ba51595da15f6f1211435b71466460da022aa140" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/cumulus/pallets/dmp-queue/src/lib.rs b/cumulus/pallets/dmp-queue/src/lib.rs index eff4a625ef1b..740722b05699 100644 --- a/cumulus/pallets/dmp-queue/src/lib.rs +++ b/cumulus/pallets/dmp-queue/src/lib.rs @@ -54,9 +54,11 @@ pub struct ConfigData { impl Default for ConfigData { fn default() -> Self { Self { + // For beacon checkpoint to work require a bigger default max_individual: Weight::from_parts( - 10u64 * WEIGHT_REF_TIME_PER_MILLIS, // 10 ms of execution time maximum by default - DEFAULT_POV_SIZE, // 64 KB of proof size by default + 20u64 * 10u64 * WEIGHT_REF_TIME_PER_MILLIS, /* 200 ms of execution time maximum + * by default */ + 10u64 * DEFAULT_POV_SIZE, // 640 KB of proof size by default ), } } diff --git a/cumulus/parachain-template/node/src/chain_spec.rs b/cumulus/parachain-template/node/src/chain_spec.rs index 0ca3c51900f2..733e6136d7e6 100644 --- a/cumulus/parachain-template/node/src/chain_spec.rs +++ b/cumulus/parachain-template/node/src/chain_spec.rs @@ -102,7 +102,7 @@ pub fn development_config() -> ChainSpec { get_account_id_from_seed::("Ferdie//stash"), ], get_account_id_from_seed::("Alice"), - 1000.into(), + 1001.into(), ) }, Vec::new(), @@ -112,7 +112,7 @@ pub fn development_config() -> ChainSpec { None, Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: 1000, + para_id: 1001, }, ) } @@ -174,7 +174,7 @@ pub fn local_testnet_config() -> ChainSpec { // Extensions Extensions { relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: 1000, + para_id: 1001, }, ) } diff --git a/cumulus/parachain-template/pallets/template/Cargo.toml b/cumulus/parachain-template/pallets/template/Cargo.toml index 925457839348..1f53ff50e81a 100644 --- a/cumulus/parachain-template/pallets/template/Cargo.toml +++ b/cumulus/parachain-template/pallets/template/Cargo.toml @@ -19,6 +19,10 @@ scale-info = { version = "2.10.0", default-features = false, features = ["derive frame-benchmarking = { path = "../../../../substrate/frame/benchmarking", default-features = false, optional = true} frame-support = { path = "../../../../substrate/frame/support", default-features = false} frame-system = { path = "../../../../substrate/frame/system", default-features = false} +sp-std = { path = "../../../../substrate/primitives/std", default-features = false} + +pallet-xcm = { path = "../../../../polkadot/xcm/pallet-xcm", default-features = false} +xcm = { package = "staging-xcm", path = "../../../../polkadot/xcm", default-features = false} [dev-dependencies] serde = { version = "1.0.188" } @@ -45,6 +49,9 @@ std = [ "sp-core/std", "sp-io/std", "sp-runtime/std", + "sp-std/std", + "pallet-xcm/std", + "xcm/std", ] try-runtime = [ "frame-support/try-runtime", diff --git a/cumulus/parachain-template/pallets/template/src/lib.rs b/cumulus/parachain-template/pallets/template/src/lib.rs index 5f3252bfc3a7..911896d15d40 100644 --- a/cumulus/parachain-template/pallets/template/src/lib.rs +++ b/cumulus/parachain-template/pallets/template/src/lib.rs @@ -18,10 +18,12 @@ mod benchmarking; pub mod pallet { use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*}; use frame_system::pallet_prelude::*; + use sp_std::boxed::Box; + use xcm::{v3::prelude::*, VersionedMultiLocation, VersionedXcm}; /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] - pub trait Config: frame_system::Config { + pub trait Config: frame_system::Config + pallet_xcm::Config { /// Because this pallet emits events, it depends on the runtime's definition of an event. type RuntimeEvent: From> + IsType<::RuntimeEvent>; } @@ -45,6 +47,8 @@ pub mod pallet { /// Event documentation should end with an array that provides descriptive names for event /// parameters. [something, who] SomethingStored(u32, T::AccountId), + /// XCM message sent. \[to, message\] + Sent { from: T::AccountId, to: MultiLocation, message: Xcm<()> }, } // Errors inform users that something went wrong. @@ -54,6 +58,15 @@ pub mod pallet { NoneValue, /// Errors should have helpful documentation associated with them. StorageOverflow, + /// The message and destination combination was not recognized as being + /// reachable. + Unreachable, + /// The message and destination was recognized as being reachable but + /// the operation could not be completed. + SendFailure, + /// The version of the `Versioned` value used is not able to be + /// interpreted. + BadVersion, } #[pallet::hooks] @@ -102,5 +115,27 @@ pub mod pallet { }, } } + + /// Send an XCM message as parachain sovereign. + #[pallet::call_index(2)] + #[pallet::weight(Weight::from_parts(100_000_000, 0))] + pub fn send_xcm( + origin: OriginFor, + dest: Box, + message: Box>, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + let dest = MultiLocation::try_from(*dest).map_err(|()| Error::::BadVersion)?; + let message: Xcm<()> = (*message).try_into().map_err(|()| Error::::BadVersion)?; + + pallet_xcm::Pallet::::send_xcm(Here, dest, message.clone()).map_err( + |e| match e { + SendError::Unroutable => Error::::Unreachable, + _ => Error::::SendFailure, + }, + )?; + Self::deposit_event(Event::Sent { from: who, to: dest, message }); + Ok(()) + } } } diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml index b3ce2a99f70a..29499034fba5 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml @@ -33,3 +33,6 @@ bridge-hub-rococo-runtime = { path = "../../../../../parachains/runtimes/bridge- # Local xcm-emulator = { path = "../../../../../xcm/xcm-emulator", default-features = false} integration-tests-common = { path = "../../common", default-features = false} + +# Snowbridge +snowbridge-control = { path = "../../../../../../../parachain/pallets/control" } diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs index 1eef05c6b928..6d439b634f4e 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs @@ -14,4 +14,5 @@ // limitations under the License. mod example; +mod snowbridge; mod teleport; diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs new file mode 100644 index 000000000000..fa494fbac3c6 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -0,0 +1,126 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::*; +use integration_tests_common::BridgeHubRococoPallet; +use snowbridge_control; + +#[test] +fn create_agent() { + let sudo_origin = ::RuntimeOrigin::root(); + let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into(); + + let remote_xcm = VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, + DescendOrigin(X1(Parachain(1000))), + Transact { + require_weight_at_most: 3000000000.into(), + origin_kind: OriginKind::Xcm, + call: vec![51, 1].into(), + }, + ])); + + //Rococo Global Consensus + // Send XCM message from Relay Chain to Bridge Hub source Parachain + Rococo::execute_with(|| { + assert_ok!(::XcmPallet::send( + sudo_origin, + bx!(destination), + bx!(remote_xcm), + )); + + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward { + outcome: Outcome::Complete(_), + .. + }) => {}, + RuntimeEvent::EthereumControl(snowbridge_control::Event::CreateAgent { + .. + }) => {}, + ] + ); + }); +} + +#[test] +fn create_channel() { + let sudo_origin = ::RuntimeOrigin::root(); + let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into(); + + let remote_xcm = VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, + DescendOrigin(X1(Parachain(1000))), + Transact { + require_weight_at_most: 8000000000.into(), + origin_kind: OriginKind::Xcm, + call: vec![51, 2].into(), + }, + ])); + + //BridgeHubRococo::execute_with(|| { // TODO Create agent in storage + // ::EthereumControl::create_agent(sudo_origin); + //}); + + //Rococo Global Consensus + // Send XCM message from Relay Chain to Bridge Hub source Parachain + Rococo::execute_with(|| { + assert_ok!(::XcmPallet::send( + sudo_origin, + bx!(destination), + bx!(remote_xcm), + )); + + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward { + outcome: Outcome::Complete(_), + .. + }) => {}, + RuntimeEvent::EthereumControl(snowbridge_control::Event::CreateChannel { + .. + }) => {}, + ] + ); + }); +} diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index 8a8081c9fac3..3317ba2950e5 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -150,6 +150,7 @@ decl_test_parachains! { pallets = { PolkadotXcm: bridge_hub_rococo_runtime::PolkadotXcm, Balances: bridge_hub_rococo_runtime::Balances, + EthereumControl: bridge_hub_rococo_runtime::EthereumControl, } }, // AssetHubRococo diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index b1ec66f40bff..02fc43b81521 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -78,6 +78,7 @@ pallet-collator-selection = { path = "../../../../pallets/collator-selection", d parachain-info = { path = "../../../pallets/parachain-info", default-features = false } parachains-common = { path = "../../../common", default-features = false } assets-common = { path = "../common", default-features = false } +snowbridge-router-primitives = { path = "../../../../../../parachain/primitives/router", default-features = false } # Bridges pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } @@ -219,6 +220,7 @@ std = [ "polkadot-runtime-common/std", "rococo-runtime-constants/std", "scale-info/std", + "snowbridge-router-primitives/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 20b59368a5b5..aba226b3baab 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -97,8 +97,8 @@ use xcm::latest::prelude::*; use xcm_executor::XcmExecutor; use crate::xcm_config::{ - ForeignCreatorsSovereignAccountOf, LocalAndForeignAssetsMultiLocationMatcher, - TrustBackedAssetsPalletLocation, + bridging::to_rococo::EthereumGatewayLocation, ForeignCreatorsSovereignAccountOf, + LocalAndForeignAssetsMultiLocationMatcher, TrustBackedAssetsPalletLocation, }; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; @@ -387,7 +387,12 @@ impl pallet_assets::Config for Runtime { type AssetIdParameter = MultiLocationForAssetId; type Currency = Balances; type CreateOrigin = ForeignCreators< - (FromSiblingParachain>,), + ( + FromSiblingParachain>, + snowbridge_router_primitives::inbound::FromEthereumGlobalConsensus< + EthereumGatewayLocation, + >, + ), ForeignCreatorsSovereignAccountOf, AccountId, >; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index ae4a275d43ac..7b2b97dfe716 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -41,6 +41,7 @@ use parachains_common::{ use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; use rococo_runtime_constants::system_parachain::SystemParachains; +use snowbridge_router_primitives::inbound::GlobalConsensusEthereumAccountConvertsFor; use sp_runtime::traits::{AccountIdConversion, ConvertInto}; use xcm::latest::prelude::*; use xcm_builder::{ @@ -109,6 +110,9 @@ pub type LocationToAccountId = ( // Different global consensus parachain sovereign account. // (Used for over-bridge transfers and reserve processing) GlobalConsensusParachainConvertsFor, + // Ethereum contract sovereign account. + // (Used to get convert ethereum contract locations to sovereign account) + GlobalConsensusEthereumAccountConvertsFor, ); /// Means for transacting the native currency on this chain. @@ -568,6 +572,7 @@ impl xcm_executor::Config for XcmConfig { type IsReserve = ( bridging::to_wococo::IsTrustedBridgedReserveLocationForConcreteAsset, bridging::to_rococo::IsTrustedBridgedReserveLocationForConcreteAsset, + bridging::to_rococo::IsTrustedBridgedReserveLocationForForeignAsset, ); type IsTeleporter = TrustedTeleporters; type UniversalLocation = UniversalLocation; @@ -672,6 +677,7 @@ impl pallet_xcm::Config for Runtime { type XcmReserveTransferFilter = ( LocationWithAssetFilters, bridging::to_rococo::AllowedReserveTransferAssets, + //bridging::to_rococo::AllowedReserveTransferAssetsEthereum, bridging::to_wococo::AllowedReserveTransferAssets, ); @@ -707,6 +713,7 @@ pub type ForeignCreatorsSovereignAccountOf = ( SiblingParachainConvertsVia, AccountId32Aliases, ParentIsPreset, + GlobalConsensusEthereumAccountConvertsFor, ); /// Simple conversion of `u32` into an `AssetId` for use in benchmarking. @@ -864,6 +871,7 @@ pub mod bridging { pub mod to_rococo { use super::*; + use assets_common::matching::FromNetwork; parameter_types! { pub SiblingBridgeHubWithBridgeHubRococoInstance: MultiLocation = MultiLocation::new( @@ -877,12 +885,29 @@ pub mod bridging { pub const RococoNetwork: NetworkId = NetworkId::Rococo; pub AssetHubRococo: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(RococoNetwork::get()), Parachain(bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID))); pub RocLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(RococoNetwork::get()))); + pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; + pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); // TODO: Maybe registry address belongs here + + pub const EthereumGatewayAddress: [u8; 20] = hex_literal::hex!("EDa338E4dC46038493b885327842fD3E301CaB39"); + // The Registry contract for the bridge which is also the origin for reserves and the prefix of all assets. + pub EthereumGatewayLocation: MultiLocation = EthereumLocation::get() + .pushed_with_interior( + AccountKey20 { + network: None, + key: EthereumGatewayAddress::get(), + } + ).unwrap(); pub RocFromAssetHubRococo: (MultiAssetFilter, MultiLocation) = ( Wild(AllOf { fun: WildFungible, id: Concrete(RocLocation::get()) }), AssetHubRococo::get() ); + /*pub EtherFromEthereum: (MultiAssetFilter, MultiLocation) = ( + EthereumGatewayLocation::get().into(), + EthereumGatewayLocation::get() + );*/ + /// Set up exporters configuration. /// `Option` represents static "base fee" which is used for total delivery fee calculation. pub BridgeTable: sp_std::vec::Vec = sp_std::vec![ @@ -897,7 +922,15 @@ pub mod bridging { XcmBridgeHubRouterFeeAssetId::get(), bp_asset_hub_wococo::BridgeHubWococoBaseFeeInWocs::get(), ).into()) - ) + ), + NetworkExportTableItem::new( + EthereumNetwork::get(), + Some(sp_std::vec![ + EthereumLocation::get().interior.split_global().expect("invalid configuration for AssetHubRococo").1, + ]), + SiblingBridgeHub::get(), // TODO check + None // TODO check + ), ]; /// Allowed assets for reserve transfer to `AssetHubWococo`. @@ -907,10 +940,15 @@ pub mod bridging { // and nothing else ]; + pub AllowedReserveTransferAssetsToEthereum: sp_std::vec::Vec = sp_std::vec![ + Wild(AllOf { fun: WildFungible, id: Concrete(EthereumGatewayLocation::get()) }), + ]; + /// Universal aliases pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( sp_std::vec![ - (SiblingBridgeHubWithBridgeHubRococoInstance::get(), GlobalConsensus(RococoNetwork::get())) + (SiblingBridgeHubWithBridgeHubRococoInstance::get(), GlobalConsensus(RococoNetwork::get())), + (SiblingBridgeHub::get(), GlobalConsensus(EthereumNetwork::get())), ] ); } @@ -933,12 +971,21 @@ pub mod bridging { ), >; + pub type IsTrustedBridgedReserveLocationForForeignAsset = + matching::IsForeignConcreteAsset>; + /// Allows to reserve transfer assets to `AssetHubRococo`. pub type AllowedReserveTransferAssets = LocationWithAssetFilters< Equals, AllowedReserveTransferAssetsToAssetHubRococo, >; + /* + pub type AllowedReserveTransferAssetsEthereum = LocationWithAssetFilters< + StartsWithExplicitGlobalConsensus, // TODO check + AllowedReserveTransferAssetsToEthereum, + >;*/ + impl Contains for ToRococoXcmRouter { fn contains(call: &RuntimeCall) -> bool { matches!( diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index 914972812521..2f61a2824b09 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -51,13 +51,32 @@ impl> ContainsPair // here we check if sibling match a { - MultiLocation { parents: 1, interior } => - matches!(interior.first(), Some(Parachain(sibling_para_id)) if sibling_para_id.ne(&u32::from(SelfParaId::get()))), + MultiLocation { parents: 1, interior } => { + matches!(interior.first(), Some(Parachain(sibling_para_id)) if sibling_para_id.ne(&u32::from(SelfParaId::get()))) + }, _ => false, } } } +pub struct FromNetwork(sp_std::marker::PhantomData); +impl> ContainsPair + for FromNetwork +{ + fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool { + // `a` needs to be from `b` at least + if !a.starts_with(b) { + return false + } + + match a { + MultiLocation { parents: 2, interior } => { + matches!(interior.first(), Some(GlobalConsensus(network)) if *network == SelfNetworkId::get()) + }, + _ => false, + } + } +} /// Adapter verifies if it is allowed to receive `MultiAsset` from `MultiLocation`. /// /// Note: `MultiLocation` has to be from a different global consensus. diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index 5befb21c8911..ce786a727f62 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -29,6 +29,7 @@ pallet-authorship = { path = "../../../../../substrate/frame/authorship", defaul pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false} pallet-session = { path = "../../../../../substrate/frame/session", default-features = false} pallet-multisig = { path = "../../../../../substrate/frame/multisig", default-features = false} +pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false} pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false} pallet-transaction-payment-rpc-runtime-api = { path = "../../../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false} @@ -91,6 +92,17 @@ pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false } bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false } +# Ethereum Bridge (Snowbridge) +snowbridge-core = { path = "../../../../../../parachain/primitives/core", default-features = false } +snowbridge-beacon-primitives = { path = "../../../../../../parachain/primitives/beacon", default-features = false } +snowbridge-router-primitives = { path = "../../../../../../parachain/primitives/router", default-features = false } +snowbridge-ethereum-beacon-client = { path = "../../../../../../parachain/pallets/ethereum-beacon-client", default-features = false } +snowbridge-inbound-queue = { path = "../../../../../../parachain/pallets/inbound-queue", default-features = false } +snowbridge-outbound-queue = { path = "../../../../../../parachain/pallets/outbound-queue", default-features = false } +snowbridge-outbound-queue-runtime-api = { path = "../../../../../../parachain/pallets/outbound-queue/runtime-api", default-features = false } +snowbridge-control = { path = "../../../../../../parachain/pallets/control", default-features = false } +snowbridge-control-runtime-api = { path = "../../../../../../parachain/pallets/control/runtime-api", default-features = false } + [dev-dependencies] static_assertions = "1.1" bridge-hub-test-utils = { path = "../test-utils" } @@ -139,6 +151,7 @@ std = [ "pallet-bridge-relayers/std", "pallet-collator-selection/std", "pallet-multisig/std", + "pallet-message-queue/std", "pallet-session/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", @@ -172,6 +185,16 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", + "snowbridge-core/std", + "snowbridge-router-primitives/std", + "snowbridge-beacon-primitives/std", + "snowbridge-ethereum-beacon-client/std", + "snowbridge-inbound-queue/std", + "snowbridge-outbound-queue/std", + "snowbridge-outbound-queue-runtime-api/std", + "snowbridge-control/std", + "snowbridge-control-runtime-api/std", + "substrate-wasm-builder", ] runtime-benchmarks = [ @@ -201,6 +224,11 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "xcm-executor/runtime-benchmarks", + "snowbridge-core/runtime-benchmarks", + "snowbridge-control/runtime-benchmarks", + "snowbridge-inbound-queue/runtime-benchmarks", + "snowbridge-outbound-queue/runtime-benchmarks", + "snowbridge-ethereum-beacon-client/runtime-benchmarks" ] try-runtime = [ @@ -231,5 +259,7 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", ] - +beacon-spec-mainnet = [ + "snowbridge-ethereum-beacon-client/beacon-spec-mainnet", +] experimental = [ "pallet-aura/experimental" ] diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 5973801d37c4..c1c4ca880826 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -38,15 +38,30 @@ pub mod xcm_config; use codec::{Decode, Encode}; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; +use snowbridge_beacon_primitives::{Fork, ForkVersions}; +use snowbridge_core::{outbound::Message, AgentId}; +use snowbridge_router_primitives::inbound::MessageToXcm; use sp_api::impl_runtime_apis; -use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT}, + traits::{AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Keccak256}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, }; +#[cfg(feature = "runtime-benchmarks")] +use crate::xcm_config::benchmark_helper::DoNothingRouter; +#[cfg(feature = "runtime-benchmarks")] +use snowbridge_beacon_primitives::CompactExecutionHeader; +#[cfg(feature = "runtime-benchmarks")] +use snowbridge_core::RingBufferMap; +#[cfg(feature = "runtime-benchmarks")] +pub use snowbridge_ethereum_beacon_client::ExecutionHeaderBuffer; +#[cfg(feature = "runtime-benchmarks")] +use snowbridge_inbound_queue::BenchmarkHelper; +#[cfg(feature = "runtime-benchmarks")] +use sp_core::H256; use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; @@ -65,9 +80,13 @@ use frame_system::{ limits::{BlockLength, BlockWeights}, EnsureRoot, }; + +use pallet_xcm::EnsureXcm; + pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; pub use sp_runtime::{MultiAddress, Perbill, Permill}; -use xcm_config::{XcmConfig, XcmOriginToTransactDispatchOrigin}; +use xcm::VersionedMultiLocation; +use xcm_config::{EthereumGatewayAddress, XcmConfig, XcmOriginToTransactDispatchOrigin}; use bp_runtime::HeaderId; @@ -79,6 +98,8 @@ use xcm::latest::prelude::*; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +#[cfg(not(feature = "runtime-benchmarks"))] +use crate::xcm_config::AllowSiblingsOnly; use crate::{ bridge_hub_rococo_config::BridgeRefundBridgeHubWococoMessages, bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages, xcm_config::XcmRouter, @@ -327,7 +348,8 @@ impl pallet_transaction_payment::Config for Runtime { parameter_types! { pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + // For beacon checkpoint to work require a bigger default + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT; } impl cumulus_pallet_parachain_system::Config for Runtime { @@ -457,6 +479,167 @@ impl pallet_utility::Config for Runtime { type WeightInfo = weights::pallet_utility::WeightInfo; } +parameter_types! { + /// Amount of weight that can be spent per block to service messages. + pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_message_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Size = u32; + type HeapSize = ConstU32<{ 64 * 1024 }>; + type MaxStale = ConstU32<8>; + type ServiceWeight = MessageQueueServiceWeight; + type MessageProcessor = EthereumOutboundQueue; + type QueueChangeHandler = (); + type QueuePausedQuery = (); + type WeightInfo = (); +} + +// Ethereum Bridge + +parameter_types! { + pub const Reward: u128 = 10; + pub const GatewayAddress: H160 = H160(EthereumGatewayAddress::get()); + pub const CreateAssetCall: [u8;2] = [53, 0]; + pub const CreateAssetExecutionFee: u128 = 2_000_000_000; + pub const SendTokenExecutionFee: u128 = 1_000_000_000; +} + +#[cfg(feature = "runtime-benchmarks")] +impl BenchmarkHelper for Runtime { + fn initialize_storage(block_hash: H256, header: CompactExecutionHeader) { + >::insert(block_hash, header); + } +} + +impl snowbridge_inbound_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Verifier = snowbridge_ethereum_beacon_client::Pallet; + type Token = Balances; + type Reward = Reward; + #[cfg(not(feature = "runtime-benchmarks"))] + type XcmSender = XcmRouter; + #[cfg(feature = "runtime-benchmarks")] + type XcmSender = DoNothingRouter; + type WeightInfo = weights::snowbridge_inbound_queue::WeightInfo; + type GatewayAddress = GatewayAddress; + #[cfg(feature = "runtime-benchmarks")] + type Helper = Runtime; + type MessageConverter = + MessageToXcm; +} + +pub const GWEI: u128 = 1_000_000_000; + +parameter_types! { + pub const MaxMessagePayloadSize: u32 = 2048; + pub const MaxMessagesPerBlock: u32 = 32; + pub const DeliveryFeePerGas: u128 = 10; + pub const DeliveryRefundPerGas: u128 = 10 * GWEI; + pub const DeliveryReward: u128 = 1000 * GWEI; +} + +impl snowbridge_outbound_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Hashing = Keccak256; + type MessageQueue = MessageQueue; + type MaxMessagePayloadSize = MaxMessagePayloadSize; + type MaxMessagesPerBlock = MaxMessagesPerBlock; + type OwnParaId = ParachainInfo; + type GasMeter = snowbridge_core::outbound::ConstantGasMeter; + type Balance = Balance; + type DeliveryFeePerGas = DeliveryFeePerGas; + type DeliveryRefundPerGas = DeliveryRefundPerGas; + type DeliveryReward = DeliveryReward; + type WeightToFee = WeightToFee; + type WeightInfo = weights::snowbridge_outbound_queue::WeightInfo; +} + +#[cfg(not(feature = "beacon-spec-mainnet"))] +parameter_types! { + pub const ChainForkVersions: ForkVersions = ForkVersions { + genesis: Fork { + version: [0, 0, 0, 1], // 0x00000001 + epoch: 0, + }, + altair: Fork { + version: [1, 0, 0, 1], // 0x01000001 + epoch: 0, + }, + bellatrix: Fork { + version: [2, 0, 0, 1], // 0x02000001 + epoch: 0, + }, + capella: Fork { + version: [3, 0, 0, 1], // 0x03000001 + epoch: 0, + }, + }; + pub const MaxExecutionHeadersToKeep:u32 = 1000; +} + +#[cfg(feature = "beacon-spec-mainnet")] +parameter_types! { + pub const ChainForkVersions: ForkVersions = ForkVersions { + genesis: Fork { + version: [0, 0, 16, 32], // 0x00001020 + epoch: 0, + }, + altair: Fork { + version: [1, 0, 16, 32], // 0x01001020 + epoch: 36660, + }, + bellatrix: Fork { + version: [2, 0, 16, 32], // 0x02001020 + epoch: 112260, + }, + capella: Fork { + version: [3, 0, 16, 32], // 0x03001020 + epoch: 162304, + }, + }; + pub const MaxExecutionHeadersToKeep:u32 = 8192 * 2; +} + +impl snowbridge_ethereum_beacon_client::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type ForkVersions = ChainForkVersions; + type MaxExecutionHeadersToKeep = MaxExecutionHeadersToKeep; + type WeightInfo = weights::snowbridge_ethereum_beacon_client::WeightInfo; +} + +parameter_types! { + // TODO: placeholder value - choose a real one + pub const MaxUpgradeDataSize: u32 = 1024; + pub const RelayNetwork: NetworkId = Rococo; +} + +parameter_types! { + pub TreasuryAccount: AccountId = PalletId(*b"py/trsry").into_account_truncating(); +} + +#[cfg(feature = "runtime-benchmarks")] +impl snowbridge_control::BenchmarkHelper for () { + fn make_xcm_origin(location: xcm::latest::MultiLocation) -> RuntimeOrigin { + RuntimeOrigin::from(pallet_xcm::Origin::Xcm(location)) + } +} + +impl snowbridge_control::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OwnParaId = ParachainInfo; + type OutboundQueue = EthereumOutboundQueue; + type MessageHasher = BlakeTwo256; + type SiblingOrigin = EnsureXcm; + type AgentIdOf = xcm_config::AgentIdOf; + type TreasuryAccount = TreasuryAccount; + type Token = Balances; + type WeightInfo = weights::snowbridge_control::WeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -505,6 +688,15 @@ construct_runtime!( BridgeWococoToRococoMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 45, BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 47, + + EthereumInboundQueue: snowbridge_inbound_queue::{Pallet, Call, Storage, Event} = 48, + EthereumOutboundQueue: snowbridge_outbound_queue::{Pallet, Call, Storage, Event} = 49, + EthereumBeaconClient: snowbridge_ethereum_beacon_client::{Pallet, Call, Storage, Event} = 50, + EthereumControl: snowbridge_control::{Pallet, Call, Storage, Event} = 51, + + // Message Queue. Registered after EthereumOutboundQueue so that their `on_initialize` handlers + // run in the desired order. + MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} = 60, } ); @@ -528,6 +720,7 @@ mod benches { [frame_system, SystemBench::] [pallet_balances, Balances] [pallet_multisig, Multisig] + [pallet_message_queue, MessageQueue] [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] @@ -548,6 +741,11 @@ mod benches { [pallet_bridge_messages, WococoToRococo] // Bridge relayer pallets [pallet_bridge_relayers, BridgeRelayersBench::] + // Ethereum Bridge + [snowbridge_inbound_queue, EthereumInboundQueue] + [snowbridge_outbound_queue, EthereumOutboundQueue] + [snowbridge_control, EthereumControl] + [snowbridge_ethereum_beacon_client, EthereumBeaconClient] ); } @@ -786,6 +984,23 @@ impl_runtime_apis! { } } + impl snowbridge_outbound_queue_runtime_api::OutboundQueueApi for Runtime { + fn prove_message(leaf_index: u64) -> Option { + snowbridge_outbound_queue::api::prove_message::(leaf_index) + } + + fn calculate_fee(message: Message) -> Option { + snowbridge_outbound_queue::api::calculate_fee::(message) + } + } + + impl snowbridge_control_runtime_api::ControlApi for Runtime { + fn agent_id(location: VersionedMultiLocation) -> Option { + snowbridge_control::api::agent_id::(location) + } + } + + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs index c41900097a1b..7a791db64756 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/mod.rs @@ -37,6 +37,10 @@ pub mod pallet_utility; pub mod pallet_xcm; pub mod paritydb_weights; pub mod rocksdb_weights; +pub mod snowbridge_control; +pub mod snowbridge_ethereum_beacon_client; +pub mod snowbridge_inbound_queue; +pub mod snowbridge_outbound_queue; pub mod xcm; pub use block_weights::constants::BlockExecutionWeight; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs new file mode 100644 index 000000000000..06e12a2a0382 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs @@ -0,0 +1,202 @@ + +//! Autogenerated weights for `snowbridge_control` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-10-09, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `crake.local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/polkadot-parachain +// benchmark +// pallet +// --chain +// bridge-hub-rococo-dev +// --pallet=snowbridge_control +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --output +// parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_control.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `snowbridge_control`. +pub struct WeightInfo(PhantomData); +impl snowbridge_control::WeightInfo for WeightInfo { + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn upgrade() -> Weight { + // Proof Size summary in bytes: + // Measured: `80` + // Estimated: `3517` + // Minimum execution time: 47_000_000 picoseconds. + Weight::from_parts(47_000_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: EthereumControl Agents (r:1 w:1) + /// Proof: EthereumControl Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn create_agent() -> Weight { + // Proof Size summary in bytes: + // Measured: `187` + // Estimated: `6196` + // Minimum execution time: 87_000_000 picoseconds. + Weight::from_parts(87_000_000, 0) + .saturating_add(Weight::from_parts(0, 6196)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(6)) + } + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: EthereumControl Agents (r:1 w:0) + /// Proof: EthereumControl Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: EthereumControl Channels (r:1 w:1) + /// Proof: EthereumControl Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:1 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn create_channel() -> Weight { + // Proof Size summary in bytes: + // Measured: `602` + // Estimated: `69050` + // Minimum execution time: 84_000_000 picoseconds. + Weight::from_parts(84_000_000, 0) + .saturating_add(Weight::from_parts(0, 69050)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: EthereumControl Channels (r:1 w:0) + /// Proof: EthereumControl Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn update_channel() -> Weight { + // Proof Size summary in bytes: + // Measured: `256` + // Estimated: `6044` + // Minimum execution time: 41_000_000 picoseconds. + Weight::from_parts(41_000_000, 0) + .saturating_add(Weight::from_parts(0, 6044)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: EthereumControl Channels (r:1 w:0) + /// Proof: EthereumControl Channels (max_values: None, max_size: Some(12), added: 2487, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn force_update_channel() -> Weight { + // Proof Size summary in bytes: + // Measured: `256` + // Estimated: `6044` + // Minimum execution time: 41_000_000 picoseconds. + Weight::from_parts(41_000_000, 0) + .saturating_add(Weight::from_parts(0, 6044)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:1 w:1) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:1) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn set_operating_mode() -> Weight { + // Proof Size summary in bytes: + // Measured: `80` + // Estimated: `3517` + // Minimum execution time: 30_000_000 picoseconds. + Weight::from_parts(30_000_000, 0) + .saturating_add(Weight::from_parts(0, 3517)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: EthereumControl Agents (r:1 w:0) + /// Proof: EthereumControl Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn transfer_native_from_agent() -> Weight { + // Proof Size summary in bytes: + // Measured: `252` + // Estimated: `6044` + // Minimum execution time: 43_000_000 picoseconds. + Weight::from_parts(43_000_000, 0) + .saturating_add(Weight::from_parts(0, 6044)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: EthereumControl Agents (r:1 w:0) + /// Proof: EthereumControl Agents (max_values: None, max_size: Some(40), added: 2515, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumOutboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: MessageQueue BookStateFor (r:2 w:2) + /// Proof: MessageQueue BookStateFor (max_values: None, max_size: Some(52), added: 2527, mode: MaxEncodedLen) + /// Storage: MessageQueue ServiceHead (r:1 w:0) + /// Proof: MessageQueue ServiceHead (max_values: Some(1), max_size: Some(5), added: 500, mode: MaxEncodedLen) + /// Storage: MessageQueue Pages (r:0 w:1) + /// Proof: MessageQueue Pages (max_values: None, max_size: Some(65585), added: 68060, mode: MaxEncodedLen) + fn force_transfer_native_from_agent() -> Weight { + // Proof Size summary in bytes: + // Measured: `252` + // Estimated: `6044` + // Minimum execution time: 42_000_000 picoseconds. + Weight::from_parts(42_000_000, 0) + .saturating_add(Weight::from_parts(0, 6044)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs new file mode 100644 index 000000000000..4ca518b45b87 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs @@ -0,0 +1,137 @@ + +//! Autogenerated weights for `snowbridge_ethereum_beacon_client` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-06-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-172-31-8-124`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/polkadot-parachain +// benchmark +// pallet +// --base-path +// /mnt/scratch/benchmark +// --chain=bridge-hub-rococo-dev +// --pallet=snowbridge_ethereum_beacon_client +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --steps +// 50 +// --repeat +// 20 +// --output +// ./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_ethereum_beacon_client.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `snowbridge_ethereum_beacon_client`. +pub struct WeightInfo(PhantomData); +impl snowbridge_ethereum_beacon_client::WeightInfo for WeightInfo { + /// Storage: EthereumBeaconClient FinalizedBeaconStateIndex (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconStateIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconStateMapping (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconStateMapping (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient NextSyncCommittee (r:0 w:1) + /// Proof: EthereumBeaconClient NextSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient InitialCheckpointRoot (r:0 w:1) + /// Proof: EthereumBeaconClient InitialCheckpointRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ValidatorsRoot (r:0 w:1) + /// Proof: EthereumBeaconClient ValidatorsRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:0 w:1) + /// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient CurrentSyncCommittee (r:0 w:1) + /// Proof: EthereumBeaconClient CurrentSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestExecutionState (r:0 w:1) + /// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconState (r:0 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + fn force_checkpoint() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `3501` + // Minimum execution time: 97_185_781_000 picoseconds. + Weight::from_parts(97_263_571_000, 0) + .saturating_add(Weight::from_parts(0, 3501)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(9)) + } + /// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:1 w:1) + /// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconState (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestExecutionState (r:1 w:0) + /// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient NextSyncCommittee (r:1 w:0) + /// Proof: EthereumBeaconClient NextSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient CurrentSyncCommittee (r:1 w:0) + /// Proof: EthereumBeaconClient CurrentSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ValidatorsRoot (r:1 w:0) + /// Proof: EthereumBeaconClient ValidatorsRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconStateIndex (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconStateIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconStateMapping (r:1 w:1) + /// Proof: EthereumBeaconClient FinalizedBeaconStateMapping (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + fn submit() -> Weight { + // Proof Size summary in bytes: + // Measured: `92753` + // Estimated: `93857` + // Minimum execution time: 25_999_968_000 picoseconds. + Weight::from_parts(26_051_019_000, 0) + .saturating_add(Weight::from_parts(0, 93857)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:1 w:0) + /// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconState (r:1 w:0) + /// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestExecutionState (r:1 w:0) + /// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient NextSyncCommittee (r:1 w:1) + /// Proof: EthereumBeaconClient NextSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient CurrentSyncCommittee (r:1 w:0) + /// Proof: EthereumBeaconClient CurrentSyncCommittee (max_values: Some(1), max_size: Some(92372), added: 92867, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ValidatorsRoot (r:1 w:0) + /// Proof: EthereumBeaconClient ValidatorsRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + fn submit_with_sync_committee() -> Weight { + // Proof Size summary in bytes: + // Measured: `92717` + // Estimated: `93857` + // Minimum execution time: 122_354_917_000 picoseconds. + Weight::from_parts(122_461_312_000, 0) + .saturating_add(Weight::from_parts(0, 93857)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: EthereumBeaconClient LatestFinalizedBlockRoot (r:1 w:0) + /// Proof: EthereumBeaconClient LatestFinalizedBlockRoot (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient FinalizedBeaconState (r:1 w:0) + /// Proof: EthereumBeaconClient FinalizedBeaconState (max_values: None, max_size: Some(72), added: 2547, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient LatestExecutionState (r:1 w:1) + /// Proof: EthereumBeaconClient LatestExecutionState (max_values: Some(1), max_size: Some(80), added: 575, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ExecutionHeaderIndex (r:1 w:1) + /// Proof: EthereumBeaconClient ExecutionHeaderIndex (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ExecutionHeaderMapping (r:1 w:1) + /// Proof: EthereumBeaconClient ExecutionHeaderMapping (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ExecutionHeaders (r:0 w:1) + /// Proof: EthereumBeaconClient ExecutionHeaders (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen) + fn submit_execution_header() -> Weight { + // Proof Size summary in bytes: + // Measured: `386` + // Estimated: `3537` + // Minimum execution time: 108_761_000 picoseconds. + Weight::from_parts(113_158_000, 0) + .saturating_add(Weight::from_parts(0, 3537)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs new file mode 100644 index 000000000000..ae04fa162504 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs @@ -0,0 +1,55 @@ + +//! Autogenerated weights for `snowbridge_inbound_queue` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-09-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `macbook pro 14 m2`, CPU: `m2-arm64` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/polkadot-parachain +// benchmark +// pallet +// --chain=bridge-hub-rococo-dev +// --pallet=snowbridge_inbound_queue +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --steps +// 50 +// --repeat +// 20 +// --output +// ./parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_inbound_queue.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `snowbridge_inbound_queue`. +pub struct WeightInfo(PhantomData); +impl snowbridge_inbound_queue::WeightInfo for WeightInfo { + /// Storage: EthereumInboundQueue PalletOperatingMode (r:1 w:0) + /// Proof: EthereumInboundQueue PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: EthereumBeaconClient ExecutionHeaders (r:1 w:0) + /// Proof: EthereumBeaconClient ExecutionHeaders (max_values: None, max_size: Some(136), added: 2611, mode: MaxEncodedLen) + /// Storage: EthereumInboundQueue Nonce (r:1 w:1) + /// Proof: EthereumInboundQueue Nonce (max_values: None, max_size: Some(20), added: 2495, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn submit() -> Weight { + // Proof Size summary in bytes: + // Measured: `457` + // Estimated: `3601` + // Minimum execution time: 69_000_000 picoseconds. + Weight::from_parts(70_000_000, 0) + .saturating_add(Weight::from_parts(0, 3601)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs new file mode 100644 index 000000000000..4836c0f830f5 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs @@ -0,0 +1,72 @@ +//! Autogenerated weights for `snowbridge_outbound_queue` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-10-20, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `192.168.1.13`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-rococo-dev"), DB CACHE: 1024 + +// Executed Command: +// ../target/release/polkadot-parachain +// benchmark +// pallet +// --chain=bridge-hub-rococo-dev +// --pallet=snowbridge_outbound_queue +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --output +// ../parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `snowbridge_outbound_queue`. +pub struct WeightInfo(PhantomData); +impl snowbridge_outbound_queue::WeightInfo for WeightInfo { + /// Storage: EthereumOutboundQueue MessageLeaves (r:1 w:1) + /// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: EthereumOutboundQueue PendingHighPriorityMessageCount (r:1 w:1) + /// Proof: EthereumOutboundQueue PendingHighPriorityMessageCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue Nonce (r:1 w:1) + /// Proof: EthereumOutboundQueue Nonce (max_values: None, max_size: Some(20), added: 2495, mode: MaxEncodedLen) + /// Storage: EthereumOutboundQueue Messages (r:1 w:1) + /// Proof Skipped: EthereumOutboundQueue Messages (max_values: Some(1), max_size: None, mode: Measured) + fn do_process_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `3485` + // Minimum execution time: 39_000_000 picoseconds. + Weight::from_parts(39_000_000, 3485) + .saturating_add(T::DbWeight::get().reads(4_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) + } + /// Storage: EthereumOutboundQueue MessageLeaves (r:1 w:0) + /// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Digest (r:1 w:1) + /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) + fn commit_messages() -> Weight { + // Proof Size summary in bytes: + // Measured: `1094` + // Estimated: `2579` + // Minimum execution time: 28_000_000 picoseconds. + Weight::from_parts(28_000_000, 2579) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + + fn commit_one_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `1094` + // Estimated: `2579` + // Minimum execution time: 9_000_000 picoseconds. + Weight::from_parts(9_000_000, 1586) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 703acfa44174..a01d9a26342c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -41,14 +41,16 @@ use parachains_common::{ use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; use rococo_runtime_constants::system_parachain::SystemParachains; -use sp_core::Get; +use snowbridge_router_primitives::outbound::EthereumBlobExporter; +use sp_core::{Get, H256}; use sp_runtime::traits::AccountIdConversion; use xcm::latest::prelude::*; use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, - DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, IsConcrete, ParentAsSuperuser, - ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily, + EnsureXcmOrigin, HashedDescription, IsConcrete, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeesToAccount, @@ -67,6 +69,21 @@ parameter_types! { pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; pub TreasuryAccount: Option = Some(TREASURY_PALLET_ID.into_account_truncating()); + + + // Network and location for the local Ethereum testnet. + pub const EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; + pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); + + pub const EthereumGatewayAddress: [u8; 20] = hex_literal::hex!("EDa338E4dC46038493b885327842fD3E301CaB39"); + // The Registry contract for the bridge which is also the origin for reserves and the prefix of all assets. + pub EthereumGatewayLocation: MultiLocation = EthereumLocation::get() + .pushed_with_interior( + AccountKey20 { + network: None, + key: EthereumGatewayAddress::get(), + } + ).unwrap(); } /// Adapter for resolving `NetworkId` based on `pub storage Flavor: RuntimeFlavor`. @@ -204,7 +221,15 @@ impl Contains for SafeCallFilter { RuntimeCall::BridgeWococoGrandpa(pallet_bridge_grandpa::Call::< Runtime, BridgeGrandpaWococoInstance, - >::initialize { .. }) + >::initialize { .. }) | + RuntimeCall::EthereumBeaconClient( + snowbridge_ethereum_beacon_client::Call::force_checkpoint { .. } | + snowbridge_ethereum_beacon_client::Call::set_operating_mode { .. }, + ) | RuntimeCall::EthereumInboundQueue( + snowbridge_inbound_queue::Call::set_operating_mode { .. }, + ) | RuntimeCall::EthereumOutboundQueue( + snowbridge_outbound_queue::Call::set_operating_mode { .. }, + ) | RuntimeCall::EthereumControl(..) ) } } @@ -306,6 +331,27 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; +#[cfg(feature = "runtime-benchmarks")] +pub(crate) mod benchmark_helper { + use crate::xcm_config::{ + MultiAssets, MultiLocation, SendError, SendResult, SendXcm, Xcm, XcmHash, + }; + + pub struct DoNothingRouter; + impl SendXcm for DoNothingRouter { + type Ticket = (); + fn validate( + _dest: &mut Option, + _msg: &mut Option>, + ) -> SendResult<()> { + Ok(((), MultiAssets::new())) + } + fn deliver(_: ()) -> Result { + Ok([0; 32]) + } + } +} + #[cfg(feature = "runtime-benchmarks")] parameter_types! { pub ReachableDest: Option = Some(Parent.into()); @@ -350,6 +396,15 @@ impl cumulus_pallet_xcm::Config for Runtime { type XcmExecutor = XcmExecutor; } +pub type AgentIdOf = HashedDescription>; + +pub type SnowbridgeExporter = EthereumBlobExporter< + UniversalLocation, + EthereumGatewayLocation, + snowbridge_outbound_queue::Pallet, + AgentIdOf, +>; + /// Hacky switch implementation, because we have just one runtime for Rococo and Wococo BridgeHub, /// so it means we have just one XcmConfig pub struct BridgeHubRococoOrBridgeHubWococoSwitchExporter; @@ -363,6 +418,7 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { destination: &mut Option, message: &mut Option>, ) -> SendResult { + let relay: NetworkId = RelayNetwork::get(); match network { Rococo => ToBridgeHubRococoHaulBlobExporter::validate( network, @@ -380,16 +436,40 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { message, ) .map(|result| ((Wococo, result.0), result.1)), + location if location == EthereumNetwork::get() && relay == Rococo => { + SnowbridgeExporter::validate( + network, + channel, + universal_source, + destination, + message, + ) + .map(|result| ((Ethereum { chain_id: 15 }, result.0), result.1)) // TODO get network ID + }, _ => unimplemented!("Unsupported network: {:?}", network), } } fn deliver(ticket: Self::Ticket) -> Result { let (network, ticket) = ticket; + let relay: NetworkId = RelayNetwork::get(); match network { Rococo => ToBridgeHubRococoHaulBlobExporter::deliver(ticket), Wococo => ToBridgeHubWococoHaulBlobExporter::deliver(ticket), + location if location == EthereumNetwork::get() && relay == Rococo => + SnowbridgeExporter::deliver(ticket), _ => unimplemented!("Unsupported network: {:?}", network), } } } + +pub struct AllowSiblingsOnly; +impl Contains for AllowSiblingsOnly { + fn contains(location: &MultiLocation) -> bool { + if let MultiLocation { parents: 1, interior: X1(Parachain(_)) } = location { + true + } else { + false + } + } +} diff --git a/cumulus/polkadot-parachain/Cargo.toml b/cumulus/polkadot-parachain/Cargo.toml index 3c2069c81ef4..9720e505b59f 100644 --- a/cumulus/polkadot-parachain/Cargo.toml +++ b/cumulus/polkadot-parachain/Cargo.toml @@ -145,3 +145,4 @@ try-runtime = [ "shell-runtime/try-runtime", "sp-runtime/try-runtime", ] +beacon-spec-mainnet = [] diff --git a/substrate/frame/nomination-pools/src/lib.rs b/substrate/frame/nomination-pools/src/lib.rs index 909a930e3821..8d78ff546a39 100644 --- a/substrate/frame/nomination-pools/src/lib.rs +++ b/substrate/frame/nomination-pools/src/lib.rs @@ -3406,6 +3406,7 @@ impl Pallet { // Warn if any pool has incorrect ED frozen. We don't want to fail hard as this could be a // result of an intentional ED change. + #[cfg(any(feature = "try-runtime", feature = "runtime-benchmarks", test, debug_assertions))] let _ = Self::check_ed_imbalance()?; Ok(()) From 95f3c78b8ad743cc6b9060a0b909a95568af3d84 Mon Sep 17 00:00:00 2001 From: Vincent Geddes Date: Mon, 30 Oct 2023 18:45:19 +0200 Subject: [PATCH 086/124] Runtime changes for refactored outbound-queue pallet --- Cargo.lock | 3 +-- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 10 ++-------- .../src/weights/snowbridge_outbound_queue.rs | 4 ++-- .../polkadot-parachain/src/chain_spec/bridge_hubs.rs | 1 + 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f36db27fbbb2..576e3836c943 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16797,7 +16797,6 @@ dependencies = [ name = "snowbridge-core" version = "0.1.1" dependencies = [ - "derivative", "ethabi-decode", "frame-support", "frame-system", @@ -16807,6 +16806,7 @@ dependencies = [ "serde", "snowbridge-beacon-primitives", "snowbridge-ethereum", + "sp-arithmetic", "sp-core", "sp-runtime", "sp-std", @@ -16898,7 +16898,6 @@ dependencies = [ "frame-system", "hex-literal", "parity-scale-codec", - "rlp", "scale-info", "serde", "snowbridge-core", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index c1c4ca880826..730a966f472d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -492,7 +492,7 @@ impl pallet_message_queue::Config for Runtime { type ServiceWeight = MessageQueueServiceWeight; type MessageProcessor = EthereumOutboundQueue; type QueueChangeHandler = (); - type QueuePausedQuery = (); + type QueuePausedQuery = EthereumOutboundQueue; type WeightInfo = (); } @@ -535,9 +535,6 @@ pub const GWEI: u128 = 1_000_000_000; parameter_types! { pub const MaxMessagePayloadSize: u32 = 2048; pub const MaxMessagesPerBlock: u32 = 32; - pub const DeliveryFeePerGas: u128 = 10; - pub const DeliveryRefundPerGas: u128 = 10 * GWEI; - pub const DeliveryReward: u128 = 1000 * GWEI; } impl snowbridge_outbound_queue::Config for Runtime { @@ -549,9 +546,6 @@ impl snowbridge_outbound_queue::Config for Runtime { type OwnParaId = ParachainInfo; type GasMeter = snowbridge_core::outbound::ConstantGasMeter; type Balance = Balance; - type DeliveryFeePerGas = DeliveryFeePerGas; - type DeliveryRefundPerGas = DeliveryRefundPerGas; - type DeliveryReward = DeliveryReward; type WeightToFee = WeightToFee; type WeightInfo = weights::snowbridge_outbound_queue::WeightInfo; } @@ -690,7 +684,7 @@ construct_runtime!( BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 47, EthereumInboundQueue: snowbridge_inbound_queue::{Pallet, Call, Storage, Event} = 48, - EthereumOutboundQueue: snowbridge_outbound_queue::{Pallet, Call, Storage, Event} = 49, + EthereumOutboundQueue: snowbridge_outbound_queue::{Pallet, Call, Storage, Config, Event} = 49, EthereumBeaconClient: snowbridge_ethereum_beacon_client::{Pallet, Call, Storage, Event} = 50, EthereumControl: snowbridge_control::{Pallet, Call, Storage, Event} = 51, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs index 4836c0f830f5..c5b872d7b362 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/weights/snowbridge_outbound_queue.rs @@ -50,7 +50,7 @@ impl snowbridge_outbound_queue::WeightInfo for WeightIn /// Proof Skipped: EthereumOutboundQueue MessageLeaves (max_values: Some(1), max_size: None, mode: Measured) /// Storage: System Digest (r:1 w:1) /// Proof Skipped: System Digest (max_values: Some(1), max_size: None, mode: Measured) - fn commit_messages() -> Weight { + fn commit() -> Weight { // Proof Size summary in bytes: // Measured: `1094` // Estimated: `2579` @@ -60,7 +60,7 @@ impl snowbridge_outbound_queue::WeightInfo for WeightIn .saturating_add(T::DbWeight::get().writes(1_u64)) } - fn commit_one_message() -> Weight { + fn commit_single() -> Weight { // Proof Size summary in bytes: // Measured: `1094` // Estimated: `2579` diff --git a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs index ca5583fe2e53..b6925453e837 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs @@ -325,6 +325,7 @@ pub mod rococo { owner: bridges_pallet_owner, ..Default::default() }, + ethereum_outbound_queue: Default::default(), } } } From c90619c478c39e46b2067e761521851f40ad37fc Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Mon, 30 Oct 2023 20:14:13 +0200 Subject: [PATCH 087/124] updates relay --- .../bridge-hubs/bridge-hub-rococo/src/xcm_config.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 97932241fb0f..bc1a0e57472c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -436,6 +436,7 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { destination: &mut Option, message: &mut Option>, ) -> SendResult { + let relay: NetworkId = RelayNetwork::get(); match network { Rococo => ToBridgeHubRococoHaulBlobExporter::validate( network, @@ -453,7 +454,7 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { message, ) .map(|result| ((Wococo, result.0), result.1)), - location if location == EthereumNetwork::get() && network == EthereumNetwork::get() => { // TODO check + location if location == EthereumNetwork::get() && relay == Rococo => { SnowbridgeExporter::validate( network, channel, @@ -469,12 +470,12 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { fn deliver(ticket: Self::Ticket) -> Result { let (network, ticket) = ticket; + let relay: NetworkId = RelayNetwork::get(); match network { Rococo => ToBridgeHubRococoHaulBlobExporter::deliver(ticket), Wococo => ToBridgeHubWococoHaulBlobExporter::deliver(ticket), - location if location == EthereumNetwork::get() && network == EthereumNetwork::get() => { // TODO check - SnowbridgeExporter::deliver(ticket) - }, + location if location == EthereumNetwork::get() && relay == Rococo => + SnowbridgeExporter::deliver(ticket), _ => unimplemented!("Unsupported network: {:?}", network), } } From 0f76530bfb21ad30452f6c60a33637a72a9bbd08 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 31 Oct 2023 16:20:31 +0200 Subject: [PATCH 088/124] Update polkadot/xcm/xcm-builder/src/barriers.rs Co-authored-by: Branislav Kontur --- polkadot/xcm/xcm-builder/src/barriers.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/polkadot/xcm/xcm-builder/src/barriers.rs b/polkadot/xcm/xcm-builder/src/barriers.rs index 50098791b443..3b13cab2c1ea 100644 --- a/polkadot/xcm/xcm-builder/src/barriers.rs +++ b/polkadot/xcm/xcm-builder/src/barriers.rs @@ -88,8 +88,6 @@ impl> ShouldExecute for AllowTopLevelPaidExecutionFro _ => Err(ProcessMessageError::BadFormat), })? .skip_inst_while(|inst| matches!(inst, ClearOrigin))? - // allow setting fees mode to jit or not for use in following `BuyExecution` - .skip_inst_while(|inst| matches!(inst, SetFeesMode { .. }))? .match_next_inst(|inst| match inst { BuyExecution { weight_limit: Limited(ref mut weight), .. } if weight.all_gte(max_weight) => From 9d3f2dda31bd3e75044e8a5932f2c6c1eafa142b Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 31 Oct 2023 16:21:08 +0200 Subject: [PATCH 089/124] Update polkadot/xcm/pallet-xcm/src/lib.rs Co-authored-by: Branislav Kontur --- polkadot/xcm/pallet-xcm/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index fcd51fd7b0f2..0d146dff9e44 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1219,7 +1219,7 @@ impl Pallet { ensure!(!x.is_zero(), Error::::Empty); } let transfer_type = - ::determine_for(&asset, dest) + T::XcmExecutor::determine_for(&asset, dest) .map_err(Error::::from)?; // Ensure asset is not teleportable to `dest`. ensure!(transfer_type != TransferType::Teleport, Error::::Filtered); From 9feb4b0103819eaac668cafde11b4840ecba0c7f Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 31 Oct 2023 16:21:23 +0200 Subject: [PATCH 090/124] Update polkadot/xcm/pallet-xcm/src/lib.rs Co-authored-by: Branislav Kontur --- polkadot/xcm/pallet-xcm/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 0d146dff9e44..f57a4720282b 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1259,7 +1259,7 @@ impl Pallet { } let fees = assets.swap_remove(fee_asset_item as usize); let fees_transfer_type = - ::determine_for(&fees, &dest) + T::XcmExecutor::determine_for(&fees, &dest) .map_err(Error::::from)?; let assets_transfer_type = if assets.is_empty() { // Single asset to transfer (one used for fees where transfer type is determined above). From 0a38b70d17fe5fb059e847381280769624372073 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 31 Oct 2023 16:21:39 +0200 Subject: [PATCH 091/124] Update polkadot/xcm/pallet-xcm/src/lib.rs Co-authored-by: Branislav Kontur --- polkadot/xcm/pallet-xcm/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index f57a4720282b..3cc2d600d62c 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1332,7 +1332,7 @@ impl Pallet { let (origin_location, assets) = value; for asset in assets.iter() { let transfer_type = - ::determine_for(asset, &dest) + T::XcmExecutor::determine_for(asset, &dest) .map_err(Error::::from)?; ensure!(matches!(transfer_type, TransferType::Teleport), Error::::Filtered); } From 02447d00d928b27bd94022fa87eac09ec1978af2 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Tue, 31 Oct 2023 16:22:56 +0200 Subject: [PATCH 092/124] fmt --- polkadot/xcm/pallet-xcm/src/lib.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 3cc2d600d62c..3af0a48b2440 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -1219,8 +1219,7 @@ impl Pallet { ensure!(!x.is_zero(), Error::::Empty); } let transfer_type = - T::XcmExecutor::determine_for(&asset, dest) - .map_err(Error::::from)?; + T::XcmExecutor::determine_for(&asset, dest).map_err(Error::::from)?; // Ensure asset is not teleportable to `dest`. ensure!(transfer_type != TransferType::Teleport, Error::::Filtered); if let Some(reserve) = reserve.as_ref() { @@ -1259,8 +1258,7 @@ impl Pallet { } let fees = assets.swap_remove(fee_asset_item as usize); let fees_transfer_type = - T::XcmExecutor::determine_for(&fees, &dest) - .map_err(Error::::from)?; + T::XcmExecutor::determine_for(&fees, &dest).map_err(Error::::from)?; let assets_transfer_type = if assets.is_empty() { // Single asset to transfer (one used for fees where transfer type is determined above). ensure!(fees_transfer_type != TransferType::Teleport, Error::::Filtered); @@ -1332,8 +1330,7 @@ impl Pallet { let (origin_location, assets) = value; for asset in assets.iter() { let transfer_type = - T::XcmExecutor::determine_for(asset, &dest) - .map_err(Error::::from)?; + T::XcmExecutor::determine_for(asset, &dest).map_err(Error::::from)?; ensure!(matches!(transfer_type, TransferType::Teleport), Error::::Filtered); } let fees = assets.get(fee_asset_item as usize).ok_or(Error::::Empty)?.clone(); From 0f1377ed2e727a1aa5b7cb9ef93810bba5d9f18c Mon Sep 17 00:00:00 2001 From: Vincent Geddes Date: Tue, 31 Oct 2023 20:13:31 +0200 Subject: [PATCH 093/124] Update bridge --- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 14 ++++---------- .../src/chain_spec/bridge_hubs.rs | 1 - 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 730a966f472d..a25355b93cea 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -530,19 +530,13 @@ impl snowbridge_inbound_queue::Config for Runtime { MessageToXcm; } -pub const GWEI: u128 = 1_000_000_000; - -parameter_types! { - pub const MaxMessagePayloadSize: u32 = 2048; - pub const MaxMessagesPerBlock: u32 = 32; -} - impl snowbridge_outbound_queue::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Hashing = Keccak256; type MessageQueue = MessageQueue; - type MaxMessagePayloadSize = MaxMessagePayloadSize; - type MaxMessagesPerBlock = MaxMessagesPerBlock; + type Decimals = ConstU8<12>; + type MaxMessagePayloadSize = ConstU32<2048>; + type MaxMessagesPerBlock = ConstU32<32>; type OwnParaId = ParachainInfo; type GasMeter = snowbridge_core::outbound::ConstantGasMeter; type Balance = Balance; @@ -684,7 +678,7 @@ construct_runtime!( BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 47, EthereumInboundQueue: snowbridge_inbound_queue::{Pallet, Call, Storage, Event} = 48, - EthereumOutboundQueue: snowbridge_outbound_queue::{Pallet, Call, Storage, Config, Event} = 49, + EthereumOutboundQueue: snowbridge_outbound_queue::{Pallet, Call, Storage, Event} = 49, EthereumBeaconClient: snowbridge_ethereum_beacon_client::{Pallet, Call, Storage, Event} = 50, EthereumControl: snowbridge_control::{Pallet, Call, Storage, Event} = 51, diff --git a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs index b6925453e837..ca5583fe2e53 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs @@ -325,7 +325,6 @@ pub mod rococo { owner: bridges_pallet_owner, ..Default::default() }, - ethereum_outbound_queue: Default::default(), } } } From 6372d2d7945d1cb70431632b7b562a776110f67f Mon Sep 17 00:00:00 2001 From: ron Date: Wed, 1 Nov 2023 11:21:43 +0800 Subject: [PATCH 094/124] Add WeightToFee to inbound queue config --- .../parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index c1c4ca880826..4fb2431151c3 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -528,6 +528,7 @@ impl snowbridge_inbound_queue::Config for Runtime { type Helper = Runtime; type MessageConverter = MessageToXcm; + type WeightToFee = WeightToFee; } pub const GWEI: u128 = 1_000_000_000; From 0652d74038fdf6445394314805a190e988ab6d66 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Wed, 1 Nov 2023 09:56:11 +0200 Subject: [PATCH 095/124] remove comments --- .../assets/asset-hub-rococo/src/xcm_config.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 4566d7bf13a6..4fcebe9be1bd 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -678,7 +678,6 @@ impl pallet_xcm::Config for Runtime { type XcmReserveTransferFilter = ( LocationWithAssetFilters, bridging::to_rococo::AllowedReserveTransferAssets, - //bridging::to_rococo::AllowedReserveTransferAssetsEthereum, bridging::to_wococo::AllowedReserveTransferAssets, ); @@ -908,11 +907,6 @@ pub mod bridging { AssetHubRococo::get() ); - /*pub EtherFromEthereum: (MultiAssetFilter, MultiLocation) = ( - EthereumGatewayLocation::get().into(), - EthereumGatewayLocation::get() - );*/ - /// Set up exporters configuration. /// `Option` represents static "base fee" which is used for total delivery fee calculation. pub BridgeTable: sp_std::vec::Vec = sp_std::vec![ @@ -986,12 +980,6 @@ pub mod bridging { AllowedReserveTransferAssetsToAssetHubRococo, >; - /* - pub type AllowedReserveTransferAssetsEthereum = LocationWithAssetFilters< - StartsWithExplicitGlobalConsensus, // TODO check - AllowedReserveTransferAssetsToEthereum, - >;*/ - impl Contains for ToRococoXcmRouter { fn contains(call: &RuntimeCall) -> bool { matches!( From 2f7d49eb5b49428236c0ee702d44ced6100c7268 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Wed, 1 Nov 2023 10:04:42 +0200 Subject: [PATCH 096/124] Add back treasury account --- .../runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 48bee1c6a430..5c8160da3ccb 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -69,6 +69,7 @@ parameter_types! { pub const MaxInstructions: u32 = 100; pub const MaxAssetsIntoHolding: u32 = 64; pub TreasuryAccount: Option = Some(TREASURY_PALLET_ID.into_account_truncating()); + pub RelayTreasuryLocation: MultiLocation = (Parent, PalletInstance(rococo_runtime_constants::TREASURY_PALLET_ID)).into(); // Network and location for the local Ethereum testnet. pub const EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; From f2d835060cd2463bf3f0bb17b32ef064eed33c2d Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Wed, 1 Nov 2023 10:06:04 +0200 Subject: [PATCH 097/124] fix warnings --- cumulus/parachains/runtimes/assets/common/src/matching.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index 91110f6cf1d2..6b0d8b0967e1 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -63,7 +63,8 @@ pub struct FromNetwork(sp_std::marker::PhantomData impl> ContainsPair for FromNetwork { - fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool { + fn contains(&a: &MultiLocation, _b: &MultiLocation) -> bool { + // TODO: check that a.starts_with(b) match a { MultiLocation { parents: 2, interior } => { matches!(interior.first(), Some(GlobalConsensus(network)) if *network == SelfNetworkId::get()) From 79197a35db823cdfacd5d105e5b6988d16d8798c Mon Sep 17 00:00:00 2001 From: ron Date: Wed, 1 Nov 2023 18:11:50 +0800 Subject: [PATCH 098/124] Update for benchmark --- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 6b5395248ac2..67237de0d9e7 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -98,11 +98,10 @@ use xcm::latest::prelude::*; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; -#[cfg(not(feature = "runtime-benchmarks"))] -use crate::xcm_config::AllowSiblingsOnly; use crate::{ bridge_hub_rococo_config::BridgeRefundBridgeHubWococoMessages, - bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages, xcm_config::XcmRouter, + bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages, + xcm_config::{AllowSiblingsOnly, XcmRouter}, }; use parachains_common::{ impls::DealWithFees, From 302d2f5122181f52a7e5f3a1a093afaf712cac63 Mon Sep 17 00:00:00 2001 From: ron Date: Wed, 1 Nov 2023 18:11:50 +0800 Subject: [PATCH 099/124] Update for benchmark --- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index a25355b93cea..277a8889d724 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -98,11 +98,10 @@ use xcm::latest::prelude::*; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; -#[cfg(not(feature = "runtime-benchmarks"))] -use crate::xcm_config::AllowSiblingsOnly; use crate::{ bridge_hub_rococo_config::BridgeRefundBridgeHubWococoMessages, - bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages, xcm_config::XcmRouter, + bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages, + xcm_config::{AllowSiblingsOnly, XcmRouter}, }; use parachains_common::{ impls::DealWithFees, From b67cb0f8ab13b20aba82c19d4b08ae84f9f71efc Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 1 Nov 2023 09:43:54 +0200 Subject: [PATCH 100/124] xcm-emulator: configure penpal for asset transfers and enhance existing tests --- .../src/tests/reserve_transfer.rs | 7 ++- .../asset-hub-rococo/src/tests/teleport.rs | 2 +- .../asset-hub-westend/src/tests/teleport.rs | 2 +- .../emulated/common/src/constants.rs | 15 +++-- .../runtimes/testing/penpal/src/xcm_config.rs | 56 ++++++------------- 5 files changed, 33 insertions(+), 49 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index a1b604fad02c..903c01ee921c 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -166,6 +166,7 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { let mut test = SystemParaToParaTest::new(test_args); let sender_balance_before = test.sender.balance; + let receiver_balance_before = test.receiver.balance; test.set_assertion::(system_para_to_para_assertions); // TODO: Add assertion for Penpal runtime. Right now message is failing with @@ -174,6 +175,7 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { test.assert(); let sender_balance_after = test.sender.balance; + let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubRococo::execute_with(|| { xcm_helpers::transfer_assets_delivery_fees::< @@ -181,9 +183,10 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) }); + // Sender's balance is reduced assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve - // transfers + // Receiver's balance is increased + assert!(receiver_balance_after > receiver_balance_before); } /// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs index 0d2ca6852470..297ee83d7535 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs @@ -51,7 +51,7 @@ fn relay_dest_assertions(t: SystemParaToRelayTest) { assert_expected_events!( Rococo, vec![ - // Amount is witdrawn from Relay Chain's `CheckAccount` + // Amount is withdrawn from Relay Chain's `CheckAccount` RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => { who: *who == ::XcmPallet::check_account(), amount: *amount == t.args.amount, diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs index 4fe0062dafcd..aca41322c3cf 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/teleport.rs @@ -53,7 +53,7 @@ fn relay_dest_assertions(t: SystemParaToRelayTest) { assert_expected_events!( Westend, vec![ - // Amount is witdrawn from Relay Chain's `CheckAccount` + // Amount is withdrawn from Relay Chain's `CheckAccount` RuntimeEvent::Balances(pallet_balances::Event::Withdraw { who, amount }) => { who: *who == ::XcmPallet::check_account(), amount: *amount == t.args.amount, diff --git a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs index 93abae753b94..6b2824bd09f2 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs @@ -386,6 +386,7 @@ pub mod asset_hub_westend { use super::*; pub const PARA_ID: u32 = 1000; pub const ED: Balance = parachains_common::westend::currency::EXISTENTIAL_DEPOSIT; + const ENDOWMENT: u128 = ED * 4096; pub fn genesis() -> Storage { let genesis_config = asset_hub_westend_runtime::RuntimeGenesisConfig { @@ -399,7 +400,7 @@ pub mod asset_hub_westend { balances: accounts::init_balances() .iter() .cloned() - .map(|k| (k, ED * 4096)) + .map(|k| (k, ENDOWMENT)) .collect(), }, parachain_info: asset_hub_westend_runtime::ParachainInfoConfig { @@ -442,6 +443,7 @@ pub mod asset_hub_rococo { use super::*; pub const PARA_ID: u32 = 1000; pub const ED: Balance = parachains_common::rococo::currency::EXISTENTIAL_DEPOSIT; + const ENDOWMENT: u128 = ED * 4096 * 4096; pub fn genesis() -> Storage { let genesis_config = asset_hub_rococo_runtime::RuntimeGenesisConfig { @@ -455,7 +457,7 @@ pub mod asset_hub_rococo { balances: accounts::init_balances() .iter() .cloned() - .map(|k| (k, ED * 4096 * 4096)) + .map(|k| (k, ENDOWMENT)) .collect(), }, parachain_info: asset_hub_rococo_runtime::ParachainInfoConfig { @@ -498,6 +500,7 @@ pub mod asset_hub_wococo { use super::*; pub const PARA_ID: u32 = 1000; pub const ED: Balance = parachains_common::wococo::currency::EXISTENTIAL_DEPOSIT; + const ENDOWMENT: u128 = ED * 4096; pub fn genesis() -> Storage { let genesis_config = asset_hub_rococo_runtime::RuntimeGenesisConfig { @@ -511,7 +514,7 @@ pub mod asset_hub_wococo { balances: accounts::init_balances() .iter() .cloned() - .map(|k| (k, ED * 4096)) + .map(|k| (k, ENDOWMENT)) .collect(), }, parachain_info: asset_hub_rococo_runtime::ParachainInfoConfig { @@ -556,6 +559,7 @@ pub mod penpal { pub const PARA_ID_A: u32 = 2000; pub const PARA_ID_B: u32 = 2001; pub const ED: Balance = penpal_runtime::EXISTENTIAL_DEPOSIT; + const ENDOWMENT: u128 = ED * 4096; pub fn genesis(para_id: u32) -> Storage { let genesis_config = penpal_runtime::RuntimeGenesisConfig { @@ -569,7 +573,7 @@ pub mod penpal { balances: accounts::init_balances() .iter() .cloned() - .map(|k| (k, ED * 4096)) + .map(|k| (k, ENDOWMENT)) .collect(), }, parachain_info: penpal_runtime::ParachainInfoConfig { @@ -616,6 +620,7 @@ pub mod bridge_hub_rococo { use super::*; pub const PARA_ID: u32 = 1013; pub const ED: Balance = parachains_common::rococo::currency::EXISTENTIAL_DEPOSIT; + const ENDOWMENT: u128 = ED * 4096; pub fn genesis() -> Storage { let genesis_config = bridge_hub_rococo_runtime::RuntimeGenesisConfig { @@ -629,7 +634,7 @@ pub mod bridge_hub_rococo { balances: accounts::init_balances() .iter() .cloned() - .map(|k| (k, ED * 4096)) + .map(|k| (k, ENDOWMENT)) .collect(), }, parachain_info: bridge_hub_rococo_runtime::ParachainInfoConfig { diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index 542d07fbed95..7dde53452d35 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -182,7 +182,7 @@ pub type Barrier = TrailingSetTopicAsId< /// Type alias to conveniently refer to `frame_system`'s `Config::AccountId`. pub type AccountIdOf = ::AccountId; -/// Asset filter that allows all assets from a certain location. +/// Asset filter that allows all assets from a certain location matching asset id. pub struct AssetsFrom(PhantomData); impl> ContainsPair for AssetsFrom { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { @@ -193,6 +193,17 @@ impl> ContainsPair for AssetsFr } } +/// Asset filter that allows native/relay asset if coming from a certain location. +pub struct NativeAssetFrom(PhantomData); +impl> ContainsPair for NativeAssetFrom { + fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { + let loc = T::get(); + &loc == origin && + matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } + if *asset_loc == MultiLocation::from(Parent)) + } +} + /// Allow checking in assets that have issuance > 0. pub struct NonZeroIssuance(PhantomData<(AccountId, Assets)>); impl Contains<>::AssetId> @@ -221,43 +232,6 @@ where } } -pub trait Reserve { - /// Returns assets reserve location. - fn reserve(&self) -> Option; -} - -// Takes the chain part of a MultiAsset -impl Reserve for MultiAsset { - fn reserve(&self) -> Option { - if let AssetId::Concrete(location) = self.id { - let first_interior = location.first_interior(); - let parents = location.parent_count(); - match (parents, first_interior) { - (0, Some(Parachain(id))) => Some(MultiLocation::new(0, X1(Parachain(*id)))), - (1, Some(Parachain(id))) => Some(MultiLocation::new(1, X1(Parachain(*id)))), - (1, _) => Some(MultiLocation::parent()), - _ => None, - } - } else { - None - } - } -} - -/// A `FilterAssetLocation` implementation. Filters multi native assets whose -/// reserve is same with `origin`. -pub struct MultiNativeAsset; -impl ContainsPair for MultiNativeAsset { - fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { - if let Some(ref reserve) = asset.reserve() { - if reserve == origin { - return true - } - } - false - } -} - parameter_types! { /// The location that this chain recognizes as the Relay network's Asset Hub. pub SystemAssetHubLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(1000))); @@ -268,7 +242,8 @@ parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); } -pub type Reserves = (NativeAsset, AssetsFrom); +pub type Reserves = + (NativeAsset, AssetsFrom, NativeAssetFrom); pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { @@ -277,7 +252,8 @@ impl xcm_executor::Config for XcmConfig { // How to withdraw and deposit an asset. type AssetTransactor = AssetTransactors; type OriginConverter = XcmOriginToTransactDispatchOrigin; - type IsReserve = MultiNativeAsset; // TODO: maybe needed to be replaced by Reserves + type IsReserve = Reserves; + // no teleport trust established with other chains type IsTeleporter = NativeAsset; type UniversalLocation = UniversalLocation; type Barrier = Barrier; From ec87ce6d97c85c5c50a9205bbc7d2a30689f1a07 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 1 Nov 2023 11:00:16 +0200 Subject: [PATCH 101/124] xcm-emulator: add relay to penpal native transfer test --- Cargo.lock | 3 + .../assets/asset-hub-rococo/Cargo.toml | 2 + .../assets/asset-hub-rococo/src/lib.rs | 20 ++-- .../src/tests/reserve_transfer.rs | 109 +++++++++++++++++- .../asset-hub-rococo/src/tests/teleport.rs | 8 +- .../assets/asset-hub-westend/Cargo.toml | 1 + .../src/tests/reserve_transfer.rs | 29 +++-- 7 files changed, 147 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6af9c3efdf56..0c35615ddaa4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -879,6 +879,8 @@ dependencies = [ "assert_matches", "asset-hub-rococo-runtime", "asset-test-utils", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-xcmp-queue", "frame-support", "frame-system", "integration-tests-common", @@ -985,6 +987,7 @@ dependencies = [ "asset-test-utils", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", + "cumulus-pallet-xcmp-queue", "frame-support", "frame-system", "integration-tests-common", diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml index db58d8d33039..5b8ad06d63bd 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml @@ -32,6 +32,8 @@ rococo-runtime = { path = "../../../../../../polkadot/runtime/rococo", default-f asset-test-utils = { path = "../../../../runtimes/assets/test-utils", default-features = false } parachains-common = { path = "../../../../common" } asset-hub-rococo-runtime = { path = "../../../../runtimes/assets/asset-hub-rococo" } +cumulus-pallet-dmp-queue = { path = "../../../../../pallets/dmp-queue", default-features = false} +cumulus-pallet-xcmp-queue = { path = "../../../../../pallets/xcmp-queue", default-features = false} # Local xcm-emulator = { path = "../../../../../xcm/xcm-emulator", default-features = false} diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs index 42f54bdf49df..686d9e3f0d36 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs @@ -49,18 +49,20 @@ pub const ASSET_MIN_BALANCE: u128 = 1000; pub const ASSETS_PALLET_ID: u8 = 50; pub type RelayToSystemParaTest = Test; +pub type RelayToParaTest = Test; pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; +pub type ParaToSystemParaTest = Test; -/// Returns a `TestArgs` instance to de used for the Relay Chain accross integraton tests -pub fn relay_test_args(amount: Balance) -> TestArgs { +/// Returns a `TestArgs` instance to de used for the Relay Chain across integration tests +pub fn relay_test_args( + dest: MultiLocation, + beneficiary_id: AccountId32, + amount: Balance, +) -> TestArgs { TestArgs { - dest: Rococo::child_location_of(AssetHubRococo::para_id()), - beneficiary: AccountId32Junction { - network: None, - id: AssetHubRococoReceiver::get().into(), - } - .into(), + dest, + beneficiary: AccountId32Junction { network: None, id: beneficiary_id.into() }.into(), amount, assets: (Here, amount).into(), asset_id: None, @@ -69,7 +71,7 @@ pub fn relay_test_args(amount: Balance) -> TestArgs { } } -/// Returns a `TestArgs` instance to de used for the System Parachain accross integraton tests +/// Returns a `TestArgs` instance to de used for the System Parachain across integration tests pub fn system_para_test_args( dest: MultiLocation, beneficiary_id: AccountId32, diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index 903c01ee921c..08873a9ce548 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -15,8 +15,45 @@ use crate::*; use asset_hub_rococo_runtime::xcm_config::XcmConfig as AssetHubRococoXcmConfig; +use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig; -fn system_para_to_para_assertions(t: SystemParaToParaTest) { +fn relay_to_para_sender_assertions(t: RelayToParaTest) { + type RuntimeEvent = ::RuntimeEvent; + + Rococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts(864_610_000, 8_799))); + + assert_expected_events!( + Rococo, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::Balances( + pallet_balances::Event::Transfer { from, to, amount } + ) => { + from: *from == t.sender.account_id, + to: *to == Rococo::sovereign_account_id_of( + t.args.dest + ), + amount: *amount == t.args.amount, + }, + ] + ); +} + +fn relay_to_para_receiver_assertions(_: Test) { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + PenpalRococoA, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, + RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward { + outcome: Outcome::Complete(_), + .. + }) => {}, + ] + ); +} + +fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; AssetHubRococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( @@ -27,7 +64,7 @@ fn system_para_to_para_assertions(t: SystemParaToParaTest) { assert_expected_events!( AssetHubRococo, vec![ - // Amount to reserve transfer is transferred to Parachain's Sovereing account + // Amount to reserve transfer is transferred to Parachain's Sovereign account RuntimeEvent::Balances( pallet_balances::Event::Transfer { from, to, amount } ) => { @@ -41,6 +78,17 @@ fn system_para_to_para_assertions(t: SystemParaToParaTest) { ); } +fn system_para_to_para_receiver_assertions(_: Test) { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + PenpalRococoA, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + ] + ); +} + fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -52,7 +100,7 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { assert_expected_events!( AssetHubRococo, vec![ - // Amount to reserve transfer is transferred to Parachain's Sovereing account + // Amount to reserve transfer is transferred to Parachain's Sovereign account RuntimeEvent::Assets( pallet_assets::Event::Transferred { asset_id, from, to, amount } ) => { @@ -67,6 +115,17 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { ); } +fn relay_to_para_limited_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { + ::XcmPallet::limited_reserve_transfer_assets( + t.signed_origin, + bx!(t.args.dest.into()), + bx!(t.args.beneficiary.into()), + bx!(t.args.assets.into()), + t.args.fee_asset_item, + t.args.weight_limit, + ) +} + fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) -> DispatchResult { ::PolkadotXcm::limited_reserve_transfer_assets( t.signed_origin, @@ -148,6 +207,45 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_relay_fails() { }); } +/// Limited Reserve Transfers of native asset from Relay to Parachain should work +#[test] +fn limited_reserve_transfer_native_asset_from_relay_to_para() { + // Init values for Relay + let destination = Rococo::child_location_of(PenpalRococoA::para_id()); + let beneficiary_id = PenpalRococoAReceiver::get(); + let amount_to_send: Balance = ROCOCO_ED * 1000; + + let test_args = TestContext { + sender: RococoSender::get(), + receiver: PenpalRococoAReceiver::get(), + args: relay_test_args(destination, beneficiary_id, amount_to_send), + }; + + let mut test = RelayToParaTest::new(test_args); + + let sender_balance_before = test.sender.balance; + let receiver_balance_before = test.receiver.balance; + + test.set_assertion::(relay_to_para_sender_assertions); + test.set_assertion::(relay_to_para_receiver_assertions); + test.set_dispatchable::(relay_to_para_limited_reserve_transfer_assets); + test.assert(); + + let sender_balance_after = test.sender.balance; + let receiver_balance_after = test.receiver.balance; + + let delivery_fees = Rococo::execute_with(|| { + xcm_helpers::transfer_assets_delivery_fees::< + ::XcmSender, + >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + }); + + // Sender's balance is reduced + assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + // Receiver's balance is increased + assert!(receiver_balance_after > receiver_balance_before); +} + /// Limited Reserve Transfers of native asset from System Parachain to Parachain should work #[test] fn limited_reserve_transfer_native_asset_from_system_para_to_para() { @@ -168,9 +266,8 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { let sender_balance_before = test.sender.balance; let receiver_balance_before = test.receiver.balance; - test.set_assertion::(system_para_to_para_assertions); - // TODO: Add assertion for Penpal runtime. Right now message is failing with - // `UntrustedReserveLocation` + test.set_assertion::(system_para_to_para_sender_assertions); + test.set_assertion::(system_para_to_para_receiver_assertions); test.set_dispatchable::(system_para_to_para_limited_reserve_transfer_assets); test.assert(); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs index 297ee83d7535..09f1e6c0a590 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs @@ -157,10 +157,12 @@ fn system_para_teleport_assets(t: SystemParaToRelayTest) -> DispatchResult { fn limited_teleport_native_assets_from_relay_to_system_para_works() { // Init values for Relay Chain let amount_to_send: Balance = ROCOCO_ED * 1000; + let dest = Rococo::child_location_of(AssetHubRococo::para_id()); + let beneficiary_id = AssetHubRococoReceiver::get(); let test_args = TestContext { sender: RococoSender::get(), receiver: AssetHubRococoReceiver::get(), - args: relay_test_args(amount_to_send), + args: relay_test_args(dest, beneficiary_id, amount_to_send), }; let mut test = RelayToSystemParaTest::new(test_args); @@ -278,10 +280,12 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { fn teleport_native_assets_from_relay_to_system_para_works() { // Init values for Relay Chain let amount_to_send: Balance = ROCOCO_ED * 1000; + let dest = Rococo::child_location_of(AssetHubRococo::para_id()); + let beneficiary_id = AssetHubRococoReceiver::get(); let test_args = TestContext { sender: RococoSender::get(), receiver: AssetHubRococoReceiver::get(), - args: relay_test_args(amount_to_send), + args: relay_test_args(dest, beneficiary_id, amount_to_send), }; let mut test = RelayToSystemParaTest::new(test_args); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/Cargo.toml index 4b6b8874b6a4..87f3c1d4b513 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/Cargo.toml @@ -39,6 +39,7 @@ asset-hub-westend-runtime = { path = "../../../../runtimes/assets/asset-hub-west asset-test-utils = { path = "../../../../runtimes/assets/test-utils", default-features = false } cumulus-pallet-dmp-queue = { default-features = false, path = "../../../../../pallets/dmp-queue" } cumulus-pallet-parachain-system = { default-features = false, path = "../../../../../pallets/parachain-system" } +cumulus-pallet-xcmp-queue = { path = "../../../../../pallets/xcmp-queue", default-features = false} # Local xcm-emulator = { path = "../../../../../xcm/xcm-emulator", default-features = false} diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs index c7a25dde78d3..518e117c1074 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -16,7 +16,7 @@ use crate::*; use asset_hub_westend_runtime::xcm_config::XcmConfig; -fn system_para_to_para_assertions(t: SystemParaToParaTest) { +fn system_para_to_para_sender_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; AssetHubWestend::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( @@ -27,7 +27,7 @@ fn system_para_to_para_assertions(t: SystemParaToParaTest) { assert_expected_events!( AssetHubWestend, vec![ - // Amount to reserve transfer is transferred to Parachain's Sovereing account + // Amount to reserve transfer is transferred to Parachain's Sovereign account RuntimeEvent::Balances( pallet_balances::Event::Transfer { from, to, amount } ) => { @@ -41,6 +41,17 @@ fn system_para_to_para_assertions(t: SystemParaToParaTest) { ); } +fn para_receiver_assertions(_: Test) { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + PenpalWestendA, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + ] + ); +} + fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -52,7 +63,7 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { assert_expected_events!( AssetHubWestend, vec![ - // Amount to reserve transfer is transferred to Parachain's Sovereing account + // Amount to reserve transfer is transferred to Parachain's Sovereign account RuntimeEvent::Assets( pallet_assets::Event::Transferred { asset_id, from, to, amount } ) => { @@ -165,14 +176,15 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { let mut test = SystemParaToParaTest::new(test_args); let sender_balance_before = test.sender.balance; + let receiver_balance_before = test.receiver.balance; - test.set_assertion::(system_para_to_para_assertions); - // TODO: Add assertion for Penpal runtime. Right now message is failing with - // `UntrustedReserveLocation` + test.set_assertion::(system_para_to_para_sender_assertions); + test.set_assertion::(para_receiver_assertions); test.set_dispatchable::(system_para_to_para_limited_reserve_transfer_assets); test.assert(); let sender_balance_after = test.sender.balance; + let receiver_balance_after = test.receiver.balance; let delivery_fees = AssetHubWestend::execute_with(|| { xcm_helpers::transfer_assets_delivery_fees::<::XcmSender>( @@ -184,9 +196,10 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { ) }); + // Sender's balance is reduced assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); - // TODO: Check receiver balance when Penpal runtime is improved to propery handle reserve - // transfers + // Receiver's balance is increased + assert!(receiver_balance_after > receiver_balance_before); } /// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work From da3c12e89f5e21aaabe43b8be58c77e65d2a7b97 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 1 Nov 2023 13:47:04 +0200 Subject: [PATCH 102/124] xcm-emulator: add ah to penpal native asset transfer test --- Cargo.lock | 1 + .../assets/asset-hub-rococo/Cargo.toml | 1 + .../assets/asset-hub-rococo/src/lib.rs | 6 +- .../src/tests/reserve_transfer.rs | 113 +++++++++++++++++- .../asset-hub-rococo/src/tests/teleport.rs | 8 +- .../assets/asset-hub-westend/src/lib.rs | 4 +- .../bridges/bridge-hub-rococo/src/lib.rs | 2 +- .../emulated/common/src/lib.rs | 2 + 8 files changed, 123 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c35615ddaa4..066cc394bd82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -890,6 +890,7 @@ dependencies = [ "pallet-xcm", "parachains-common", "parity-scale-codec", + "penpal-runtime", "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-runtime-parachains", diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml index 5b8ad06d63bd..820429deae45 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml @@ -32,6 +32,7 @@ rococo-runtime = { path = "../../../../../../polkadot/runtime/rococo", default-f asset-test-utils = { path = "../../../../runtimes/assets/test-utils", default-features = false } parachains-common = { path = "../../../../common" } asset-hub-rococo-runtime = { path = "../../../../runtimes/assets/asset-hub-rococo" } +penpal-runtime = { path = "../../../../runtimes/testing/penpal" } cumulus-pallet-dmp-queue = { path = "../../../../../pallets/dmp-queue", default-features = false} cumulus-pallet-xcmp-queue = { path = "../../../../../pallets/xcmp-queue", default-features = false} diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs index 686d9e3f0d36..6da7537e82f4 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs @@ -54,7 +54,7 @@ pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; pub type ParaToSystemParaTest = Test; -/// Returns a `TestArgs` instance to de used for the Relay Chain across integration tests +/// Returns a `TestArgs` instance to be used for the Relay Chain across integration tests pub fn relay_test_args( dest: MultiLocation, beneficiary_id: AccountId32, @@ -71,8 +71,8 @@ pub fn relay_test_args( } } -/// Returns a `TestArgs` instance to de used for the System Parachain across integration tests -pub fn system_para_test_args( +/// Returns a `TestArgs` instance to be used by parachains across integration tests +pub fn para_test_args( dest: MultiLocation, beneficiary_id: AccountId32, amount: Balance, diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index 08873a9ce548..14b2aae7a8e0 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -15,6 +15,7 @@ use crate::*; use asset_hub_rococo_runtime::xcm_config::XcmConfig as AssetHubRococoXcmConfig; +use penpal_runtime::xcm_config::XcmConfig as PenpalRococoXcmConfig; use rococo_runtime::xcm_config::XcmConfig as RococoXcmConfig; fn relay_to_para_sender_assertions(t: RelayToParaTest) { @@ -89,6 +90,51 @@ fn system_para_to_para_receiver_assertions(_: Test) { ); } +fn para_to_system_para_sender_assertions(t: ParaToSystemParaTest) { + type RuntimeEvent = ::RuntimeEvent; + + PenpalRococoA::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( + 864_610_000, + 8_799, + ))); + + assert_expected_events!( + PenpalRococoA, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::Balances( + pallet_balances::Event::Withdraw { who, amount } + ) => { + who: *who == t.sender.account_id, + amount: *amount == t.args.amount, + }, + ] + ); +} + +fn para_to_system_para_receiver_assertions(t: ParaToSystemParaTest) { + type RuntimeEvent = ::RuntimeEvent; + + let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of( + AssetHubRococo::sibling_location_of(PenpalRococoA::para_id()), + ); + + assert_expected_events!( + AssetHubRococo, + vec![ + // Amount to reserve transfer is transferred to Parachain's Sovereign account + RuntimeEvent::Balances( + pallet_balances::Event::Withdraw { who, amount } + ) => { + who: *who == sov_penpal_on_ahr.clone().into(), + amount: *amount == t.args.amount, + }, + RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + ] + ); +} + fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; @@ -137,6 +183,17 @@ fn system_para_to_para_limited_reserve_transfer_assets(t: SystemParaToParaTest) ) } +fn para_to_system_para_limited_reserve_transfer_assets(t: ParaToSystemParaTest) -> DispatchResult { + ::PolkadotXcm::limited_reserve_transfer_assets( + t.signed_origin, + bx!(t.args.dest.into()), + bx!(t.args.beneficiary.into()), + bx!(t.args.assets.into()), + t.args.fee_asset_item, + t.args.weight_limit, + ) +} + /// Limited Reserve Transfers of native asset from Relay Chain to the System Parachain shouldn't /// work #[test] @@ -258,7 +315,7 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: PenpalRococoAReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), }; let mut test = SystemParaToParaTest::new(test_args); @@ -286,6 +343,54 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { assert!(receiver_balance_after > receiver_balance_before); } +/// Limited Reserve Transfers of native asset from Parachain to System Parachain should work +#[test] +fn limited_reserve_transfer_native_asset_from_para_to_system_para() { + // Init values for Penpal Parachain + let destination = PenpalRococoA::sibling_location_of(AssetHubRococo::para_id()); + let beneficiary_id = AssetHubRococoReceiver::get(); + let amount_to_send: Balance = ASSET_HUB_ROCOCO_ED * 1000; + let assets = (Parent, amount_to_send).into(); + + let test_args = TestContext { + sender: PenpalRococoASender::get(), + receiver: AssetHubRococoReceiver::get(), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + }; + + let mut test = ParaToSystemParaTest::new(test_args); + + let sender_balance_before = test.sender.balance; + let receiver_balance_before = test.receiver.balance; + + // MultiLocation { parents: 1, interior: X1(Parachain(PenpalRococoA::para_id().into())) }; + let penpal_location_as_seen_by_ahr = + AssetHubRococo::sibling_location_of(PenpalRococoA::para_id()); + let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location_as_seen_by_ahr); + + // fund the Penpal's SA on AHR with the native tokens held in reserve + AssetHubRococo::fund_accounts(vec![(sov_penpal_on_ahr.into(), amount_to_send * 2)]); + + test.set_assertion::(para_to_system_para_sender_assertions); + test.set_assertion::(para_to_system_para_receiver_assertions); + test.set_dispatchable::(para_to_system_para_limited_reserve_transfer_assets); + test.assert(); + + let sender_balance_after = test.sender.balance; + let receiver_balance_after = test.receiver.balance; + + let delivery_fees = PenpalRococoA::execute_with(|| { + xcm_helpers::transfer_assets_delivery_fees::< + ::XcmSender, + >(test.args.assets.clone(), 0, test.args.weight_limit, test.args.beneficiary, test.args.dest) + }); + + // Sender's balance is reduced + assert_eq!(sender_balance_before - amount_to_send - delivery_fees, sender_balance_after); + // Receiver's balance is increased + assert!(receiver_balance_after > receiver_balance_before); +} + /// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work #[test] fn limited_reserve_transfer_asset_from_system_para_to_para() { @@ -307,13 +412,13 @@ fn limited_reserve_transfer_asset_from_system_para_to_para() { (X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send) .into(); - let system_para_test_args = TestContext { + let para_test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: PenpalRococoAReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), }; - let mut system_para_test = SystemParaToParaTest::new(system_para_test_args); + let mut system_para_test = SystemParaToParaTest::new(para_test_args); system_para_test.set_assertion::(system_para_to_para_assets_assertions); // TODO: Add assertions when Penpal is able to manage assets diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs index 09f1e6c0a590..217bac6865c8 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs @@ -206,7 +206,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: RococoReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), }; let mut test = SystemParaToRelayTest::new(test_args); @@ -247,7 +247,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: RococoReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), }; let mut test = SystemParaToRelayTest::new(test_args); @@ -329,7 +329,7 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: RococoReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), }; let mut test = SystemParaToRelayTest::new(test_args); @@ -370,7 +370,7 @@ fn teleport_native_assets_from_system_para_to_relay_fails() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: RococoReceiver::get(), - args: system_para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), }; let mut test = SystemParaToRelayTest::new(test_args); diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs index 2ade5f81d8a9..d3ad32f7c946 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/lib.rs @@ -53,7 +53,7 @@ pub type RelayToSystemParaTest = Test; pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; -/// Returns a `TestArgs` instance to de used for the Relay Chain across integration tests +/// Returns a `TestArgs` instance to be used for the Relay Chain across integration tests pub fn relay_test_args(amount: Balance) -> TestArgs { TestArgs { dest: Westend::child_location_of(AssetHubWestend::para_id()), @@ -70,7 +70,7 @@ pub fn relay_test_args(amount: Balance) -> TestArgs { } } -/// Returns a `TestArgs` instance to de used for the System Parachain across integration tests +/// Returns a `TestArgs` instance to be used for the System Parachain across integration tests pub fn system_para_test_args( dest: MultiLocation, beneficiary_id: AccountId32, diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs index ecf773765b3e..ab7043b37f8f 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs @@ -46,7 +46,7 @@ pub type RelayToSystemParaTest = Test; pub type SystemParaToRelayTest = Test; pub type SystemParaToParaTest = Test; -/// Returns a `TestArgs` instance to de used for the Relay Chain across integration tests +/// Returns a `TestArgs` instance to be used for the Relay Chain across integration tests pub fn relay_test_args(amount: Balance) -> TestArgs { TestArgs { dest: Rococo::child_location_of(AssetHubRococo::para_id()), diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index 8a8081c9fac3..1ec006f4510b 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -189,6 +189,7 @@ decl_test_parachains! { pallets = { PolkadotXcm: penpal_runtime::PolkadotXcm, Assets: penpal_runtime::Assets, + Balances: penpal_runtime::Balances, } }, pub struct PenpalRococoB { @@ -326,6 +327,7 @@ impl_accounts_helpers_for_parachain!(BridgeHubRococo); impl_assert_events_helpers_for_parachain!(BridgeHubRococo); // PenpalRococo implementations +impl_accounts_helpers_for_parachain!(PenpalRococoA); impl_assert_events_helpers_for_parachain!(PenpalRococoA); impl_assert_events_helpers_for_parachain!(PenpalRococoB); From ac9bf49411b9de4545ad4ef97d696a74bd536871 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 1 Nov 2023 17:43:00 +0200 Subject: [PATCH 103/124] xcm: MultiLocation::chain_location() takes nonmut reference --- polkadot/xcm/src/v3/multilocation.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/polkadot/xcm/src/v3/multilocation.rs b/polkadot/xcm/src/v3/multilocation.rs index f948340abcb5..a685c15c7d98 100644 --- a/polkadot/xcm/src/v3/multilocation.rs +++ b/polkadot/xcm/src/v3/multilocation.rs @@ -446,17 +446,18 @@ impl MultiLocation { } /// Return the MultiLocation subsection identifying the chain that `self` points to. - pub fn chain_location(mut self) -> MultiLocation { + pub fn chain_location(&self) -> MultiLocation { + let mut clone = self.clone(); // start popping junctions until we reach chain identifier - while let Some(j) = self.last() { + while let Some(j) = clone.last() { if matches!(j, Junction::Parachain(_) | Junction::GlobalConsensus(_)) { // return chain subsection - return self + return clone } else { - (self, _) = self.split_last_interior(); + (clone, _) = clone.split_last_interior(); } } - MultiLocation::new(self.parents, Junctions::Here) + MultiLocation::new(clone.parents, Junctions::Here) } } From e85e3390609ee69bda7316c03bbe0622042fda7a Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 1 Nov 2023 18:01:32 +0200 Subject: [PATCH 104/124] pallet-xcm: benchmarks: enforce single asset transfer at the api level --- .../assets/asset-hub-kusama/src/lib.rs | 8 ++--- .../assets/asset-hub-polkadot/src/lib.rs | 8 ++--- .../assets/asset-hub-rococo/src/lib.rs | 8 ++--- .../assets/asset-hub-westend/src/lib.rs | 8 ++--- .../bridge-hubs/bridge-hub-kusama/src/lib.rs | 6 ++-- .../bridge-hub-polkadot/src/lib.rs | 6 ++-- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 6 ++-- .../collectives-polkadot/src/lib.rs | 4 +-- .../contracts/contracts-rococo/src/lib.rs | 6 ++-- polkadot/runtime/rococo/src/lib.rs | 8 ++--- polkadot/runtime/westend/src/lib.rs | 11 +++---- polkadot/xcm/pallet-xcm/src/benchmarking.rs | 30 +++++++------------ polkadot/xcm/pallet-xcm/src/mock.rs | 8 ++--- 13 files changed, 52 insertions(+), 65 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index 25d5712f4dfb..e5261cf06b63 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -1217,18 +1217,18 @@ impl_runtime_apis! { Some(Parent.into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported between AH and Relay. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, Parent.into(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // AH can reserve transfer native token to some random parachain. let random_para_id = 43211234; ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( @@ -1238,7 +1238,7 @@ impl_runtime_apis! { MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, ParentThen(Parachain(random_para_id).into()).into(), )) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index dd111355c02b..99898c1a5b44 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -1096,18 +1096,18 @@ impl_runtime_apis! { Some(Parent.into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported between AH and Relay. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, Parent.into(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // AH can reserve transfer native token to some random parachain. let random_para_id = 43211234; ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( @@ -1117,7 +1117,7 @@ impl_runtime_apis! { MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, ParentThen(Parachain(random_para_id).into()).into(), )) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 1f54c3ca997b..06787c9e1e7e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -1305,18 +1305,18 @@ impl_runtime_apis! { Some(Parent.into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported between AH and Relay. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, Parent.into(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // AH can reserve transfer native token to some random parachain. let random_para_id = 43211234; ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( @@ -1326,7 +1326,7 @@ impl_runtime_apis! { MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, ParentThen(Parachain(random_para_id).into()).into(), )) } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index cc04db22785b..e23b9b36e12d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -1281,18 +1281,18 @@ impl_runtime_apis! { Some(Parent.into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported between AH and Relay. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, Parent.into(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // AH can reserve transfer native token to some random parachain. let random_para_id = 43211234; ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( @@ -1302,7 +1302,7 @@ impl_runtime_apis! { MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, ParentThen(Parachain(random_para_id).into()).into(), )) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs index 7ff1e1cdb356..ba4d373de3b0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs @@ -678,18 +678,18 @@ impl_runtime_apis! { Some(Parent.into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported between BH and Relay. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, Parent.into(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Reserve transfers are disabled on BH. None } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs index 39238689d458..18269d713c45 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs @@ -678,18 +678,18 @@ impl_runtime_apis! { Some(Parent.into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported between BH and Relay. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, Parent.into(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Reserve transfers are disabled on BH. None } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 77f6d8cdd1ea..4914554227a9 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -867,18 +867,18 @@ impl_runtime_apis! { Some(Parent.into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported between BH and Relay. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, Parent.into(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Reserve transfers are disabled on BH. None } diff --git a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs index 258ecd54f901..3fc2215c7658 100644 --- a/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/collectives/collectives-polkadot/src/lib.rs @@ -943,7 +943,7 @@ impl_runtime_apis! { Some(Parent.into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported between Collectives and Relay. Some(( MultiAsset { @@ -954,7 +954,7 @@ impl_runtime_apis! { )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Reserve transfers are disabled on Collectives. None } diff --git a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs index 4353d209fe21..958ee94b5ac1 100644 --- a/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/contracts/contracts-rococo/src/lib.rs @@ -687,18 +687,18 @@ impl_runtime_apis! { Some(Parent.into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported between Contracts-System-Para and Relay. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Parent.into()) - }.into(), + }, Parent.into(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Reserve transfers are disabled on Contracts-System-Para. None } diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 6171576d30c0..643cde530078 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -2089,24 +2089,24 @@ sp_api::impl_runtime_apis! { Some(crate::xcm_config::AssetHub::get()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported to/from AH. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) - }.into(), + }, crate::xcm_config::AssetHub::get(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay can reserve transfer native token to some random parachain. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) - }.into(), + }, Parachain(43211234).into(), )) } diff --git a/polkadot/runtime/westend/src/lib.rs b/polkadot/runtime/westend/src/lib.rs index 79145855d71a..47454dae0ad6 100644 --- a/polkadot/runtime/westend/src/lib.rs +++ b/polkadot/runtime/westend/src/lib.rs @@ -2171,24 +2171,21 @@ sp_api::impl_runtime_apis! { Some(crate::xcm_config::AssetHub::get()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay/native token can be teleported to/from AH. Some(( - MultiAsset { - fun: Fungible(EXISTENTIAL_DEPOSIT), - id: Concrete(Here.into()) - }.into(), + MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) }, crate::xcm_config::AssetHub::get(), )) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { // Relay can reserve transfer native token to some random parachain. Some(( MultiAsset { fun: Fungible(EXISTENTIAL_DEPOSIT), id: Concrete(Here.into()) - }.into(), + }, crate::Junction::Parachain(43211234).into(), )) } diff --git a/polkadot/xcm/pallet-xcm/src/benchmarking.rs b/polkadot/xcm/pallet-xcm/src/benchmarking.rs index ab2941b10de3..fb3929bfa8e3 100644 --- a/polkadot/xcm/pallet-xcm/src/benchmarking.rs +++ b/polkadot/xcm/pallet-xcm/src/benchmarking.rs @@ -39,23 +39,23 @@ pub trait Config: crate::Config { None } - /// A `(MultiAssets, MultiLocation)` pair representing assets and the destination they can - /// be teleported to. Used only in benchmarks. + /// A `(MultiAsset, MultiLocation)` pair representing asset and the destination it can be + /// teleported to. Used only in benchmarks. /// /// Implementation should also make sure `dest` is reachable/connected. /// /// If `None`, the benchmarks that depend on this will be skipped. - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { None } - /// A `(MultiAssets, MultiLocation)` pair representing assets and the destination they can - /// be reserve-transferred to. Used only in benchmarks. + /// A `(MultiAsset, MultiLocation)` pair representing asset and the destination it can be + /// reserve-transferred to. Used only in benchmarks. /// /// Implementation should also make sure `dest` is reachable/connected. /// /// If `None`, the benchmarks that depend on this will be skipped. - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { None } } @@ -81,20 +81,15 @@ benchmarks! { }: _>(send_origin, Box::new(versioned_dest), Box::new(versioned_msg)) teleport_assets { - let (assets, destination) = T::teleportable_assets_and_dest().ok_or( + let (asset, destination) = T::teleportable_asset_and_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; - // most chains deploying `pallet-xcm` don't have `pallet-assets` so we're - // stuck with using native token and `pallet-balances`. - if assets.len() != 1 { - return Err(BenchmarkError::Stop("Generic benchmark supports only single native asset")) - } - let asset = assets.inner().clone().pop().unwrap(); let transferred_amount = match &asset.fun { Fungible(amount) => *amount, _ => return Err(BenchmarkError::Stop("Benchmark asset not fungible")), }.into(); + let assets: MultiAssets = asset.into(); let existential_deposit = T::ExistentialDeposit::get(); let caller = whitelisted_caller(); @@ -125,20 +120,15 @@ benchmarks! { } reserve_transfer_assets { - let (assets, destination) = T::reserve_transferable_assets_and_dest().ok_or( + let (asset, destination) = T::reserve_transferable_asset_and_dest().ok_or( BenchmarkError::Override(BenchmarkResult::from_weight(Weight::MAX)), )?; - // most chains deploying `pallet-xcm` don't have `pallet-assets` so we're - // stuck with using native token and `pallet-balances`. - if assets.len() != 1 { - return Err(BenchmarkError::Stop("Generic benchmark supports only single native asset")) - } - let asset = assets.inner().clone().pop().unwrap(); let transferred_amount = match &asset.fun { Fungible(amount) => *amount, _ => return Err(BenchmarkError::Stop("Benchmark asset not fungible")), }.into(); + let assets: MultiAssets = asset.into(); let existential_deposit = T::ExistentialDeposit::get(); let caller = whitelisted_caller(); diff --git a/polkadot/xcm/pallet-xcm/src/mock.rs b/polkadot/xcm/pallet-xcm/src/mock.rs index b88734b9abfb..c018ef723fe4 100644 --- a/polkadot/xcm/pallet-xcm/src/mock.rs +++ b/polkadot/xcm/pallet-xcm/src/mock.rs @@ -538,13 +538,13 @@ impl super::benchmarking::Config for Test { Some(Parachain(1000).into()) } - fn teleportable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { - Some((NativeAsset::get().into(), SystemParachainLocation::get())) + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { + Some((NativeAsset::get(), SystemParachainLocation::get())) } - fn reserve_transferable_assets_and_dest() -> Option<(MultiAssets, MultiLocation)> { + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { Some(( - MultiAsset { fun: Fungible(10), id: Concrete(Here.into_location()) }.into(), + MultiAsset { fun: Fungible(10), id: Concrete(Here.into_location()) }, Parachain(OTHER_PARA_ID).into(), )) } From 9f7538dc333ed18472cef0f6742cc354a07d73bf Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 1 Nov 2023 18:51:48 +0200 Subject: [PATCH 105/124] xcm-executor: rename AssetTransferSupport to XcmAssetTransfer --- polkadot/xcm/pallet-xcm/src/lib.rs | 8 ++++---- polkadot/xcm/xcm-executor/src/lib.rs | 4 ++-- polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs | 2 +- polkadot/xcm/xcm-executor/src/traits/mod.rs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/polkadot/xcm/pallet-xcm/src/lib.rs b/polkadot/xcm/pallet-xcm/src/lib.rs index 3af0a48b2440..a89baedb7f4c 100644 --- a/polkadot/xcm/pallet-xcm/src/lib.rs +++ b/polkadot/xcm/pallet-xcm/src/lib.rs @@ -42,7 +42,7 @@ use sp_runtime::{ use sp_std::{boxed::Box, marker::PhantomData, prelude::*, result::Result, vec}; use xcm::{latest::QueryResponseInfo, prelude::*}; use xcm_executor::traits::{ - AssetTransferError, AssetTransferSupport, ConvertOrigin, Properties, TransferType, + AssetTransferError, ConvertOrigin, Properties, TransferType, XcmAssetTransfers, }; use frame_support::{ @@ -208,7 +208,7 @@ pub mod pallet { type XcmExecuteFilter: Contains<(MultiLocation, Xcm<::RuntimeCall>)>; /// Something to execute an XCM message. - type XcmExecutor: ExecuteXcm<::RuntimeCall> + AssetTransferSupport; + type XcmExecutor: ExecuteXcm<::RuntimeCall> + XcmAssetTransfers; /// Our XCM filter which messages to be teleported using the dedicated extrinsic must pass. type XcmTeleportFilter: Contains<(MultiLocation, Vec)>; @@ -1635,13 +1635,13 @@ impl Pallet { // be in error, there would need to be an accounting violation by ourselves, // so it's unlikely, but we don't want to allow that kind of bug to leak into // a trusted chain. - ::AssetTransactor::can_check_out( + ::AssetTransactor::can_check_out( &dest, &fees, &dummy_context, ) .map_err(|_| Error::::CannotCheckOutTeleport)?; - ::AssetTransactor::check_out( + ::AssetTransactor::check_out( &dest, &fees, &dummy_context, diff --git a/polkadot/xcm/xcm-executor/src/lib.rs b/polkadot/xcm/xcm-executor/src/lib.rs index b8e4c53c9889..53a2620a37be 100644 --- a/polkadot/xcm/xcm-executor/src/lib.rs +++ b/polkadot/xcm/xcm-executor/src/lib.rs @@ -38,7 +38,7 @@ use traits::{ mod assets; pub use assets::Assets; mod config; -use crate::traits::AssetTransferSupport; +use crate::traits::XcmAssetTransfers; pub use config::Config; /// A struct to specify how fees are being paid. @@ -255,7 +255,7 @@ impl ExecuteXcm for XcmExecutor AssetTransferSupport for XcmExecutor { +impl XcmAssetTransfers for XcmExecutor { type IsReserve = Config::IsReserve; type IsTeleporter = Config::IsTeleporter; type AssetTransactor = Config::AssetTransactor; diff --git a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs index 980554f2dce2..5fdc9b15e015 100644 --- a/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs +++ b/polkadot/xcm/xcm-executor/src/traits/asset_transfer.rs @@ -44,7 +44,7 @@ pub enum TransferType { /// A trait for identifying asset transfer type based on `IsTeleporter` and `IsReserve` /// configurations. -pub trait AssetTransferSupport { +pub trait XcmAssetTransfers { /// Combinations of (Asset, Location) pairs which we trust as reserves. Meaning /// reserve-based-transfers are to be used for assets matching this filter. type IsReserve: ContainsPair; diff --git a/polkadot/xcm/xcm-executor/src/traits/mod.rs b/polkadot/xcm/xcm-executor/src/traits/mod.rs index 1723da0c3f40..71e75c77e939 100644 --- a/polkadot/xcm/xcm-executor/src/traits/mod.rs +++ b/polkadot/xcm/xcm-executor/src/traits/mod.rs @@ -25,7 +25,7 @@ pub use asset_exchange::AssetExchange; mod asset_lock; pub use asset_lock::{AssetLock, Enact, LockError}; mod asset_transfer; -pub use asset_transfer::{AssetTransferSupport, Error as AssetTransferError, TransferType}; +pub use asset_transfer::{Error as AssetTransferError, TransferType, XcmAssetTransfers}; mod export; pub use export::{export_xcm, validate_export, ExportXcm}; mod fee_manager; From 45279ccce23e3dbf3ee0dd0b04ddf7a1545ce3f2 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Wed, 1 Nov 2023 20:19:12 +0200 Subject: [PATCH 106/124] clippy --- polkadot/xcm/src/v3/multilocation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/xcm/src/v3/multilocation.rs b/polkadot/xcm/src/v3/multilocation.rs index a685c15c7d98..89e259844438 100644 --- a/polkadot/xcm/src/v3/multilocation.rs +++ b/polkadot/xcm/src/v3/multilocation.rs @@ -447,7 +447,7 @@ impl MultiLocation { /// Return the MultiLocation subsection identifying the chain that `self` points to. pub fn chain_location(&self) -> MultiLocation { - let mut clone = self.clone(); + let mut clone = *self; // start popping junctions until we reach chain identifier while let Some(j) = clone.last() { if matches!(j, Junction::Parachain(_) | Junction::GlobalConsensus(_)) { From ebe8bafac6de7e256f6f40c1b9e662d45d4c38d4 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Wed, 1 Nov 2023 21:33:07 +0200 Subject: [PATCH 107/124] fixes --- .../bridge-hub-rococo/src/xcm_config.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 6a074bf237f6..bec3d5b0c39c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -58,8 +58,9 @@ use xcm::latest::prelude::*; use xcm_builder::{ deposit_or_burn_fee, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, HandleFee, - IsConcrete, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, + DescribeFamily, EnsureXcmOrigin, HandleFee, HashedDescription, IsConcrete, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, @@ -490,6 +491,17 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { } } +pub struct AllowSiblingsOnly; +impl Contains for AllowSiblingsOnly { + fn contains(location: &MultiLocation) -> bool { + if let MultiLocation { parents: 1, interior: X1(Parachain(_)) } = location { + true + } else { + false + } + } +} + /// A `HandleFee` implementation that simply deposits the fees for `ExportMessage` XCM instructions /// into the accounts that are used for paying the relayer rewards. /// Burns the fees in case of a failure. From 2dd39ade8b332fff320c31f0dc886a734c6d9c97 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Wed, 1 Nov 2023 21:50:21 +0200 Subject: [PATCH 108/124] remove duplicated trait --- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 3 +-- .../bridge-hubs/bridge-hub-rococo/src/xcm_config.rs | 11 ----------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index ac4c822c0480..a5a9582d1a04 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -99,7 +99,6 @@ use xcm::latest::prelude::*; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; #[cfg(not(feature = "runtime-benchmarks"))] -use crate::xcm_config::AllowSiblingsOnly; use crate::{ bridge_hub_rococo_config::BridgeRefundBridgeHubWococoMessages, bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages, xcm_config::XcmRouter, @@ -620,7 +619,7 @@ impl snowbridge_control::Config for Runtime { type OwnParaId = ParachainInfo; type OutboundQueue = EthereumOutboundQueue; type MessageHasher = BlakeTwo256; - type SiblingOrigin = EnsureXcm; + type SiblingOrigin = EnsureXcm; type AgentIdOf = xcm_config::AgentIdOf; type TreasuryAccount = TreasuryAccount; type Token = Balances; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index bec3d5b0c39c..5571432fc030 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -491,17 +491,6 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { } } -pub struct AllowSiblingsOnly; -impl Contains for AllowSiblingsOnly { - fn contains(location: &MultiLocation) -> bool { - if let MultiLocation { parents: 1, interior: X1(Parachain(_)) } = location { - true - } else { - false - } - } -} - /// A `HandleFee` implementation that simply deposits the fees for `ExportMessage` XCM instructions /// into the accounts that are used for paying the relayer rewards. /// Burns the fees in case of a failure. From 6ba36f8c863bc7492c35b880b428263a6f07c044 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 2 Nov 2023 10:16:39 +0200 Subject: [PATCH 109/124] AssetHub tests: account for Westend higher delivery fees --- .../runtimes/assets/test-utils/src/test_cases_over_bridge.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs index 2cb304d22388..5f2d7942e232 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -129,7 +129,7 @@ pub fn limited_reserve_transfer_assets_for_native_asset_works< // we calculate exact delivery fees _after_ sending the message by weighing the sent // xcm, and this delivery fee varies for different runtimes, so just add enough buffer, // then verify the arithmetics check out on final balance. - let delivery_fees_buffer = 40_000_000_000u128; + let delivery_fees_buffer = 800_000_000_000u128; // drip ED + transfer_amount + delivery_fees_buffer to Alice account let alice_account_init_balance = existential_deposit + balance_to_transfer.into() + delivery_fees_buffer.into(); From 772852778f0b2d5ccbe3b0428dc8dd4ea24ed708 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 2 Nov 2023 10:33:31 +0200 Subject: [PATCH 110/124] fix merge damage --- .../runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs index babd579f0022..62c5bc8271f0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs @@ -111,12 +111,6 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( _ => None, } }), - Box::new(|runtime_event_encoded: Vec| { - match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { - Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), - _ => None, - } - }), bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID ); From a4089c8de3d5d36a7f0c7c8e3f9dc0a8ec779eb7 Mon Sep 17 00:00:00 2001 From: Branislav Kontur Date: Thu, 2 Nov 2023 11:29:49 +0100 Subject: [PATCH 111/124] Added withdraw reserve to scripts --- .../parachains/runtimes/bridge-hubs/README.md | 16 ++++++++++- cumulus/scripts/bridges_rococo_westend.sh | 28 ++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/README.md b/cumulus/parachains/runtimes/bridge-hubs/README.md index 9bd6557f350c..b2a14a0405d2 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/README.md +++ b/cumulus/parachains/runtimes/bridge-hubs/README.md @@ -270,7 +270,7 @@ cd ### Send messages - transfer asset over bridge (ROCs/WNDs) -Do (asset) transfers: +Do reserve-backed transfers: ``` cd @@ -291,6 +291,20 @@ cd - AssetHubWestend (see `foreignAssets.Issued`, `xcmpQueue.Success`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:9010#/explorer - BridgeHubRocococ (see `bridgeWestendMessages.MessagesDelivered`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:8943#/explorer +Do reserve withdraw transfers: (when previous is finished) +``` +cd + +# wrappedWNDs from Rococo's Asset Hub to Westend's. +./cumulus/scripts/bridges_rococo_westend.sh withdraw-reserve-assets-from-asset-hub-rococo-local +``` +``` +cd + +# wrappedROCs from Westend's Asset Hub to Rococo's. +./cumulus/scripts/bridges_rococo_westend.sh withdraw-reserve-assets-from-asset-hub-westend-local +``` + ### Claim relayer's rewards on BridgeHubRococo and BridgeHubWestend **Accounts of BridgeHub parachains:** diff --git a/cumulus/scripts/bridges_rococo_westend.sh b/cumulus/scripts/bridges_rococo_westend.sh index ce8480685aad..82b5f1942b2f 100755 --- a/cumulus/scripts/bridges_rococo_westend.sh +++ b/cumulus/scripts/bridges_rococo_westend.sh @@ -301,9 +301,21 @@ case "$1" in 0 \ "Unlimited" ;; + withdraw-reserve-assets-from-asset-hub-rococo-local) + ensure_polkadot_js_api + # send back only 100000000000 wrappedWNDs to Alice account on AHW + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Westend" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Westend" } } } }, "fun": { "Fungible": 140000000000 } } ] }')" \ + 0 \ + "Unlimited" + ;; reserve-transfer-assets-from-asset-hub-westend-local) ensure_polkadot_js_api - # send WOCs to Alice account on AHR + # send WNDs to Alice account on AHR limited_reserve_transfer_assets \ "ws://127.0.0.1:9010" \ "//Alice" \ @@ -313,6 +325,18 @@ case "$1" in 0 \ "Unlimited" ;; + withdraw-reserve-assets-from-asset-hub-westend-local) + ensure_polkadot_js_api + # send back only 100000000000 wrappedROCs to Alice account on AHR + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9010" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } } }, "fun": { "Fungible": 100000000000 } } ] }')" \ + 0 \ + "Unlimited" + ;; claim-rewards-bridge-hub-rococo-local) ensure_polkadot_js_api # bhwd -> [62, 68, 77, 64] -> 0x62687764 @@ -360,7 +384,9 @@ case "$1" in - init-asset-hub-westend-local - init-bridge-hub-westend-local - reserve-transfer-assets-from-asset-hub-rococo-local + - withdraw-reserve-assets-from-asset-hub-rococo-local - reserve-transfer-assets-from-asset-hub-westend-local + - withdraw-reserve-assets-from-asset-hub-westend-local - claim-rewards-bridge-hub-rococo-local - claim-rewards-bridge-hub-westend-local"; exit 1 From 44e19184f191c19ef4cebcb606edac9fe828a748 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Thu, 2 Nov 2023 13:39:02 +0200 Subject: [PATCH 112/124] bridge-hub-westend-runtime: fix benchmarks --- .../bridge-hubs/bridge-hub-westend/src/lib.rs | 26 ++++++++++++++++++- .../bridge-hub-westend/src/xcm_config.rs | 7 ----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs index 7d4cb03aa06d..5ffe1f37a1a6 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/lib.rs @@ -508,7 +508,7 @@ mod benches { [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] // XCM - [pallet_xcm, PolkadotXcm] + [pallet_xcm, PalletXcmExtrinsiscsBenchmark::] // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] @@ -736,6 +736,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -777,6 +778,29 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsiscsBenchmark; + impl pallet_xcm::benchmarking::Config for Runtime { + fn reachable_dest() -> Option { + Some(Parent.into()) + } + + fn teleportable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { + // Relay/native token can be teleported between BH and Relay. + Some(( + MultiAsset { + fun: Fungible(EXISTENTIAL_DEPOSIT), + id: Concrete(Parent.into()) + }, + Parent.into(), + )) + } + + fn reserve_transferable_asset_and_dest() -> Option<(MultiAsset, MultiLocation)> { + // Reserve transfers are disabled on BH. + None + } + } + use xcm::latest::prelude::*; use xcm_config::WestendLocation; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs index 8efc75ed13eb..393767a17efd 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs @@ -284,11 +284,6 @@ pub type XcmRouter = WithUniqueTopic<( XcmpQueue, )>; -#[cfg(feature = "runtime-benchmarks")] -parameter_types! { - pub ReachableDest: Option = Some(Parent.into()); -} - impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type XcmRouter = XcmRouter; @@ -316,8 +311,6 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = crate::weights::pallet_xcm::WeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; type AdminOrigin = EnsureRoot; type MaxRemoteLockConsumers = ConstU32<0>; type RemoteLockConsumerIdentifier = (); From 528f646fc68373710d679f07cbda68c92f6e175a Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Thu, 2 Nov 2023 13:50:19 +0200 Subject: [PATCH 113/124] unknown import --- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index d40ed9de2419..b2a19c5658a0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -101,7 +101,7 @@ use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; use crate::{ bridge_hub_rococo_config::BridgeRefundBridgeHubWococoMessages, bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages, - xcm_config::{AllowSiblingsOnly, XcmRouter}, + xcm_config::XcmRouter, }; use parachains_common::{ impls::DealWithFees, From 8c9dc763308bc27613ca8d9c770c86128eb9e35b Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Thu, 2 Nov 2023 17:44:42 +0200 Subject: [PATCH 114/124] move AllowSiblingsOnly to core --- .../runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index b2a19c5658a0..dff547e72698 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -39,7 +39,7 @@ pub mod xcm_config; use codec::{Decode, Encode}; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use snowbridge_beacon_primitives::{Fork, ForkVersions}; -use snowbridge_core::{outbound::Message, AgentId}; +use snowbridge_core::{outbound::Message, AgentId, AllowSiblingsOnly}; use snowbridge_router_primitives::inbound::MessageToXcm; use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H160}; @@ -620,7 +620,7 @@ impl snowbridge_control::Config for Runtime { type OwnParaId = ParachainInfo; type OutboundQueue = EthereumOutboundQueue; type MessageHasher = BlakeTwo256; - type SiblingOrigin = EnsureXcm; + type SiblingOrigin = EnsureXcm; type AgentIdOf = xcm_config::AgentIdOf; type TreasuryAccount = TreasuryAccount; type Token = Balances; From 55305d2e6ad48b84bbec74f8dcd77665d5237857 Mon Sep 17 00:00:00 2001 From: Clara van Staden Date: Thu, 2 Nov 2023 20:00:15 +0200 Subject: [PATCH 115/124] Adds transfer token user fee (#7) * adds transfer token user fee * updates fee calc * starts with adding snowbridge conf * updates fee * correct ROC amount * correct ROC amount --------- Co-authored-by: claravanstaden --- cumulus/parachains/common/src/lib.rs | 1 + cumulus/parachains/common/src/snowbridge_config.rs | 6 ++++++ .../runtimes/assets/asset-hub-rococo/src/xcm_config.rs | 5 +++-- .../bridge-hubs/bridge-hub-rococo/src/xcm_config.rs | 4 ++-- 4 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 cumulus/parachains/common/src/snowbridge_config.rs diff --git a/cumulus/parachains/common/src/lib.rs b/cumulus/parachains/common/src/lib.rs index 4ebc2cc6e1e2..caea757e0d60 100644 --- a/cumulus/parachains/common/src/lib.rs +++ b/cumulus/parachains/common/src/lib.rs @@ -19,6 +19,7 @@ pub mod impls; pub mod kusama; pub mod polkadot; pub mod rococo; +pub mod snowbridge_config; pub mod westend; pub mod wococo; pub mod xcm_config; diff --git a/cumulus/parachains/common/src/snowbridge_config.rs b/cumulus/parachains/common/src/snowbridge_config.rs new file mode 100644 index 000000000000..8edc52c1b014 --- /dev/null +++ b/cumulus/parachains/common/src/snowbridge_config.rs @@ -0,0 +1,6 @@ +frame_support::parameter_types! { + /// User fee for ERC20 token transfer back to Ethereum. + /// (initially was calculated by test `OutboundQueue::calculate_fees` - ETH/ROC 1/400 and fee_per_gas 15 GWEI = 22698000000 + *25%) + /// Needs to be more than fee calculated from DefaultFeeConfig FeeConfigRecord in snowbridge:parachain/pallets/outbound-queue/src/lib.rs + pub const BridgeHubEthereumBaseFeeInRocs: u128 = 28372500000; +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index c6ea9f3fdd5d..c96d9e2df8e3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -32,6 +32,7 @@ use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; use parachains_common::{ impls::ToStakingPot, + snowbridge_config::BridgeHubEthereumBaseFeeInRocs, xcm_config::{ AssetFeeAsExistentialDepositMultiplier, ConcreteAssetFromSystem, RelayOrOtherSystemParachains, @@ -910,8 +911,8 @@ pub mod bridging { SiblingBridgeHub::get(), Some(( XcmBridgeHubRouterFeeAssetId::get(), - bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get(), - ).into()) // TODO calculate fee factor + BridgeHubEthereumBaseFeeInRocs::get(), + ).into()) ), ]; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 5571432fc030..4ff63f9b0cfe 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -237,9 +237,9 @@ impl Contains for SafeCallFilter { snowbridge_ethereum_beacon_client::Call::force_checkpoint { .. } | snowbridge_ethereum_beacon_client::Call::set_operating_mode { .. }, ) | RuntimeCall::EthereumInboundQueue( - snowbridge_inbound_queue::Call::set_operating_mode { .. }, + snowbridge_inbound_queue::Call::set_operating_mode { .. }, ) | RuntimeCall::EthereumOutboundQueue( - snowbridge_outbound_queue::Call::set_operating_mode { .. }, + snowbridge_outbound_queue::Call::set_operating_mode { .. }, ) | RuntimeCall::EthereumControl(..) ) } From 989fb0f1ce4c9ab8359dd9f70f90a03d3eefa245 Mon Sep 17 00:00:00 2001 From: Ron Date: Fri, 3 Nov 2023 15:45:06 +0800 Subject: [PATCH 116/124] Improve xcm integration test (#13) * Fix tests * Improve integration tests --- Cargo.lock | 6 ++ .../bridges/bridge-hub-rococo/Cargo.toml | 35 +++--- .../bridge-hub-rococo/src/tests/snowbridge.rs | 101 ++++++++++++++++-- .../emulated/common/src/lib.rs | 1 + 4 files changed, 120 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 576e3836c943..ce3793856e3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2022,7 +2022,10 @@ dependencies = [ "cumulus-pallet-dmp-queue", "cumulus-pallet-xcmp-queue", "frame-support", + "hex", + "hex-literal", "integration-tests-common", + "pallet-assets", "pallet-bridge-messages", "pallet-xcm", "parachains-common", @@ -2031,6 +2034,9 @@ dependencies = [ "polkadot-parachain-primitives", "polkadot-runtime-parachains", "snowbridge-control", + "snowbridge-core", + "snowbridge-inbound-queue", + "snowbridge-router-primitives", "staging-xcm", "staging-xcm-executor", "xcm-emulator", diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml index 29499034fba5..90eb7738876a 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml @@ -7,32 +7,41 @@ license = "Apache-2.0" description = "Bridge Hub Rococo runtime integration tests with xcm-emulator" publish = false +[lib] +doctest = false + [dependencies] codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } +hex = "0.4.3" +hex-literal = "0.4.1" # Substrate -frame-support = { path = "../../../../../../substrate/frame/support", default-features = false} +frame-support = { path = "../../../../../../substrate/frame/support", default-features = false } +pallet-assets = { path = "../../../../../../substrate/frame/assets", default-features = false } # Polkadot -polkadot-core-primitives = { path = "../../../../../../polkadot/core-primitives", default-features = false} -polkadot-parachain-primitives = { path = "../../../../../../polkadot/parachain", default-features = false} +polkadot-core-primitives = { path = "../../../../../../polkadot/core-primitives", default-features = false } +polkadot-parachain-primitives = { path = "../../../../../../polkadot/parachain", default-features = false } polkadot-runtime-parachains = { path = "../../../../../../polkadot/runtime/parachains" } -xcm = { package = "staging-xcm", path = "../../../../../../polkadot/xcm", default-features = false} -pallet-xcm = { path = "../../../../../../polkadot/xcm/pallet-xcm", default-features = false} -xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../polkadot/xcm/xcm-executor", default-features = false} +xcm = { package = "staging-xcm", path = "../../../../../../polkadot/xcm", default-features = false } +pallet-xcm = { path = "../../../../../../polkadot/xcm/pallet-xcm", default-features = false } +xcm-executor = { package = "staging-xcm-executor", path = "../../../../../../polkadot/xcm/xcm-executor", default-features = false } # Cumulus asset-test-utils = { path = "../../../../../parachains/runtimes/assets/test-utils", default-features = false } parachains-common = { path = "../../../../common" } -cumulus-pallet-xcmp-queue = { path = "../../../../../pallets/xcmp-queue", default-features = false} -cumulus-pallet-dmp-queue = { path = "../../../../../pallets/dmp-queue", default-features = false} -pallet-bridge-messages = { path = "../../../../../../bridges/modules/messages", default-features = false} -bp-messages = { path = "../../../../../../bridges/primitives/messages", default-features = false} +cumulus-pallet-xcmp-queue = { path = "../../../../../pallets/xcmp-queue", default-features = false } +cumulus-pallet-dmp-queue = { path = "../../../../../pallets/dmp-queue", default-features = false } +pallet-bridge-messages = { path = "../../../../../../bridges/modules/messages", default-features = false } +bp-messages = { path = "../../../../../../bridges/primitives/messages", default-features = false } bridge-hub-rococo-runtime = { path = "../../../../../parachains/runtimes/bridge-hubs/bridge-hub-rococo", default-features = false } # Local -xcm-emulator = { path = "../../../../../xcm/xcm-emulator", default-features = false} -integration-tests-common = { path = "../../common", default-features = false} +xcm-emulator = { path = "../../../../../xcm/xcm-emulator", default-features = false } +integration-tests-common = { path = "../../common", default-features = false } # Snowbridge -snowbridge-control = { path = "../../../../../../../parachain/pallets/control" } +snowbridge-core = { path = "../../../../../../../parachain/primitives/core", default-features = false } +snowbridge-router-primitives = { path = "../../../../../../../parachain/primitives/router", default-features = false } +snowbridge-control = { path = "../../../../../../../parachain/pallets/control", default-features = false } +snowbridge-inbound-queue = { path = "../../../../../../../parachain/pallets/inbound-queue", default-features = false } diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs index fa494fbac3c6..35f9c7e06de9 100644 --- a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/snowbridge.rs @@ -14,16 +14,26 @@ // limitations under the License. use crate::*; +use hex_literal::hex; use integration_tests_common::BridgeHubRococoPallet; use snowbridge_control; +use snowbridge_router_primitives::inbound::{Command, MessageV1, VersionedMessage}; #[test] fn create_agent() { + BridgeHubRococo::fund_accounts(vec![( + BridgeHubRococo::sovereign_account_id_of(MultiLocation { + parents: 1, + interior: X1(Parachain(1000)), + }), + 5_000_000 * ROCOCO_ED, + )]); + let sudo_origin = ::RuntimeOrigin::root(); let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into(); let remote_xcm = VersionedXcm::from(Xcm(vec![ - UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, DescendOrigin(X1(Parachain(1000))), Transact { require_weight_at_most: 3000000000.into(), @@ -71,30 +81,50 @@ fn create_agent() { #[test] fn create_channel() { + let source_location = MultiLocation { parents: 1, interior: X1(Parachain(1000)) }; + + BridgeHubRococo::fund_accounts(vec![( + BridgeHubRococo::sovereign_account_id_of(source_location), + 5_000_000 * ROCOCO_ED, + )]); + let sudo_origin = ::RuntimeOrigin::root(); - let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into(); + let destination: VersionedMultiLocation = + Rococo::child_location_of(BridgeHubRococo::para_id()).into(); - let remote_xcm = VersionedXcm::from(Xcm(vec![ - UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, + let create_agent_xcm = VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, DescendOrigin(X1(Parachain(1000))), Transact { - require_weight_at_most: 8000000000.into(), + require_weight_at_most: 3000000000.into(), origin_kind: OriginKind::Xcm, - call: vec![51, 2].into(), + call: vec![51, 1].into(), }, ])); - //BridgeHubRococo::execute_with(|| { // TODO Create agent in storage - // ::EthereumControl::create_agent(sudo_origin); - //}); + let create_channel_xcm = VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + DescendOrigin(X1(Parachain(1000))), + Transact { + require_weight_at_most: 3000000000.into(), + origin_kind: OriginKind::Xcm, + call: vec![51, 2].into(), + }, + ])); //Rococo Global Consensus // Send XCM message from Relay Chain to Bridge Hub source Parachain Rococo::execute_with(|| { + assert_ok!(::XcmPallet::send( + sudo_origin.clone(), + bx!(destination.clone()), + bx!(create_agent_xcm), + )); + assert_ok!(::XcmPallet::send( sudo_origin, bx!(destination), - bx!(remote_xcm), + bx!(create_channel_xcm), )); type RuntimeEvent = ::RuntimeEvent; @@ -124,3 +154,54 @@ fn create_channel() { ); }); } + +#[test] +fn register_token() { + BridgeHubRococo::fund_accounts(vec![( + BridgeHubRococo::sovereign_account_id_of(MultiLocation { + parents: 1, + interior: X1(Parachain(1000)), + }), + 5_000_000 * ROCOCO_ED, + )]); + + // Fund gateway sovereign in asset hub + AssetHubRococo::fund_accounts(vec![( + hex!("c9794dd8013efb2ad83f668845c62b373c16ad33971745731408058e4d0c6ff5").into(), + 5_000_000_000_000 * ROCOCO_ED, + )]); + + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + type EthereumInboundQueue = + ::EthereumInboundQueue; + let message = VersionedMessage::V1(MessageV1 { + chain_id: 15, + command: Command::RegisterToken { + gateway: hex!("EDa338E4dC46038493b885327842fD3E301CaB39").into(), + token: hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d").into(), + }, + }); + let xcm = EthereumInboundQueue::do_convert(message).unwrap(); + let _ = EthereumInboundQueue::send_xcm(xcm, 1000.into()).unwrap(); + + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {}, + ] + ); + }); + + AssetHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + AssetHubRococo, + vec![ + RuntimeEvent::ForeignAssets(pallet_assets::Event::Created { .. }) => {}, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + ] + ); + }); +} diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index 3317ba2950e5..c87e406247be 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -151,6 +151,7 @@ decl_test_parachains! { PolkadotXcm: bridge_hub_rococo_runtime::PolkadotXcm, Balances: bridge_hub_rococo_runtime::Balances, EthereumControl: bridge_hub_rococo_runtime::EthereumControl, + EthereumInboundQueue: bridge_hub_rococo_runtime::EthereumInboundQueue, } }, // AssetHubRococo From 1341a73eb44018a9ba67abcf79ec9f0e3e2b87a7 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Wed, 1 Nov 2023 22:45:14 +0200 Subject: [PATCH 117/124] remove gateway contract location --- .../assets/asset-hub-rococo/src/lib.rs | 4 ++-- .../assets/asset-hub-rococo/src/xcm_config.rs | 20 +++++-------------- .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 4 ++-- .../bridge-hub-rococo/src/xcm_config.rs | 12 +---------- 4 files changed, 10 insertions(+), 30 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 895c4794675d..a273ea375867 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -97,7 +97,7 @@ use xcm::latest::prelude::*; use xcm_executor::XcmExecutor; use crate::xcm_config::{ - bridging::to_rococo::EthereumGatewayLocation, ForeignCreatorsSovereignAccountOf, + bridging::to_rococo::EthereumLocation, ForeignCreatorsSovereignAccountOf, LocalAndForeignAssetsMultiLocationMatcher, TrustBackedAssetsPalletLocation, }; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; @@ -391,7 +391,7 @@ impl pallet_assets::Config for Runtime { ( FromSiblingParachain>, snowbridge_router_primitives::inbound::FromEthereumGlobalConsensus< - EthereumGatewayLocation, + EthereumLocation, >, ), ForeignCreatorsSovereignAccountOf, diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index c96d9e2df8e3..d144467ca9e7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -42,7 +42,7 @@ use parachains_common::{ use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::ExponentialPrice; use rococo_runtime_constants::system_parachain::SystemParachains; -use snowbridge_router_primitives::inbound::GlobalConsensusEthereumAccountConvertsFor; +use snowbridge_router_primitives::inbound::GlobalConsensusEthereumConvertsFor; use sp_runtime::traits::{AccountIdConversion, ConvertInto}; use xcm::latest::prelude::*; use xcm_builder::{ @@ -114,7 +114,7 @@ pub type LocationToAccountId = ( GlobalConsensusParachainConvertsFor, // Ethereum contract sovereign account. // (Used to get convert ethereum contract locations to sovereign account) - GlobalConsensusEthereumAccountConvertsFor, + GlobalConsensusEthereumConvertsFor, ); /// Means for transacting the native currency on this chain. @@ -700,7 +700,7 @@ pub type ForeignCreatorsSovereignAccountOf = ( SiblingParachainConvertsVia, AccountId32Aliases, ParentIsPreset, - GlobalConsensusEthereumAccountConvertsFor, + GlobalConsensusEthereumConvertsFor, ); /// Simple conversion of `u32` into an `AssetId` for use in benchmarking. @@ -873,17 +873,7 @@ pub mod bridging { pub AssetHubRococo: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(RococoNetwork::get()), Parachain(bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID))); pub RocLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(RococoNetwork::get()))); pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; - pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); // TODO: Maybe registry address belongs here - - pub const EthereumGatewayAddress: [u8; 20] = hex_literal::hex!("EDa338E4dC46038493b885327842fD3E301CaB39"); - // The Registry contract for the bridge which is also the origin for reserves and the prefix of all assets. - pub EthereumGatewayLocation: MultiLocation = EthereumLocation::get() - .pushed_with_interior( - AccountKey20 { - network: None, - key: EthereumGatewayAddress::get(), - } - ).unwrap(); + pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); pub RocFromAssetHubRococo: (MultiAssetFilter, MultiLocation) = ( Wild(AllOf { fun: WildFungible, id: Concrete(RocLocation::get()) }), @@ -924,7 +914,7 @@ pub mod bridging { ]; pub AllowedReserveTransferAssetsToEthereum: sp_std::vec::Vec = sp_std::vec![ - Wild(AllOf { fun: WildFungible, id: Concrete(EthereumGatewayLocation::get()) }), + Wild(AllOf { fun: WildFungible, id: Concrete(EthereumLocation::get()) }), ]; /// Universal aliases diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index dff547e72698..b2bd5bf5731b 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -86,7 +86,7 @@ use pallet_xcm::EnsureXcm; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; pub use sp_runtime::{MultiAddress, Perbill, Permill}; use xcm::VersionedMultiLocation; -use xcm_config::{EthereumGatewayAddress, XcmConfig, XcmOriginToTransactDispatchOrigin}; +use xcm_config::{XcmConfig, XcmOriginToTransactDispatchOrigin}; use bp_runtime::HeaderId; @@ -500,7 +500,7 @@ impl pallet_message_queue::Config for Runtime { parameter_types! { pub const Reward: u128 = 10; - pub const GatewayAddress: H160 = H160(EthereumGatewayAddress::get()); + pub const GatewayAddress: H160 = H160(hex_literal::hex!("EDa338E4dC46038493b885327842fD3E301CaB39")); pub const CreateAssetCall: [u8;2] = [53, 0]; pub const CreateAssetExecutionFee: u128 = 2_000_000_000; pub const SendTokenExecutionFee: u128 = 1_000_000_000; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 4ff63f9b0cfe..f95ddc3b7e81 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -85,16 +85,6 @@ parameter_types! { // Network and location for the local Ethereum testnet. pub const EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); - - pub const EthereumGatewayAddress: [u8; 20] = hex_literal::hex!("EDa338E4dC46038493b885327842fD3E301CaB39"); - // The Registry contract for the bridge which is also the origin for reserves and the prefix of all assets. - pub EthereumGatewayLocation: MultiLocation = EthereumLocation::get() - .pushed_with_interior( - AccountKey20 { - network: None, - key: EthereumGatewayAddress::get(), - } - ).unwrap(); } /// Adapter for resolving `NetworkId` based on `pub storage Flavor: RuntimeFlavor`. @@ -428,7 +418,7 @@ pub type AgentIdOf = HashedDescription pub type SnowbridgeExporter = EthereumBlobExporter< UniversalLocation, - EthereumGatewayLocation, + EthereumLocation, snowbridge_outbound_queue::Pallet, AgentIdOf, >; From f79073bdc08439b5871de883c1b90b746ebcef4a Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Wed, 1 Nov 2023 22:50:44 +0200 Subject: [PATCH 118/124] fmt --- .../runtimes/assets/asset-hub-rococo/src/lib.rs | 4 +--- .../bridge-hubs/bridge-hub-rococo/src/xcm_config.rs | 11 +++++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index a273ea375867..c35d3a1df2a9 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -390,9 +390,7 @@ impl pallet_assets::Config for Runtime { type CreateOrigin = ForeignCreators< ( FromSiblingParachain>, - snowbridge_router_primitives::inbound::FromEthereumGlobalConsensus< - EthereumLocation, - >, + snowbridge_router_primitives::inbound::FromEthereumGlobalConsensus, ), ForeignCreatorsSovereignAccountOf, AccountId, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index f95ddc3b7e81..da389b8bd1f1 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -59,12 +59,11 @@ use xcm_builder::{ deposit_or_burn_fee, AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, - DescribeFamily, EnsureXcmOrigin, HandleFee, HashedDescription, IsConcrete, - ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, - XcmFeeToAccount, + DescribeFamily, EnsureXcmOrigin, HandleFee, HashedDescription, IsConcrete, ParentAsSuperuser, + ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, + XcmFeeManagerFromComponents, XcmFeeToAccount, }; use xcm_executor::{ traits::{ExportXcm, FeeReason, TransactAsset, WithOriginFilter}, From dba7cff62bc81e0e07a3bab47951edb35776a172 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Thu, 2 Nov 2023 14:07:50 +0200 Subject: [PATCH 119/124] remove todos --- .../runtimes/assets/asset-hub-rococo/src/xcm_config.rs | 8 +++----- cumulus/parachains/runtimes/assets/common/src/matching.rs | 8 ++++++-- .../bridge-hubs/bridge-hub-rococo/src/xcm_config.rs | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index d144467ca9e7..d7fd4040805b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -897,7 +897,9 @@ pub mod bridging { ), NetworkExportTableItem::new( EthereumNetwork::get(), - None, // TODO add Ethereum network / gateway contract + Some(sp_std::vec![ + EthereumLocation::get().interior, + ]), SiblingBridgeHub::get(), Some(( XcmBridgeHubRouterFeeAssetId::get(), @@ -913,10 +915,6 @@ pub mod bridging { // and nothing else ]; - pub AllowedReserveTransferAssetsToEthereum: sp_std::vec::Vec = sp_std::vec![ - Wild(AllOf { fun: WildFungible, id: Concrete(EthereumLocation::get()) }), - ]; - /// Universal aliases pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( sp_std::vec![ diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index 6b0d8b0967e1..2f61a2824b09 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -63,8 +63,12 @@ pub struct FromNetwork(sp_std::marker::PhantomData impl> ContainsPair for FromNetwork { - fn contains(&a: &MultiLocation, _b: &MultiLocation) -> bool { - // TODO: check that a.starts_with(b) + fn contains(&a: &MultiLocation, b: &MultiLocation) -> bool { + // `a` needs to be from `b` at least + if !a.starts_with(b) { + return false + } + match a { MultiLocation { parents: 2, interior } => { matches!(interior.first(), Some(GlobalConsensus(network)) if *network == SelfNetworkId::get()) diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index da389b8bd1f1..c009891833a0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -461,7 +461,7 @@ impl ExportXcm for BridgeHubRococoOrBridgeHubWococoSwitchExporter { destination, message, ) - .map(|result| ((Ethereum { chain_id: 15 }, result.0), result.1)) // TODO get network ID + .map(|result| ((location, result.0), result.1)) }, _ => unimplemented!("Unsupported network: {:?}", network), } From 0ee181e76f58625815d7be9b6993936cbcc4c266 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Fri, 3 Nov 2023 02:53:06 +0200 Subject: [PATCH 120/124] use the correct bridge config --- .../assets/asset-hub-rococo/src/lib.rs | 2 +- .../assets/asset-hub-rococo/src/xcm_config.rs | 43 +++++++++---------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index c35d3a1df2a9..4737fc165f17 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -97,7 +97,7 @@ use xcm::latest::prelude::*; use xcm_executor::XcmExecutor; use crate::xcm_config::{ - bridging::to_rococo::EthereumLocation, ForeignCreatorsSovereignAccountOf, + bridging::to_wococo::EthereumLocation, ForeignCreatorsSovereignAccountOf, LocalAndForeignAssetsMultiLocationMatcher, TrustBackedAssetsPalletLocation, }; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index d7fd4040805b..bc9f17b79e18 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -22,7 +22,7 @@ use super::{ }; use assets_common::{ local_and_foreign_assets::MatchesLocalAndForeignAssetsMultiLocation, - matching::{FromSiblingParachain, IsForeignConcreteAsset}, + matching::{FromNetwork, FromSiblingParachain, IsForeignConcreteAsset}, }; use frame_support::{ match_types, parameter_types, @@ -563,8 +563,8 @@ impl xcm_executor::Config for XcmConfig { // Users must use teleport where allowed (e.g. ROC with the Relay Chain). type IsReserve = ( bridging::to_wococo::IsTrustedBridgedReserveLocationForConcreteAsset, + bridging::to_wococo::IsTrustedBridgedReserveLocationForForeignAsset, bridging::to_rococo::IsTrustedBridgedReserveLocationForConcreteAsset, - bridging::to_rococo::IsTrustedBridgedReserveLocationForForeignAsset, ); type IsTeleporter = TrustedTeleporters; type UniversalLocation = UniversalLocation; @@ -782,6 +782,8 @@ pub mod bridging { pub const WococoNetwork: NetworkId = NetworkId::Wococo; pub AssetHubWococo: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(WococoNetwork::get()), Parachain(bp_asset_hub_wococo::ASSET_HUB_WOCOCO_PARACHAIN_ID))); pub WocLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(WococoNetwork::get()))); + pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; + pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); pub WocFromAssetHubWococo: (MultiAssetFilter, MultiLocation) = ( Wild(AllOf { fun: WildFungible, id: Concrete(WocLocation::get()) }), @@ -802,7 +804,18 @@ pub mod bridging { XcmBridgeHubRouterFeeAssetId::get(), bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get(), ).into()) - ) + ), + NetworkExportTableItem::new( + EthereumNetwork::get(), + Some(sp_std::vec![ + EthereumLocation::get().interior.split_global().expect("invalid configuration for Ethereum").1, + ]), + SiblingBridgeHub::get(), + Some(( + XcmBridgeHubRouterFeeAssetId::get(), + BridgeHubEthereumBaseFeeInRocs::get(), + ).into()) + ), ]; /// Allowed assets for reserve transfer to `AssetHubWococo`. @@ -815,11 +828,15 @@ pub mod bridging { /// Universal aliases pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( sp_std::vec![ - (SiblingBridgeHubWithBridgeHubWococoInstance::get(), GlobalConsensus(WococoNetwork::get())) + (SiblingBridgeHubWithBridgeHubWococoInstance::get(), GlobalConsensus(WococoNetwork::get())), + (SiblingBridgeHub::get(), GlobalConsensus(EthereumNetwork::get())), ] ); } + pub type IsTrustedBridgedReserveLocationForForeignAsset = + matching::IsForeignConcreteAsset>; + impl Contains<(MultiLocation, Junction)> for UniversalAliases { fn contains(alias: &(MultiLocation, Junction)) -> bool { UniversalAliases::get().contains(alias) @@ -858,7 +875,6 @@ pub mod bridging { pub mod to_rococo { use super::*; - use assets_common::matching::FromNetwork; parameter_types! { pub SiblingBridgeHubWithBridgeHubRococoInstance: MultiLocation = MultiLocation::new( @@ -872,8 +888,6 @@ pub mod bridging { pub const RococoNetwork: NetworkId = NetworkId::Rococo; pub AssetHubRococo: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(RococoNetwork::get()), Parachain(bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID))); pub RocLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(RococoNetwork::get()))); - pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; - pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); pub RocFromAssetHubRococo: (MultiAssetFilter, MultiLocation) = ( Wild(AllOf { fun: WildFungible, id: Concrete(RocLocation::get()) }), @@ -895,17 +909,6 @@ pub mod bridging { bp_asset_hub_wococo::BridgeHubWococoBaseFeeInWocs::get(), ).into()) ), - NetworkExportTableItem::new( - EthereumNetwork::get(), - Some(sp_std::vec![ - EthereumLocation::get().interior, - ]), - SiblingBridgeHub::get(), - Some(( - XcmBridgeHubRouterFeeAssetId::get(), - BridgeHubEthereumBaseFeeInRocs::get(), - ).into()) - ), ]; /// Allowed assets for reserve transfer to `AssetHubWococo`. @@ -919,7 +922,6 @@ pub mod bridging { pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( sp_std::vec![ (SiblingBridgeHubWithBridgeHubRococoInstance::get(), GlobalConsensus(RococoNetwork::get())), - (SiblingBridgeHub::get(), GlobalConsensus(EthereumNetwork::get())), ] ); } @@ -942,9 +944,6 @@ pub mod bridging { ), >; - pub type IsTrustedBridgedReserveLocationForForeignAsset = - matching::IsForeignConcreteAsset>; - /// Allows to reserve transfer assets to `AssetHubRococo`. pub type AllowedReserveTransferAssets = LocationWithAssetFilters< Equals, From a59ccf3abdbfd1ca1aa2f091d0e47476bdbb1125 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 3 Nov 2023 11:14:09 +0200 Subject: [PATCH 121/124] xcm-emulator: add ah to penpal multiple mixed assets transfer test --- .../assets/asset-hub-rococo/src/lib.rs | 3 +- .../src/tests/reserve_transfer.rs | 114 +++++++++++++++--- .../asset-hub-rococo/src/tests/teleport.rs | 8 +- .../emulated/common/src/impls.rs | 12 +- .../emulated/common/src/lib.rs | 13 +- .../runtimes/testing/penpal/src/lib.rs | 11 +- .../runtimes/testing/penpal/src/xcm_config.rs | 21 ++-- polkadot/xcm/src/v3/multiasset.rs | 4 +- 8 files changed, 137 insertions(+), 49 deletions(-) diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs index 6da7537e82f4..a46a2efcead1 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/lib.rs @@ -78,6 +78,7 @@ pub fn para_test_args( amount: Balance, assets: MultiAssets, asset_id: Option, + fee_asset_item: u32, ) -> TestArgs { TestArgs { dest, @@ -85,7 +86,7 @@ pub fn para_test_args( amount, assets, asset_id, - fee_asset_item: 0, + fee_asset_item, weight_limit: WeightLimit::Unlimited, } } diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index 98e2ba18df17..38abc3dea740 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -135,7 +135,7 @@ fn para_to_system_para_receiver_assertions(t: ParaToSystemParaTest) { ); } -fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { +fn system_para_to_para_assets_sender_assertions(t: SystemParaToParaTest) { type RuntimeEvent = ::RuntimeEvent; AssetHubRococo::assert_xcm_pallet_attempted_complete(Some(Weight::from_parts( @@ -161,6 +161,18 @@ fn system_para_to_para_assets_assertions(t: SystemParaToParaTest) { ); } +fn system_para_to_para_assets_receiver_assertions(_: Test) { + type RuntimeEvent = ::RuntimeEvent; + assert_expected_events!( + PenpalRococoA, + vec![ + RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, + RuntimeEvent::Assets(pallet_assets::Event::Issued { .. }) => {}, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + ] + ); +} + fn relay_to_para_limited_reserve_transfer_assets(t: RelayToParaTest) -> DispatchResult { ::XcmPallet::limited_reserve_transfer_assets( t.signed_origin, @@ -315,7 +327,7 @@ fn limited_reserve_transfer_native_asset_from_system_para_to_para() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: PenpalRococoAReceiver::get(), - args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0), }; let mut test = SystemParaToParaTest::new(test_args); @@ -355,7 +367,7 @@ fn limited_reserve_transfer_native_asset_from_para_to_system_para() { let test_args = TestContext { sender: PenpalRococoASender::get(), receiver: AssetHubRococoReceiver::get(), - args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0), }; let mut test = ParaToSystemParaTest::new(test_args); @@ -363,7 +375,6 @@ fn limited_reserve_transfer_native_asset_from_para_to_system_para() { let sender_balance_before = test.sender.balance; let receiver_balance_before = test.receiver.balance; - // MultiLocation { parents: 1, interior: X1(Parachain(PenpalRococoA::para_id().into())) }; let penpal_location_as_seen_by_ahr = AssetHubRococo::sibling_location_of(PenpalRococoA::para_id()); let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location_as_seen_by_ahr); @@ -391,38 +402,101 @@ fn limited_reserve_transfer_native_asset_from_para_to_system_para() { assert!(receiver_balance_after > receiver_balance_before); } -/// Limited Reserve Transfers of a local asset from System Parachain to Parachain should work +/// Limited Reserve Transfers of a local asset and native asset from System Parachain to Parachain +/// should work #[test] -fn limited_reserve_transfer_asset_from_system_para_to_para() { - // Force create asset from Relay Chain and mint assets for System Parachain's sender account +fn limited_reserve_transfer_assets_from_system_para_to_para() { + // Force create asset on AssetHubRococo and PenpalRococoA from Relay Chain AssetHubRococo::force_create_and_mint_asset( ASSET_ID, ASSET_MIN_BALANCE, - true, + false, AssetHubRococoSender::get(), Some(Weight::from_parts(1_019_445_000, 200_000)), - ASSET_MIN_BALANCE * 1000000, + ASSET_MIN_BALANCE * 1_000_000, + ); + PenpalRococoA::force_create_and_mint_asset( + ASSET_ID, + ASSET_MIN_BALANCE, + false, + PenpalRococoASender::get(), + Some(Weight::from_parts(1_019_445_000, 200_000)), + 0, ); // Init values for System Parachain let destination = AssetHubRococo::sibling_location_of(PenpalRococoA::para_id()); let beneficiary_id = PenpalRococoAReceiver::get(); - let amount_to_send = ASSET_MIN_BALANCE * 1000; - let assets = - (X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), amount_to_send) - .into(); + let fee_amount_to_send = ASSET_HUB_ROCOCO_ED * 1000; + let asset_amount_to_send = ASSET_MIN_BALANCE * 1000; + let assets: MultiAssets = vec![ + (Parent, fee_amount_to_send).into(), + (X2(PalletInstance(ASSETS_PALLET_ID), GeneralIndex(ASSET_ID.into())), asset_amount_to_send) + .into(), + ] + .into(); + let fee_asset_index = assets + .inner() + .iter() + .position(|r| r == &(Parent, fee_amount_to_send).into()) + .unwrap() as u32; let para_test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: PenpalRococoAReceiver::get(), - args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args( + destination, + beneficiary_id, + asset_amount_to_send, + assets, + None, + fee_asset_index, + ), }; - let mut system_para_test = SystemParaToParaTest::new(para_test_args); + let mut test = SystemParaToParaTest::new(para_test_args); + + // Create SA-of-Penpal-on-AHR with ED. + let penpal_location = AssetHubRococo::sibling_location_of(PenpalRococoA::para_id()); + let sov_penpal_on_ahr = AssetHubRococo::sovereign_account_id_of(penpal_location); + AssetHubRococo::fund_accounts(vec![(sov_penpal_on_ahr.into(), ROCOCO_ED)]); + + let sender_balance_before = test.sender.balance; + let receiver_balance_before = test.receiver.balance; + + let sender_assets_before = AssetHubRococo::execute_with(|| { + type Assets = ::Assets; + >::balance(ASSET_ID, &AssetHubRococoSender::get()) + }); + let receiver_assets_before = PenpalRococoA::execute_with(|| { + type Assets = ::Assets; + >::balance(ASSET_ID, &PenpalRococoAReceiver::get()) + }); + + test.set_assertion::(system_para_to_para_assets_sender_assertions); + test.set_assertion::(system_para_to_para_assets_receiver_assertions); + test.set_dispatchable::(system_para_to_para_limited_reserve_transfer_assets); + test.assert(); + + let sender_balance_after = test.sender.balance; + let receiver_balance_after = test.receiver.balance; + + // Sender's balance is reduced + assert!(sender_balance_after < sender_balance_before); + // Receiver's balance is increased + assert!(receiver_balance_after > receiver_balance_before); - system_para_test.set_assertion::(system_para_to_para_assets_assertions); - // TODO: Add assertions when Penpal is able to manage assets - system_para_test - .set_dispatchable::(system_para_to_para_limited_reserve_transfer_assets); - system_para_test.assert(); + let sender_assets_after = AssetHubRococo::execute_with(|| { + type Assets = ::Assets; + >::balance(ASSET_ID, &AssetHubRococoSender::get()) + }); + let receiver_assets_after = PenpalRococoA::execute_with(|| { + type Assets = ::Assets; + >::balance(ASSET_ID, &PenpalRococoAReceiver::get()) + }); + + // Sender's balance is reduced + assert_eq!(sender_assets_before - asset_amount_to_send, sender_assets_after); + // Receiver's balance is increased + assert!(receiver_assets_after > receiver_assets_before); } diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs index 217bac6865c8..f8017f7a1c54 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/teleport.rs @@ -206,7 +206,7 @@ fn limited_teleport_native_assets_back_from_system_para_to_relay_works() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: RococoReceiver::get(), - args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0), }; let mut test = SystemParaToRelayTest::new(test_args); @@ -247,7 +247,7 @@ fn limited_teleport_native_assets_from_system_para_to_relay_fails() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: RococoReceiver::get(), - args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0), }; let mut test = SystemParaToRelayTest::new(test_args); @@ -329,7 +329,7 @@ fn teleport_native_assets_back_from_system_para_to_relay_works() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: RococoReceiver::get(), - args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0), }; let mut test = SystemParaToRelayTest::new(test_args); @@ -370,7 +370,7 @@ fn teleport_native_assets_from_system_para_to_relay_fails() { let test_args = TestContext { sender: AssetHubRococoSender::get(), receiver: RococoReceiver::get(), - args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None), + args: para_test_args(destination, beneficiary_id, amount_to_send, assets, None, 0), }; let mut test = SystemParaToRelayTest::new(test_args); diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs index bb4c9d102e98..b93c148dabc0 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs @@ -401,7 +401,7 @@ macro_rules! impl_accounts_helpers_for_parachain { #[macro_export] macro_rules! impl_assert_events_helpers_for_parachain { - ( $chain:ident ) => { + ( $chain:ident, $ignore_weight:expr ) => { $crate::impls::paste::paste! { type [<$chain RuntimeEvent>] = <$chain as $crate::impls::Chain>::RuntimeEvent; @@ -414,7 +414,7 @@ macro_rules! impl_assert_events_helpers_for_parachain { [<$chain RuntimeEvent>]::PolkadotXcm( $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Complete(weight) } ) => { - weight: $crate::impls::weight_within_threshold( + weight: $ignore_weight || $crate::impls::weight_within_threshold( ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD), expected_weight.unwrap_or(*weight), *weight @@ -436,7 +436,7 @@ macro_rules! impl_assert_events_helpers_for_parachain { [<$chain RuntimeEvent>]::PolkadotXcm( $crate::impls::pallet_xcm::Event::Attempted { outcome: $crate::impls::Outcome::Incomplete(weight, error) } ) => { - weight: $crate::impls::weight_within_threshold( + weight: $ignore_weight || $crate::impls::weight_within_threshold( ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD), expected_weight.unwrap_or(*weight), *weight @@ -492,7 +492,7 @@ macro_rules! impl_assert_events_helpers_for_parachain { [<$chain RuntimeEvent>]::DmpQueue($crate::impls::cumulus_pallet_dmp_queue::Event::ExecutedDownward { outcome: $crate::impls::Outcome::Complete(weight), .. }) => { - weight: $crate::impls::weight_within_threshold( + weight: $ignore_weight || $crate::impls::weight_within_threshold( ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD), expected_weight.unwrap_or(*weight), *weight @@ -513,7 +513,7 @@ macro_rules! impl_assert_events_helpers_for_parachain { [<$chain RuntimeEvent>]::DmpQueue($crate::impls::cumulus_pallet_dmp_queue::Event::ExecutedDownward { outcome: $crate::impls::Outcome::Incomplete(weight, error), .. }) => { - weight: $crate::impls::weight_within_threshold( + weight: $ignore_weight || $crate::impls::weight_within_threshold( ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD), expected_weight.unwrap_or(*weight), *weight @@ -548,7 +548,7 @@ macro_rules! impl_assert_events_helpers_for_parachain { [<$chain RuntimeEvent>]::XcmpQueue( $crate::impls::cumulus_pallet_xcmp_queue::Event::Success { weight, .. } ) => { - weight: $crate::impls::weight_within_threshold( + weight: $ignore_weight || $crate::impls::weight_within_threshold( ($crate::impls::REF_TIME_THRESHOLD, $crate::impls::PROOF_SIZE_THRESHOLD), expected_weight.unwrap_or(*weight), *weight diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index 1ec006f4510b..ac06b921e46d 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -312,24 +312,25 @@ impl_send_transact_helpers_for_relay_chain!(Wococo); // AssetHubWestend implementation impl_accounts_helpers_for_parachain!(AssetHubWestend); impl_assets_helpers_for_parachain!(AssetHubWestend, Westend); -impl_assert_events_helpers_for_parachain!(AssetHubWestend); +impl_assert_events_helpers_for_parachain!(AssetHubWestend, false); // AssetHubRococo implementation impl_accounts_helpers_for_parachain!(AssetHubRococo); impl_assets_helpers_for_parachain!(AssetHubRococo, Rococo); -impl_assert_events_helpers_for_parachain!(AssetHubRococo); +impl_assert_events_helpers_for_parachain!(AssetHubRococo, false); // PenpalWestendA implementation -impl_assert_events_helpers_for_parachain!(PenpalWestendA); +impl_assert_events_helpers_for_parachain!(PenpalWestendA, true); // BridgeHubRococo implementation impl_accounts_helpers_for_parachain!(BridgeHubRococo); -impl_assert_events_helpers_for_parachain!(BridgeHubRococo); +impl_assert_events_helpers_for_parachain!(BridgeHubRococo, false); // PenpalRococo implementations impl_accounts_helpers_for_parachain!(PenpalRococoA); -impl_assert_events_helpers_for_parachain!(PenpalRococoA); -impl_assert_events_helpers_for_parachain!(PenpalRococoB); +impl_assets_helpers_for_parachain!(PenpalRococoA, Rococo); +impl_assert_events_helpers_for_parachain!(PenpalRococoA, true); +impl_assert_events_helpers_for_parachain!(PenpalRococoB, true); decl_test_sender_receiver_accounts_parameter_types! { // Relays diff --git a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs index 522cbf1faced..b5ef56e72711 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/lib.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/lib.rs @@ -432,7 +432,7 @@ parameter_types! { // pub type AssetsForceOrigin = // EnsureOneOf, EnsureXcm>>; -impl pallet_assets::Config for Runtime { +impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; type AssetId = AssetId; @@ -557,7 +557,12 @@ impl pallet_asset_tx_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Fungibles = Assets; type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter< - pallet_assets::BalanceToAssetBalance, + pallet_assets::BalanceToAssetBalance< + Balances, + Runtime, + ConvertInto, + pallet_assets::Instance1, + >, AssetsToBlockAuthor, >; } @@ -599,7 +604,7 @@ construct_runtime!( DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 33, // The main stage. - Assets: pallet_assets::{Pallet, Call, Storage, Event} = 50, + Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, Sudo: pallet_sudo::{Pallet, Call, Storage, Event, Config} = 255, } diff --git a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs index 7dde53452d35..74d9a0b071d8 100644 --- a/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs @@ -38,6 +38,7 @@ use frame_support::{ }; use frame_system::EnsureRoot; use pallet_asset_tx_payment::HandleCredit; +use pallet_assets::Instance1; use pallet_xcm::XcmPassthrough; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; @@ -48,9 +49,10 @@ use xcm_builder::{ AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, - ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, + WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::{traits::JustTry, XcmExecutor}; @@ -126,6 +128,9 @@ pub type XcmOriginToTransactDispatchOrigin = ( // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when // recognized. SiblingParachainAsNative, + // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a + // transaction from the Root origin. + ParentAsSuperuser, // Native signed account converter; this just converts an `AccountId32` origin into a normal // `RuntimeOrigin::Signed` origin of the same 32-byte value. SignedAccountId32AsNative, @@ -189,7 +194,7 @@ impl> ContainsPair for AssetsFr let loc = T::get(); &loc == origin && matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } - if asset_loc.match_and_split(&loc).is_some()) + if asset_loc.starts_with(&loc)) } } @@ -219,15 +224,15 @@ where /// A `HandleCredit` implementation that naively transfers the fees to the block author. /// Will drop and burn the assets in case the transfer fails. pub struct AssetsToBlockAuthor(PhantomData); -impl HandleCredit, pallet_assets::Pallet> for AssetsToBlockAuthor +impl HandleCredit, pallet_assets::Pallet> for AssetsToBlockAuthor where - R: pallet_authorship::Config + pallet_assets::Config, + R: pallet_authorship::Config + pallet_assets::Config, AccountIdOf: From + Into, { - fn handle_credit(credit: Credit, pallet_assets::Pallet>) { + fn handle_credit(credit: Credit, pallet_assets::Pallet>) { if let Some(author) = pallet_authorship::Pallet::::author() { // In case of error: Will drop the result triggering the `OnDrop` of the imbalance. - let _ = pallet_assets::Pallet::::resolve(&author, credit); + let _ = pallet_assets::Pallet::::resolve(&author, credit); } } } diff --git a/polkadot/xcm/src/v3/multiasset.rs b/polkadot/xcm/src/v3/multiasset.rs index 9d86fb8deff8..aeba5389b39c 100644 --- a/polkadot/xcm/src/v3/multiasset.rs +++ b/polkadot/xcm/src/v3/multiasset.rs @@ -694,7 +694,9 @@ impl MultiAssets { target: &MultiLocation, context: InteriorMultiLocation, ) -> Result<(), ()> { - self.0.iter_mut().try_for_each(|i| i.reanchor(target, context)) + self.0.iter_mut().try_for_each(|i| i.reanchor(target, context))?; + self.0.sort(); + Ok(()) } /// Return a reference to an item at a specific index or `None` if it doesn't exist. From 582c616d697665bb116f7d6d8ab9426993293f49 Mon Sep 17 00:00:00 2001 From: Adrian Catangiu Date: Fri, 3 Nov 2023 15:46:55 +0200 Subject: [PATCH 122/124] fix merge damage --- Cargo.lock | 1 + .../assets/asset-hub-rococo/Cargo.toml | 1 + .../src/tests/reserve_transfer.rs | 19 ++++++++++++------- .../src/tests/reserve_transfer.rs | 4 +++- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bb0cfe52d2f..2bebcfe5ece3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -889,6 +889,7 @@ dependencies = [ "pallet-asset-conversion", "pallet-assets", "pallet-balances", + "pallet-message-queue", "pallet-xcm", "parachains-common", "parity-scale-codec", diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml index 820429deae45..e13d996830c6 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/Cargo.toml @@ -18,6 +18,7 @@ frame-system = { path = "../../../../../../substrate/frame/system", default-feat pallet-balances = { path = "../../../../../../substrate/frame/balances", default-features = false} pallet-assets = { path = "../../../../../../substrate/frame/assets", default-features = false} pallet-asset-conversion = { path = "../../../../../../substrate/frame/asset-conversion", default-features = false} +pallet-message-queue = { path = "../../../../../../substrate/frame/message-queue", default-features = false } # Polkadot polkadot-core-primitives = { path = "../../../../../../polkadot/core-primitives", default-features = false} diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs index 38abc3dea740..0ab293f1746b 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-rococo/src/tests/reserve_transfer.rs @@ -46,10 +46,9 @@ fn relay_to_para_receiver_assertions(_: Test) { PenpalRococoA, vec![ RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, - RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward { - outcome: Outcome::Complete(_), - .. - }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, ] ); } @@ -85,7 +84,9 @@ fn system_para_to_para_receiver_assertions(_: Test) { PenpalRococoA, vec![ RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, ] ); } @@ -130,7 +131,9 @@ fn para_to_system_para_receiver_assertions(t: ParaToSystemParaTest) { amount: *amount == t.args.amount, }, RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, ] ); } @@ -168,7 +171,9 @@ fn system_para_to_para_assets_receiver_assertions(_: Test) { vec![ RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, RuntimeEvent::Assets(pallet_assets::Event::Issued { .. }) => {}, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, ] ); } diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs index 518e117c1074..3000ac2eb02d 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-westend/src/tests/reserve_transfer.rs @@ -47,7 +47,9 @@ fn para_receiver_assertions(_: Test) { PenpalWestendA, vec![ RuntimeEvent::Balances(pallet_balances::Event::Deposit { .. }) => {}, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) => {}, + RuntimeEvent::MessageQueue( + pallet_message_queue::Event::Processed { success: true, .. } + ) => {}, ] ); } From 71197605d792abca283c01c5873bfe8e1dba83c8 Mon Sep 17 00:00:00 2001 From: Clara van Staden Date: Mon, 6 Nov 2023 10:03:33 +0200 Subject: [PATCH 123/124] Adds Ethereum router (#16) * configures ethereum router * adds benchmarks and fmt --------- Co-authored-by: claravanstaden --- .../assets/asset-hub-rococo/src/lib.rs | 52 +++++++- .../asset-hub-rococo/src/weights/mod.rs | 1 + ...allet_xcm_bridge_hub_router_to_ethereum.rs | 124 ++++++++++++++++++ .../assets/asset-hub-rococo/src/xcm_config.rs | 87 ++++++++---- 4 files changed, 240 insertions(+), 24 deletions(-) create mode 100644 cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_hub_router_to_ethereum.rs diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index 4737fc165f17..9f88b237e39d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -97,7 +97,7 @@ use xcm::latest::prelude::*; use xcm_executor::XcmExecutor; use crate::xcm_config::{ - bridging::to_wococo::EthereumLocation, ForeignCreatorsSovereignAccountOf, + bridging::to_ethereum::EthereumLocation, ForeignCreatorsSovereignAccountOf, LocalAndForeignAssetsMultiLocationMatcher, TrustBackedAssetsPalletLocation, }; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; @@ -872,7 +872,38 @@ impl pallet_xcm_bridge_hub_router::Config for Runtime type WeightInfo = weights::pallet_xcm_bridge_hub_router_to_rococo::WeightInfo; type UniversalLocation = xcm_config::UniversalLocation; - type BridgedNetworkId = (); + type BridgedNetworkId = xcm_config::bridging::to_rococo::RococoNetwork; + type Bridges = xcm_config::bridging::NetworkExportTable; + + #[cfg(not(feature = "runtime-benchmarks"))] + type BridgeHubOrigin = EnsureXcm>; + #[cfg(feature = "runtime-benchmarks")] + type BridgeHubOrigin = EitherOfDiverse< + // for running benchmarks + EnsureRoot, + // for running tests with `--feature runtime-benchmarks` + EnsureXcm>, + >; + + type ToBridgeHubSender = XcmpQueue; + type WithBridgeHubChannel = + cumulus_pallet_xcmp_queue::bridging::InAndOutXcmpChannelStatusProvider< + xcm_config::bridging::SiblingBridgeHubParaId, + Runtime, + >; + + type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee; + type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; +} + +/// XCM router instance to BridgeHub with bridging capabilities for `Ethereum` global +/// consensus with dynamic fees and back-pressure. +pub type ToEthereumXcmRouterInstance = pallet_assets::Instance3; +impl pallet_xcm_bridge_hub_router::Config for Runtime { + type WeightInfo = weights::pallet_xcm_bridge_hub_router_to_ethereum::WeightInfo; + + type UniversalLocation = xcm_config::UniversalLocation; + type BridgedNetworkId = xcm_config::bridging::to_ethereum::EthereumNetwork; type Bridges = xcm_config::bridging::NetworkExportTable; #[cfg(not(feature = "runtime-benchmarks"))] @@ -934,6 +965,7 @@ construct_runtime!( // Bridge utilities. ToWococoXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 43, ToRococoXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 44, + ToEthereumXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 45, // The main stage. Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, @@ -1268,6 +1300,7 @@ impl_runtime_apis! { type ToWococo = XcmBridgeHubRouterBench; type ToRococo = XcmBridgeHubRouterBench; + type ToEthereum = XcmBridgeHubRouterBench; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -1362,6 +1395,20 @@ impl_runtime_apis! { xcm_config::bridging::to_rococo::AssetHubRococo::get() } } + impl XcmBridgeHubRouterConfig for Runtime { + fn make_congested() { + cumulus_pallet_xcmp_queue::bridging::suspend_channel_for_benchmarks::( + xcm_config::bridging::SiblingBridgeHubParaId::get().into() + ); + } + fn ensure_bridged_target_destination() -> MultiLocation { + xcm_config::Flavor::set(&RuntimeFlavor::Rococo); + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( + xcm_config::bridging::SiblingBridgeHubParaId::get().into() + ); + xcm_config::bridging::to_rococo::AssetHubRococo::get() + } + } use xcm::latest::prelude::*; use xcm_config::{TokenLocation, MaxAssetsIntoHolding}; @@ -1499,6 +1546,7 @@ impl_runtime_apis! { type ToWococo = XcmBridgeHubRouterBench; type ToRococo = XcmBridgeHubRouterBench; + type ToEthereum = XcmBridgeHubRouterBench; let whitelist: Vec = vec![ // Block Number diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs index 59f97d2c8e5c..07dc8a6cd444 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs @@ -33,6 +33,7 @@ pub mod pallet_timestamp; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; +pub mod pallet_xcm_bridge_hub_router_to_ethereum; pub mod pallet_xcm_bridge_hub_router_to_rococo; pub mod pallet_xcm_bridge_hub_router_to_wococo; pub mod paritydb_weights; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_hub_router_to_ethereum.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_hub_router_to_ethereum.rs new file mode 100644 index 000000000000..4be3ca5f516a --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_hub_router_to_ethereum.rs @@ -0,0 +1,124 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus 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. + +// Cumulus 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 Cumulus. If not, see . + +//! Autogenerated weights for `pallet_xcm_bridge_hub_router` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-09-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-guclnr1q-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-dev")`, DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm_bridge_hub_router +// --chain=asset-hub-rococo-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_xcm_bridge_hub_router`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_bridge_hub_router::WeightInfo for WeightInfo { + /// Storage: UNKNOWN KEY `0x48297505634037ef48c848c99c0b1f1b` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x48297505634037ef48c848c99c0b1f1b` (r:1 w:0) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::InboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::InboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ToEthereumXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToEthereumXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn on_initialize_when_non_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `198` + // Estimated: `3663` + // Minimum execution time: 10_936_000 picoseconds. + Weight::from_parts(11_432_000, 0) + .saturating_add(Weight::from_parts(0, 3663)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: UNKNOWN KEY `0x48297505634037ef48c848c99c0b1f1b` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x48297505634037ef48c848c99c0b1f1b` (r:1 w:0) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn on_initialize_when_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `150` + // Estimated: `3615` + // Minimum execution time: 5_165_000 picoseconds. + Weight::from_parts(5_356_000, 0) + .saturating_add(Weight::from_parts(0, 3615)) + .saturating_add(T::DbWeight::get().reads(2)) + } + /// Storage: `ToEthereumXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToEthereumXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn report_bridge_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `83` + // Estimated: `1502` + // Minimum execution time: 11_420_000 picoseconds. + Weight::from_parts(11_946_000, 0) + .saturating_add(Weight::from_parts(0, 1502)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: UNKNOWN KEY `0x48297505634037ef48c848c99c0b1f1b` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x48297505634037ef48c848c99c0b1f1b` (r:1 w:0) + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Storage: `ToEthereumXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToEthereumXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0) + /// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn send_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `392` + // Estimated: `3857` + // Minimum execution time: 52_129_000 picoseconds. + Weight::from_parts(53_552_000, 0) + .saturating_add(Weight::from_parts(0, 3857)) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index bc9f17b79e18..c0590a79cc31 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -17,8 +17,8 @@ use super::{ AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, BaseDeliveryFee, FeeAssetId, ForeignAssets, ForeignAssetsInstance, ParachainInfo, ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeFlavor, RuntimeOrigin, - ToRococoXcmRouter, ToWococoXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, - WeightToFee, XcmpQueue, + ToEthereumXcmRouter, ToRococoXcmRouter, ToWococoXcmRouter, TransactionByteFee, + TrustBackedAssetsInstance, WeightToFee, XcmpQueue, }; use assets_common::{ local_and_foreign_assets::MatchesLocalAndForeignAssetsMultiLocation, @@ -59,6 +59,7 @@ use xcm_builder::{ }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; +use crate::ToEthereumXcmRouterInstance; #[cfg(feature = "runtime-benchmarks")] use cumulus_primitives_core::ParaId; @@ -563,8 +564,8 @@ impl xcm_executor::Config for XcmConfig { // Users must use teleport where allowed (e.g. ROC with the Relay Chain). type IsReserve = ( bridging::to_wococo::IsTrustedBridgedReserveLocationForConcreteAsset, - bridging::to_wococo::IsTrustedBridgedReserveLocationForForeignAsset, bridging::to_rococo::IsTrustedBridgedReserveLocationForConcreteAsset, + bridging::to_ethereum::IsTrustedBridgedReserveLocationForForeignAsset, ); type IsTeleporter = TrustedTeleporters; type UniversalLocation = UniversalLocation; @@ -616,8 +617,11 @@ impl xcm_executor::Config for XcmConfig { XcmFeeToAccount, >; type MessageExporter = (); - type UniversalAliases = - (bridging::to_wococo::UniversalAliases, bridging::to_rococo::UniversalAliases); + type UniversalAliases = ( + bridging::to_wococo::UniversalAliases, + bridging::to_rococo::UniversalAliases, + bridging::to_ethereum::UniversalAliases, + ); type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; @@ -648,6 +652,9 @@ pub type XcmRouter = WithUniqueTopic<( // Router which wraps and sends xcm to BridgeHub to be delivered to the Rococo // GlobalConsensus ToRococoXcmRouter, + // Router which wraps and sends xcm to BridgeHub to be delivered to the Ethereum + // GlobalConsensus + ToEthereumXcmRouter, )>; impl pallet_xcm::Config for Runtime { @@ -762,6 +769,7 @@ pub mod bridging { sp_std::vec::Vec::new().into_iter() .chain(to_wococo::BridgeTable::get()) .chain(to_rococo::BridgeTable::get()) + .chain(to_ethereum::BridgeTable::get()) .collect(); } @@ -782,8 +790,6 @@ pub mod bridging { pub const WococoNetwork: NetworkId = NetworkId::Wococo; pub AssetHubWococo: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(WococoNetwork::get()), Parachain(bp_asset_hub_wococo::ASSET_HUB_WOCOCO_PARACHAIN_ID))); pub WocLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(WococoNetwork::get()))); - pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; - pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); pub WocFromAssetHubWococo: (MultiAssetFilter, MultiLocation) = ( Wild(AllOf { fun: WildFungible, id: Concrete(WocLocation::get()) }), @@ -805,17 +811,6 @@ pub mod bridging { bp_asset_hub_rococo::BridgeHubRococoBaseFeeInRocs::get(), ).into()) ), - NetworkExportTableItem::new( - EthereumNetwork::get(), - Some(sp_std::vec![ - EthereumLocation::get().interior.split_global().expect("invalid configuration for Ethereum").1, - ]), - SiblingBridgeHub::get(), - Some(( - XcmBridgeHubRouterFeeAssetId::get(), - BridgeHubEthereumBaseFeeInRocs::get(), - ).into()) - ), ]; /// Allowed assets for reserve transfer to `AssetHubWococo`. @@ -829,14 +824,10 @@ pub mod bridging { pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( sp_std::vec![ (SiblingBridgeHubWithBridgeHubWococoInstance::get(), GlobalConsensus(WococoNetwork::get())), - (SiblingBridgeHub::get(), GlobalConsensus(EthereumNetwork::get())), ] ); } - pub type IsTrustedBridgedReserveLocationForForeignAsset = - matching::IsForeignConcreteAsset>; - impl Contains<(MultiLocation, Junction)> for UniversalAliases { fn contains(alias: &(MultiLocation, Junction)) -> bool { UniversalAliases::get().contains(alias) @@ -962,6 +953,58 @@ pub mod bridging { } } + pub mod to_ethereum { + use super::*; + + parameter_types! { + pub EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; + pub EthereumLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(EthereumNetwork::get()))); + + /// Set up exporters configuration. + /// `Option` represents static "base fee" which is used for total delivery fee calculation. + pub BridgeTable: sp_std::vec::Vec = sp_std::vec![ + NetworkExportTableItem::new( + EthereumNetwork::get(), + Some(sp_std::vec![ + EthereumLocation::get().interior.split_global().expect("invalid configuration for Ethereum").1, + ]), + SiblingBridgeHub::get(), + Some(( + XcmBridgeHubRouterFeeAssetId::get(), + BridgeHubEthereumBaseFeeInRocs::get(), + ).into()) + ), + ]; + + /// Universal aliases + pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( + sp_std::vec![ + (SiblingBridgeHub::get(), GlobalConsensus(EthereumNetwork::get())), + ] + ); + } + + pub type IsTrustedBridgedReserveLocationForForeignAsset = + matching::IsForeignConcreteAsset>; + + impl Contains<(MultiLocation, Junction)> for UniversalAliases { + fn contains(alias: &(MultiLocation, Junction)) -> bool { + UniversalAliases::get().contains(alias) + } + } + + impl Contains for ToEthereumXcmRouter { + fn contains(call: &RuntimeCall) -> bool { + matches!( + call, + RuntimeCall::ToEthereumXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } + ) + ) + } + } + } + /// Benchmarks helper for bridging configuration. #[cfg(feature = "runtime-benchmarks")] pub struct BridgingBenchmarksHelper; From 8e1cb1e2c149e1c02998b5d4e9b8506691e1a46b Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Mon, 6 Nov 2023 14:52:44 +0200 Subject: [PATCH 124/124] fixes after merge --- Cargo.lock | 316 +++++++++++++++++- .../assets/asset-hub-rococo/src/lib.rs | 4 +- .../bridge-hubs/bridge-hub-rococo/Cargo.toml | 1 - .../src/bridge_to_ethereum_config.rs | 73 ++++ .../bridge-hubs/bridge-hub-rococo/src/lib.rs | 37 +- .../bridge-hub-rococo/src/xcm_config.rs | 1 + 6 files changed, 408 insertions(+), 24 deletions(-) create mode 100644 cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_ethereum_config.rs diff --git a/Cargo.lock b/Cargo.lock index 2bebcfe5ece3..ce4a5bd059e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,6 +197,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4436e0292ab1bb631b42973c61205e704475fe8126af845c8d923c0996328127" +[[package]] +name = "amcl" +version = "0.3.0" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -965,6 +974,7 @@ dependencies = [ "rococo-runtime-constants", "scale-info", "smallvec", + "snowbridge-router-primitives", "sp-api", "sp-block-builder", "sp-consensus-aura", @@ -1474,8 +1484,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" dependencies = [ "bitcoin_hashes", - "rand 0.7.3", - "rand_core 0.5.1", + "rand 0.8.5", + "rand_core 0.6.4", "serde", "unicode-normalization", ] @@ -2151,6 +2161,8 @@ dependencies = [ "cumulus-pallet-xcmp-queue", "frame-support", "frame-system", + "hex", + "hex-literal", "integration-tests-common", "pallet-assets", "pallet-balances", @@ -2162,6 +2174,10 @@ dependencies = [ "polkadot-core-primitives", "polkadot-parachain-primitives", "polkadot-runtime-parachains", + "snowbridge-control", + "snowbridge-core", + "snowbridge-inbound-queue", + "snowbridge-router-primitives", "sp-core", "sp-weights", "staging-xcm", @@ -2233,6 +2249,15 @@ dependencies = [ "scale-info", "serde", "smallvec", + "snowbridge-beacon-primitives", + "snowbridge-control", + "snowbridge-control-runtime-api", + "snowbridge-core", + "snowbridge-ethereum-beacon-client", + "snowbridge-inbound-queue", + "snowbridge-outbound-queue", + "snowbridge-outbound-queue-runtime-api", + "snowbridge-router-primitives", "sp-api", "sp-block-builder", "sp-consensus-aura", @@ -5096,6 +5121,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ethabi-decode" +version = "1.4.0" +source = "git+https://github.com/Snowfork/ethabi-decode.git?branch=master#7d215837b626650bd9a076821e57ad488101301f" +dependencies = [ + "ethereum-types", + "tiny-keccak", +] + [[package]] name = "ethbloom" version = "0.13.0" @@ -5104,8 +5138,10 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "tiny-keccak", ] @@ -5117,9 +5153,11 @@ checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", "primitive-types", + "scale-info", "uint", ] @@ -8169,6 +8207,20 @@ dependencies = [ "thrift", ] +[[package]] +name = "milagro_bls" +version = "1.5.0" +source = "git+https://github.com/snowfork/milagro_bls?rev=a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176#a6d66e4eb89015e352fb1c9f7b661ecdbb5b2176" +dependencies = [ + "amcl", + "hex", + "lazy_static", + "parity-scale-codec", + "rand 0.8.5", + "scale-info", + "zeroize", +] + [[package]] name = "mime" version = "0.3.17" @@ -10435,12 +10487,15 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "pallet-xcm", "parity-scale-codec", "scale-info", "serde", "sp-core", "sp-io", "sp-runtime", + "sp-std 8.0.0", + "staging-xcm", ] [[package]] @@ -11314,6 +11369,12 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "parity-bytes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b56e3a2420138bdb970f84dfb9c774aea80fa0e7371549eedec0d80c209c67" + [[package]] name = "parity-db" version = "0.4.10" @@ -16416,6 +16477,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd31f59f6fe2b0c055371bb2f16d7f0aa7d8881676c04a55b1596d1a17cd10a4" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.188" @@ -16860,6 +16930,225 @@ dependencies = [ "subtle 2.4.1", ] +[[package]] +name = "snowbridge-beacon-primitives" +version = "0.0.1" +dependencies = [ + "byte-slice-cast", + "frame-support", + "frame-system", + "hex", + "milagro_bls", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-ethereum", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 8.0.0", + "ssz_rs", + "ssz_rs_derive", + "static_assertions", +] + +[[package]] +name = "snowbridge-control" +version = "4.0.0-dev" +dependencies = [ + "ethabi-decode", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "snowbridge-core", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 8.0.0", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + +[[package]] +name = "snowbridge-control-runtime-api" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "snowbridge-core", + "sp-api", + "sp-core", + "sp-std 8.0.0", + "staging-xcm", +] + +[[package]] +name = "snowbridge-core" +version = "0.1.1" +dependencies = [ + "ethabi-decode", + "frame-support", + "frame-system", + "parity-scale-codec", + "polkadot-parachain-primitives", + "scale-info", + "serde", + "snowbridge-beacon-primitives", + "snowbridge-ethereum", + "sp-arithmetic", + "sp-core", + "sp-runtime", + "sp-std 8.0.0", + "staging-xcm", +] + +[[package]] +name = "snowbridge-ethereum" +version = "0.1.0" +dependencies = [ + "ethabi-decode", + "ethbloom", + "ethereum-types", + "hex-literal", + "parity-bytes", + "parity-scale-codec", + "rlp", + "rustc-hex", + "scale-info", + "serde", + "serde-big-array", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 8.0.0", +] + +[[package]] +name = "snowbridge-ethereum-beacon-client" +version = "0.0.1" +dependencies = [ + "bp-runtime", + "byte-slice-cast", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex-literal", + "log", + "pallet-timestamp", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-ethereum", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 8.0.0", + "ssz_rs", + "ssz_rs_derive", + "static_assertions", +] + +[[package]] +name = "snowbridge-inbound-queue" +version = "0.1.1" +dependencies = [ + "ethabi-decode", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex-literal", + "pallet-balances", + "parity-scale-codec", + "rlp", + "scale-info", + "serde", + "snowbridge-beacon-primitives", + "snowbridge-core", + "snowbridge-ethereum", + "snowbridge-router-primitives", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 8.0.0", + "staging-xcm", + "staging-xcm-builder", +] + +[[package]] +name = "snowbridge-outbound-queue" +version = "0.1.1" +dependencies = [ + "ethabi-decode", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex-literal", + "parity-scale-codec", + "scale-info", + "serde", + "snowbridge-core", + "snowbridge-outbound-queue-merkle-tree", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 8.0.0", + "staging-xcm", +] + +[[package]] +name = "snowbridge-outbound-queue-merkle-tree" +version = "0.1.1" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "snowbridge-outbound-queue-runtime-api" +version = "0.1.0" +dependencies = [ + "frame-support", + "parity-scale-codec", + "snowbridge-core", + "snowbridge-outbound-queue-merkle-tree", + "sp-api", + "sp-core", + "sp-std 8.0.0", + "staging-xcm", +] + +[[package]] +name = "snowbridge-router-primitives" +version = "0.1.1" +dependencies = [ + "ethabi-decode", + "frame-support", + "frame-system", + "hex-literal", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "snowbridge-core", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std 8.0.0", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", +] + [[package]] name = "socket2" version = "0.4.9" @@ -17976,6 +18265,29 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ssz_rs" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "057291e5631f280978fa9c8009390663ca4613359fc1318e36a8c24c392f6d1f" +dependencies = [ + "bitvec", + "num-bigint", + "sha2 0.9.9", + "ssz_rs_derive", +] + +[[package]] +name = "ssz_rs_derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f07d54c4d01a1713eb363b55ba51595da15f6f1211435b71466460da022aa140" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index f895ffee9982..83ec027d24bf 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -963,7 +963,7 @@ impl pallet_xcm_bridge_hub_router::Config for Runtim /// XCM router instance to BridgeHub with bridging capabilities for `Ethereum` global /// consensus with dynamic fees and back-pressure. -pub type ToEthereumXcmRouterInstance = pallet_assets::Instance3; +pub type ToEthereumXcmRouterInstance = pallet_assets::Instance4; impl pallet_xcm_bridge_hub_router::Config for Runtime { type WeightInfo = weights::pallet_xcm_bridge_hub_router_to_ethereum::WeightInfo; @@ -1032,7 +1032,7 @@ construct_runtime!( ToWococoXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 43, ToRococoXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 44, ToWestendXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 45, - ToEthereumXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 46, + ToEthereumXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 46, // The main stage. Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml index e008ec2cf901..c54f578d4bbb 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/Cargo.toml @@ -30,7 +30,6 @@ pallet-authorship = { path = "../../../../../substrate/frame/authorship", defaul pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false} pallet-session = { path = "../../../../../substrate/frame/session", default-features = false} pallet-multisig = { path = "../../../../../substrate/frame/multisig", default-features = false} -pallet-message-queue = { path = "../../../../../substrate/frame/message-queue", default-features = false } pallet-timestamp = { path = "../../../../../substrate/frame/timestamp", default-features = false} pallet-transaction-payment = { path = "../../../../../substrate/frame/transaction-payment", default-features = false} pallet-transaction-payment-rpc-runtime-api = { path = "../../../../../substrate/frame/transaction-payment/rpc/runtime-api", default-features = false} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_ethereum_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_ethereum_config.rs new file mode 100644 index 000000000000..4d1aa03b9beb --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_to_ethereum_config.rs @@ -0,0 +1,73 @@ +use bp_messages::LaneId; +use bp_messages::source_chain::OnMessagesDelivered; +use bridge_runtime_common::messages::source::TargetHeaderChainAdapter; +use bridge_runtime_common::messages::target::SourceHeaderChainAdapter; +use bridge_runtime_common::messages_xcm_extension::{XcmAsPlainPayload, XcmBlobHauler, XcmBlobHaulerAdapter, XcmBlobMessageDispatch}; +use frame_support::parameter_types; +use xcm_builder::HaulBlobExporter; +use crate::bridge_common_config::DeliveryRewardInBalance; +use crate::bridge_to_rococo_config::{ActiveOutboundLanesToBridgeHubRococo, AssetHubWococoParaId, BridgeHubRococoChainId, CongestedMessage, MaxUnconfirmedMessagesAtInboundLane, MaxUnrewardedRelayerEntriesAtInboundLane, RococoGlobalConsensusNetwork, ToBridgeHubRococoMaximalOutboundPayloadSize, ToBridgeHubRococoMessageVerifier, UncongestedMessage, WithBridgeHubRococoMessageBridge}; +use crate::weights; +use crate::xcm_config::XcmRouter; + +parameter_types! { + pub EthereumGlobalConsensusNetwork: NetworkId = NetworkId::Ethereum { chain_id: 15 }; + pub FromAssetHubRococoToBridgehubRococoRoute: SenderAndLane = SenderAndLane::new( + ParentThen(X1(Parachain(AssetHubRococoParaId::get().into()))).into(), + XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_BRIDGE_HUB_ROCOCO, + ); +} +pub const XCM_LANE_FOR_ASSET_HUB_ROCOCO_TO_BRIDGE_HUB_ROCOCO: LaneId = LaneId([0, 0, 0, 3]); + +/// Export XCM messages to be relayed to the other side +pub type ToBridgeHubEthereumBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter, + EthereumGlobalConsensusNetwork, + (), +>; +pub struct ToBridgeHubEthereumXcmBlobHauler; +impl XcmBlobHauler for ToBridgeHubEthereumXcmBlobHauler { + type Runtime = Runtime; + type MessagesInstance = WithBridgeHubRococoMessagesInstance; + type SenderAndLane = FromAssetHubRococoToBridgehubRococoRoute; + + type ToSourceChainSender = XcmRouter; + type CongestedMessage = CongestedMessage; + type UncongestedMessage = UncongestedMessage; +} + +pub type WithBridgeHubRococoMessagesInstance = pallet_bridge_messages::Instance4; +impl pallet_bridge_messages::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_messages_wococo_to_rococo::WeightInfo; + type BridgedChainId = BridgeHubRococoChainId; + type ActiveOutboundLanes = ActiveOutboundLanesToBridgeHubRococo; + type MaxUnrewardedRelayerEntriesAtInboundLane = MaxUnrewardedRelayerEntriesAtInboundLane; + type MaxUnconfirmedMessagesAtInboundLane = MaxUnconfirmedMessagesAtInboundLane; + + type MaximalOutboundPayloadSize = ToBridgeHubRococoMaximalOutboundPayloadSize; + type OutboundPayload = XcmAsPlainPayload; + + type InboundPayload = XcmAsPlainPayload; + type InboundRelayer = AccountId; + type DeliveryPayments = (); + + type TargetHeaderChain = TargetHeaderChainAdapter; + type LaneMessageVerifier = ToBridgeHubRococoMessageVerifier; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + WithBridgeHubRococoMessagesInstance, + DeliveryRewardInBalance, + >; + + type SourceHeaderChain = SourceHeaderChainAdapter; + type MessageDispatch = XcmBlobMessageDispatch< + FromRococoMessageBlobDispatcher, + Self::WeightInfo, + cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider< + AssetHubWococoParaId, + Runtime, + >, + >; + type OnMessagesDelivered = OnMessagesDelivered; +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index 049d37222a04..72610d027503 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -38,6 +38,7 @@ pub mod bridge_common_config; pub mod bridge_to_rococo_config; pub mod bridge_to_westend_config; pub mod bridge_to_wococo_config; +pub mod bridge_to_ethereum_config; mod weights; pub mod xcm_config; @@ -404,6 +405,23 @@ impl pallet_message_queue::Config for Runtime { type ServiceWeight = MessageQueueServiceWeight; } +parameter_types! { + /// Amount of weight that can be spent per block to service messages. + pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_message_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Size = u32; + type HeapSize = ConstU32<{ 64 * 1024 }>; + type MaxStale = ConstU32<8>; + type ServiceWeight = MessageQueueServiceWeight; + type MessageProcessor = EthereumOutboundQueue; + type QueueChangeHandler = (); + type QueuePausedQuery = EthereumOutboundQueue; + type WeightInfo = (); +} + impl cumulus_pallet_aura_ext::Config for Runtime {} parameter_types! { @@ -516,23 +534,6 @@ impl pallet_utility::Config for Runtime { type WeightInfo = weights::pallet_utility::WeightInfo; } -parameter_types! { - /// Amount of weight that can be spent per block to service messages. - pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; -} - -impl pallet_message_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Size = u32; - type HeapSize = ConstU32<{ 64 * 1024 }>; - type MaxStale = ConstU32<8>; - type ServiceWeight = MessageQueueServiceWeight; - type MessageProcessor = EthereumOutboundQueue; - type QueueChangeHandler = (); - type QueuePausedQuery = EthereumOutboundQueue; - type WeightInfo = (); -} - // Ethereum Bridge parameter_types! { @@ -694,7 +695,6 @@ construct_runtime!( PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin, Config} = 31, CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 32, DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 33, - MessageQueue: pallet_message_queue::{Pallet, Call, Storage, Event} = 34, // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, @@ -763,7 +763,6 @@ mod benches { [pallet_balances, Balances] [pallet_message_queue, MessageQueue] [pallet_multisig, Multisig] - [pallet_message_queue, MessageQueue] [pallet_session, SessionBench::] [pallet_utility, Utility] [pallet_timestamp, Timestamp] diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index 64fbf3c65012..2ae5950aeb3e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -325,6 +325,7 @@ impl xcm_executor::Config for XcmConfig { crate::bridge_to_westend_config::ToBridgeHubWestendHaulBlobExporter, crate::bridge_to_wococo_config::ToBridgeHubWococoHaulBlobExporter, crate::bridge_to_rococo_config::ToBridgeHubRococoHaulBlobExporter, + crate::bridge_to_ethereum_config::ToBridgeHubEthereumHaulBlobExporter, ); type UniversalAliases = Nothing; type CallDispatcher = WithOriginFilter;