From 3ac5f12b30e7f8f505f3919af9883bb821e44e6f Mon Sep 17 00:00:00 2001 From: ron Date: Wed, 10 Jan 2024 22:47:18 +0800 Subject: [PATCH 1/7] Handle fee with error instead of silently failing --- parachain/runtime/runtime-common/src/lib.rs | 53 ++++++-------- parachain/runtime/test-common/src/lib.rs | 76 ++++++++++++++++++++- polkadot-sdk | 2 +- 3 files changed, 97 insertions(+), 34 deletions(-) diff --git a/parachain/runtime/runtime-common/src/lib.rs b/parachain/runtime/runtime-common/src/lib.rs index b7f54d262b..d17ec5e2bf 100644 --- a/parachain/runtime/runtime-common/src/lib.rs +++ b/parachain/runtime/runtime-common/src/lib.rs @@ -6,7 +6,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use core::marker::PhantomData; -use frame_support::traits::Get; +use frame_support::{ensure, traits::Get}; use snowbridge_core::{outbound::SendMessageFeeProvider, sibling_sovereign_account_raw}; use sp_arithmetic::traits::{BaseArithmetic, Unsigned}; use xcm::prelude::*; @@ -55,7 +55,7 @@ impl, reason: FeeReason, - ) -> MultiAssets { + ) -> Result { let token_location = FeeAssetLocation::get(); // Check the reason to see if this export is for snowbridge. @@ -64,7 +64,7 @@ impl (0u128).into() { - // Refund remote component of fee to physical origin - deposit_or_burn_fee::( - MultiAsset { id: Concrete(token_location), fun: Fungible(remote_fee.into()) } - .into(), - context, - para_sovereign, - ); - // Return remaining fee to the next fee handler in the chain. - let mut modified_fees = fees.inner().clone(); - modified_fees.remove(fee_index); - modified_fees.push(MultiAsset { - id: Concrete(token_location), - fun: Fungible((total_fee - remote_fee).into()), - }); - return modified_fees.into() - } - } - - log::info!( - target: "xcm::fees", - "XcmExportFeeToSibling skipped: {fees:?}, context: {context:?}, reason: {reason:?}", + let (fee_index, total_fee) = maybe_total_supplied_fee.ok_or(XcmError::FeesNotMet)?; + let remote_fee = + total_fee.checked_sub(&FeeProvider::local_fee()).ok_or(XcmError::FeesNotMet)?; + ensure!(remote_fee > Balance::zero(), XcmError::FeesNotMet); + // Refund remote component of fee to physical origin + deposit_or_burn_fee::( + MultiAsset { id: Concrete(token_location), fun: Fungible(remote_fee.into()) }.into(), + context, + para_sovereign, ); - fees + // Return remaining fee to the next fee handler in the chain. + let mut modified_fees = fees.inner().clone(); + modified_fees.remove(fee_index); + modified_fees.push(MultiAsset { + id: Concrete(token_location), + fun: Fungible((total_fee - remote_fee).into()), + }); + Ok(modified_fees.into()) } } diff --git a/parachain/runtime/test-common/src/lib.rs b/parachain/runtime/test-common/src/lib.rs index 5da447bcc9..1c77699566 100644 --- a/parachain/runtime/test-common/src/lib.rs +++ b/parachain/runtime/test-common/src/lib.rs @@ -2,13 +2,17 @@ // SPDX-FileCopyrightText: 2023 Snowfork use codec::Encode; -use frame_support::{assert_err, assert_ok, traits::fungible::Mutate}; +use frame_support::{ + assert_err, assert_ok, + traits::fungible::{Inspect, Mutate}, +}; pub use parachains_runtimes_test_utils::test_cases::change_storage_constant_by_governance_works; use parachains_runtimes_test_utils::{ AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, ValidatorIdOf, XcmReceivedFrom, }; +use snowbridge_core::{gwei, meth, PricingParameters, Rewards}; use sp_core::H160; -use sp_runtime::SaturatedConversion; +use sp_runtime::{FixedU128, SaturatedConversion}; use xcm::{ latest::prelude::*, v3::Error::{self, Barrier}, @@ -18,6 +22,10 @@ use xcm_executor::XcmExecutor; type RuntimeHelper = parachains_runtimes_test_utils::RuntimeHelper; +type TokenBalanceOf = <::Token as Inspect< + ::AccountId, +>>::Balance; + pub fn initial_fund(assethub_parachain_id: u32, initial_amount: u128) where Runtime: frame_system::Config + pallet_balances::Config, @@ -32,6 +40,13 @@ where .unwrap(); } +pub fn initialize_price_params(params: PricingParameters>) +where + Runtime: frame_system::Config + snowbridge_system::Config + pallet_balances::Config, +{ + snowbridge_system::PricingParameters::::put(params.clone()); +} + pub fn send_transfer_token_message( assethub_parachain_id: u32, weth_contract_address: H160, @@ -291,3 +306,60 @@ pub fn send_transfer_token_message_failure( assert_err!(outcome.ensure_complete(), expected_error); }); } + +#[allow(clippy::too_many_arguments)] +pub fn send_transfer_token_message_failure_with_invalid_fee_params( + collator_session_key: CollatorSessionKeys, + runtime_para_id: u32, + assethub_parachain_id: u32, + initial_amount: u128, + weth_contract_address: H160, + destination_address: H160, + fee_amount: u128, + expected_error: Error, +) 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 + + snowbridge_outbound_queue::Config + + snowbridge_system::Config, + XcmConfig: xcm_executor::Config, + ValidatorIdOf: From>, +{ + ExtBuilder::::default() + .with_collators(collator_session_key.collators()) + .with_session_keys(collator_session_key.session_keys()) + .with_para_id(runtime_para_id.into()) + .with_tracing() + .build() + .execute_with(|| { + let params: PricingParameters> = PricingParameters { + exchange_rate: FixedU128::from_rational(1, 400), + fee_per_gas: gwei(0), + rewards: Rewards { local: 0_u32.into(), remote: meth(0) }, + }; + initialize_price_params::(params); + + >::initialize( + runtime_para_id.into(), + assethub_parachain_id.into(), + ) + .unwrap(); + + // fund asset hub sovereign account enough so it can pay fees + initial_fund::(assethub_parachain_id, initial_amount); + + let outcome = send_transfer_token_message::( + assethub_parachain_id, + weth_contract_address, + destination_address, + fee_amount, + ); + // check err is NotHoldingFees + assert_err!(outcome.ensure_complete(), expected_error); + }); +} diff --git a/polkadot-sdk b/polkadot-sdk index f03fd042d4..201cdd13dd 160000 --- a/polkadot-sdk +++ b/polkadot-sdk @@ -1 +1 @@ -Subproject commit f03fd042d4f607a3530559a99f0c14d7d5b9afee +Subproject commit 201cdd13dd3fedd23c12596892d39d4ac771065f From 279dbf2d4b51d01da586ee1e5aa16a6abc41b098 Mon Sep 17 00:00:00 2001 From: ron Date: Wed, 10 Jan 2024 23:31:27 +0800 Subject: [PATCH 2/7] Fix for pallet rename --- parachain/runtime/test-common/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/parachain/runtime/test-common/src/lib.rs b/parachain/runtime/test-common/src/lib.rs index 1e0fdc59da..0f1a09a802 100644 --- a/parachain/runtime/test-common/src/lib.rs +++ b/parachain/runtime/test-common/src/lib.rs @@ -22,7 +22,7 @@ use xcm_executor::XcmExecutor; type RuntimeHelper = parachains_runtimes_test_utils::RuntimeHelper; -type TokenBalanceOf = <::Token as Inspect< +type TokenBalanceOf = <::Token as Inspect< ::AccountId, >>::Balance; @@ -42,9 +42,9 @@ where pub fn initialize_price_params(params: PricingParameters>) where - Runtime: frame_system::Config + snowbridge_system::Config + pallet_balances::Config, + Runtime: frame_system::Config + snowbridge_pallet_system::Config + pallet_balances::Config, { - snowbridge_system::PricingParameters::::put(params.clone()); + snowbridge_pallet_system::PricingParameters::::put(params.clone()); } pub fn send_transfer_token_message( @@ -326,8 +326,8 @@ pub fn send_transfer_token_message_failure_with_invalid_fee_params: From>, { @@ -345,7 +345,7 @@ pub fn send_transfer_token_message_failure_with_invalid_fee_params(params); - >::initialize( + >::initialize( runtime_para_id.into(), assethub_parachain_id.into(), ) From 7f7e4bc089bb15ad089f995d9934553e42bbaaf9 Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 11 Jan 2024 10:48:39 +0800 Subject: [PATCH 3/7] AssetTransactor::deposit_asset directly with error thrown --- parachain/pallets/system/src/tests.rs | 18 +---------- parachain/primitives/core/src/lib.rs | 4 --- parachain/runtime/runtime-common/src/lib.rs | 34 ++++++++++----------- 3 files changed, 17 insertions(+), 39 deletions(-) diff --git a/parachain/pallets/system/src/tests.rs b/parachain/pallets/system/src/tests.rs index e07481c1e3..e36cf6826e 100644 --- a/parachain/pallets/system/src/tests.rs +++ b/parachain/pallets/system/src/tests.rs @@ -3,7 +3,7 @@ use crate::{mock::*, *}; use frame_support::{assert_noop, assert_ok}; use hex_literal::hex; -use snowbridge_core::{eth, sibling_sovereign_account_raw}; +use snowbridge_core::eth; use sp_core::H256; use sp_runtime::{AccountId32, DispatchError::BadOrigin, TokenError}; @@ -551,22 +551,6 @@ fn force_transfer_native_from_agent_bad_origin() { // conversions for devops purposes. They need to be removed here and incorporated into a command // line utility. -#[ignore] -#[test] -fn check_sibling_sovereign_account() { - new_test_ext(true).execute_with(|| { - let para_id = 1001; - let sovereign_account = sibling_sovereign_account::(para_id.into()); - let sovereign_account_raw = sibling_sovereign_account_raw(para_id.into()); - println!( - "Sovereign account for parachain {}: {:#?}", - para_id, - hex::encode(sovereign_account.clone()) - ); - assert_eq!(sovereign_account, sovereign_account_raw.into()); - }); -} - #[test] fn charge_fee_for_create_agent() { new_test_ext(true).execute_with(|| { diff --git a/parachain/primitives/core/src/lib.rs b/parachain/primitives/core/src/lib.rs index ecbc3bb365..5a17aa3f0b 100644 --- a/parachain/primitives/core/src/lib.rs +++ b/parachain/primitives/core/src/lib.rs @@ -48,10 +48,6 @@ where SiblingParaId::from(para_id).into_account_truncating() } -pub fn sibling_sovereign_account_raw(para_id: ParaId) -> [u8; 32] { - SiblingParaId::from(para_id).into_account_truncating() -} - pub struct AllowSiblingsOnly; impl Contains for AllowSiblingsOnly { fn contains(location: &MultiLocation) -> bool { diff --git a/parachain/runtime/runtime-common/src/lib.rs b/parachain/runtime/runtime-common/src/lib.rs index d17ec5e2bf..c7ba59bece 100644 --- a/parachain/runtime/runtime-common/src/lib.rs +++ b/parachain/runtime/runtime-common/src/lib.rs @@ -7,10 +7,10 @@ use core::marker::PhantomData; use frame_support::{ensure, traits::Get}; -use snowbridge_core::{outbound::SendMessageFeeProvider, sibling_sovereign_account_raw}; +use snowbridge_core::outbound::SendMessageFeeProvider; use sp_arithmetic::traits::{BaseArithmetic, Unsigned}; use xcm::prelude::*; -use xcm_builder::{deposit_or_burn_fee, HandleFee}; +use xcm_builder::HandleFee; use xcm_executor::traits::{FeeReason, TransactAsset}; /// A `HandleFee` implementation that takes fees from `ExportMessage` XCM instructions @@ -68,21 +68,20 @@ impl = fees @@ -99,22 +98,21 @@ impl Balance::zero(), XcmError::FeesNotMet); // Refund remote component of fee to physical origin - deposit_or_burn_fee::( - MultiAsset { id: Concrete(token_location), fun: Fungible(remote_fee.into()) }.into(), + AssetTransactor::deposit_asset( + &MultiAsset { id: Concrete(token_location), fun: Fungible(remote_fee.into()) }, + &MultiLocation { parents: 1, interior: X1(Parachain(*para_id)) }, context, - para_sovereign, - ); + )?; + // Return remaining fee to the next fee handler in the chain. let mut modified_fees = fees.inner().clone(); modified_fees.remove(fee_index); - modified_fees.push(MultiAsset { - id: Concrete(token_location), - fun: Fungible((total_fee - remote_fee).into()), - }); + modified_fees + .push(MultiAsset { id: Concrete(token_location), fun: Fungible(local_fee.into()) }); Ok(modified_fees.into()) } } From 4ddca9caf5c131376d4b22be98f34589ce15b853 Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 11 Jan 2024 11:29:06 +0800 Subject: [PATCH 4/7] Move invalid params to test --- parachain/runtime/test-common/src/lib.rs | 21 ++++++--------------- polkadot-sdk | 2 +- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/parachain/runtime/test-common/src/lib.rs b/parachain/runtime/test-common/src/lib.rs index 0f1a09a802..c1ba8a38b2 100644 --- a/parachain/runtime/test-common/src/lib.rs +++ b/parachain/runtime/test-common/src/lib.rs @@ -10,9 +10,9 @@ pub use parachains_runtimes_test_utils::test_cases::change_storage_constant_by_g use parachains_runtimes_test_utils::{ AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, ValidatorIdOf, XcmReceivedFrom, }; -use snowbridge_core::{gwei, meth, PricingParameters, Rewards}; +use snowbridge_core::PricingParameters; use sp_core::H160; -use sp_runtime::{FixedU128, SaturatedConversion}; +use sp_runtime::SaturatedConversion; use xcm::{ latest::prelude::*, v3::Error::{self, Barrier}, @@ -40,13 +40,6 @@ where .unwrap(); } -pub fn initialize_price_params(params: PricingParameters>) -where - Runtime: frame_system::Config + snowbridge_pallet_system::Config + pallet_balances::Config, -{ - snowbridge_pallet_system::PricingParameters::::put(params.clone()); -} - pub fn send_transfer_token_message( assethub_parachain_id: u32, weth_contract_address: H160, @@ -317,6 +310,7 @@ pub fn send_transfer_token_message_failure_with_invalid_fee_params>, expected_error: Error, ) where Runtime: frame_system::Config @@ -338,13 +332,10 @@ pub fn send_transfer_token_message_failure_with_invalid_fee_params> = PricingParameters { - exchange_rate: FixedU128::from_rational(1, 400), - fee_per_gas: gwei(0), - rewards: Rewards { local: 0_u32.into(), remote: meth(0) }, - }; - initialize_price_params::(params); + // initialize price params + snowbridge_pallet_system::PricingParameters::::put(price_params); + // initialize agent and channel >::initialize( runtime_para_id.into(), assethub_parachain_id.into(), diff --git a/polkadot-sdk b/polkadot-sdk index a6f519ac78..932b1ce5ba 160000 --- a/polkadot-sdk +++ b/polkadot-sdk @@ -1 +1 @@ -Subproject commit a6f519ac789e3813aabdacd0a8930a65ab0ee3ec +Subproject commit 932b1ce5baf7cb584578a5824f68df6a17ac01e6 From 965e579047718c3f4c3d929dbbc615668a0bc57a Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 11 Jan 2024 11:34:58 +0800 Subject: [PATCH 5/7] Check more strictly --- parachain/runtime/runtime-common/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parachain/runtime/runtime-common/src/lib.rs b/parachain/runtime/runtime-common/src/lib.rs index c7ba59bece..981f42fbb0 100644 --- a/parachain/runtime/runtime-common/src/lib.rs +++ b/parachain/runtime/runtime-common/src/lib.rs @@ -100,7 +100,7 @@ impl Balance::zero(), XcmError::FeesNotMet); + ensure!(remote_fee > Balance::one(), XcmError::FeesNotMet); // Refund remote component of fee to physical origin AssetTransactor::deposit_asset( &MultiAsset { id: Concrete(token_location), fun: Fungible(remote_fee.into()) }, From 5fb402b4b618d9323ca1809136130a4bdd95d55e Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 11 Jan 2024 14:11:22 +0800 Subject: [PATCH 6/7] More tests --- parachain/Cargo.lock | 1 + parachain/runtime/runtime-common/Cargo.toml | 3 +- parachain/runtime/runtime-common/src/lib.rs | 12 +- parachain/runtime/runtime-common/src/tests.rs | 188 ++++++++++++++++++ polkadot-sdk | 2 +- 5 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 parachain/runtime/runtime-common/src/tests.rs diff --git a/parachain/Cargo.lock b/parachain/Cargo.lock index 4720ee8148..2115b1b471 100644 --- a/parachain/Cargo.lock +++ b/parachain/Cargo.lock @@ -9173,6 +9173,7 @@ dependencies = [ "frame-support", "frame-system", "log", + "parity-scale-codec", "snowbridge-core", "sp-arithmetic", "staging-xcm", diff --git a/parachain/runtime/runtime-common/Cargo.toml b/parachain/runtime/runtime-common/Cargo.toml index d3a4e9e62f..ac907bd9ff 100644 --- a/parachain/runtime/runtime-common/Cargo.toml +++ b/parachain/runtime/runtime-common/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] log = { version = "0.4.20", default-features = false } - +codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false } frame-support = { path = "../../../polkadot-sdk/substrate/frame/support", default-features = false } frame-system = { path = "../../../polkadot-sdk/substrate/frame/system", default-features = false } sp-arithmetic = { path = "../../../polkadot-sdk/substrate/primitives/arithmetic", default-features = false } @@ -28,6 +28,7 @@ snowbridge-core = { path = "../../primitives/core", default-features = false } [features] default = ["std"] std = [ + "codec/std", "frame-support/std", "frame-system/std", "log/std", diff --git a/parachain/runtime/runtime-common/src/lib.rs b/parachain/runtime/runtime-common/src/lib.rs index 981f42fbb0..4dfd0fa79d 100644 --- a/parachain/runtime/runtime-common/src/lib.rs +++ b/parachain/runtime/runtime-common/src/lib.rs @@ -5,6 +5,10 @@ //! Common traits and types shared by runtimes. #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(test)] +mod tests; + +use codec::FullCodec; use core::marker::PhantomData; use frame_support::{ensure, traits::Get}; use snowbridge_core::outbound::SendMessageFeeProvider; @@ -45,7 +49,7 @@ impl where Balance: BaseArithmetic + Unsigned + Copy + From + Into, - AccountId: Clone + Into<[u8; 32]> + From<[u8; 32]>, + AccountId: Clone + FullCodec, FeeAssetLocation: Get, EthereumNetwork: Get, AssetTransactor: TransactAsset, @@ -68,13 +72,13 @@ impl = if let Some(XcmContext { origin: Some(MultiLocation { parents: 1, interior }), .. }) = context { if let Some(Parachain(sibling_para_id)) = interior.first() { - Some(sibling_para_id) + Some(*sibling_para_id) } else { None } @@ -104,7 +108,7 @@ impl Result<(Self::Ticket, Fee), SendError> { + Ok(((), Fee { local: 1, remote: 1 })) + } + + fn deliver(_: Self::Ticket) -> Result { + Ok(H256::zero()) + } +} + +impl SendMessageFeeProvider for MockOkOutboundQueue { + type Balance = u128; + + fn local_fee() -> Self::Balance { + 1 + } +} +struct MockErrOutboundQueue; +impl SendMessage for MockErrOutboundQueue { + type Ticket = (); + + fn validate(_: &Message) -> Result<(Self::Ticket, Fee), SendError> { + Err(SendError::MessageTooLarge) + } + + fn deliver(_: Self::Ticket) -> Result { + Err(SendError::MessageTooLarge) + } +} + +impl SendMessageFeeProvider for MockErrOutboundQueue { + type Balance = u128; + + fn local_fee() -> Self::Balance { + 1 + } +} + +pub struct SuccessfulTransactor; +impl TransactAsset for SuccessfulTransactor { + fn can_check_in( + _origin: &MultiLocation, + _what: &MultiAsset, + _context: &XcmContext, + ) -> XcmResult { + Ok(()) + } + + fn can_check_out( + _dest: &MultiLocation, + _what: &MultiAsset, + _context: &XcmContext, + ) -> XcmResult { + Ok(()) + } + + fn deposit_asset( + _what: &MultiAsset, + _who: &MultiLocation, + _context: Option<&XcmContext>, + ) -> XcmResult { + Ok(()) + } + + fn withdraw_asset( + _what: &MultiAsset, + _who: &MultiLocation, + _context: Option<&XcmContext>, + ) -> Result { + Ok(Assets::default()) + } + + fn internal_transfer_asset( + _what: &MultiAsset, + _from: &MultiLocation, + _to: &MultiLocation, + _context: &XcmContext, + ) -> Result { + Ok(Assets::default()) + } +} + +pub struct NotFoundTransactor; +impl TransactAsset for NotFoundTransactor { + fn can_check_in( + _origin: &MultiLocation, + _what: &MultiAsset, + _context: &XcmContext, + ) -> XcmResult { + Err(XcmError::AssetNotFound) + } + + fn can_check_out( + _dest: &MultiLocation, + _what: &MultiAsset, + _context: &XcmContext, + ) -> XcmResult { + Err(XcmError::AssetNotFound) + } + + fn deposit_asset( + _what: &MultiAsset, + _who: &MultiLocation, + _context: Option<&XcmContext>, + ) -> XcmResult { + Err(XcmError::AssetNotFound) + } + + fn withdraw_asset( + _what: &MultiAsset, + _who: &MultiLocation, + _context: Option<&XcmContext>, + ) -> Result { + Err(XcmError::AssetNotFound) + } + + fn internal_transfer_asset( + _what: &MultiAsset, + _from: &MultiLocation, + _to: &MultiLocation, + _context: &XcmContext, + ) -> Result { + Err(XcmError::AssetNotFound) + } +} + +#[test] +fn handle_fee_success() { + let fee: MultiAssets = MultiAsset::from((MultiLocation::parent(), 10_u128)).into(); + let ctx = XcmContext { + origin: Some(MultiLocation { parents: 1, interior: X1(Parachain(1000)) }), + message_id: XcmHash::default(), + topic: None, + }; + let reason = FeeReason::Export { network: EthereumNetwork::get(), destination: Here }; + let result = XcmExportFeeToSibling::< + u128, + u64, + TokenLocation, + EthereumNetwork, + SuccessfulTransactor, + MockOkOutboundQueue, + >::handle_fee(fee, Some(&ctx), reason) + .unwrap(); + let local_fee = + MultiAsset::from((MultiLocation::parent(), MockOkOutboundQueue::local_fee())).into(); + // assert only local fee left + assert_eq!(result, local_fee) +} + +#[test] +fn handle_fee_success_but_not_for_ethereum() { + let fee: MultiAssets = MultiAsset::from((MultiLocation::parent(), 10_u128)).into(); + let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; + let reason = FeeReason::Export { network: Rococo, destination: Here }; + let result = XcmExportFeeToSibling::< + u128, + u64, + TokenLocation, + EthereumNetwork, + SuccessfulTransactor, + MockOkOutboundQueue, + >::handle_fee(fee.clone(), Some(&ctx), reason) + .unwrap(); + // assert fee not touched and just forward to the next handler + assert_eq!(result, fee) +} diff --git a/polkadot-sdk b/polkadot-sdk index 932b1ce5ba..fa290541ba 160000 --- a/polkadot-sdk +++ b/polkadot-sdk @@ -1 +1 @@ -Subproject commit 932b1ce5baf7cb584578a5824f68df6a17ac01e6 +Subproject commit fa290541baf4181cb464290332d87e7a25961575 From 3894746e9a658cdd7fa63ed3a1d4879d8e1cd970 Mon Sep 17 00:00:00 2001 From: ron Date: Thu, 11 Jan 2024 16:59:30 +0800 Subject: [PATCH 7/7] More tests --- parachain/runtime/runtime-common/src/tests.rs | 64 ++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/parachain/runtime/runtime-common/src/tests.rs b/parachain/runtime/runtime-common/src/tests.rs index ceee77fbf2..f8ee3e142a 100644 --- a/parachain/runtime/runtime-common/src/tests.rs +++ b/parachain/runtime/runtime-common/src/tests.rs @@ -2,7 +2,7 @@ use crate::XcmExportFeeToSibling; use frame_support::{parameter_types, sp_runtime::testing::H256}; use snowbridge_core::outbound::{Fee, Message, SendError, SendMessage, SendMessageFeeProvider}; use xcm::prelude::{ - Here, MultiAsset, MultiAssets, MultiLocation, NetworkId, Parachain, Rococo, XcmContext, + Here, Kusama, MultiAsset, MultiAssets, MultiLocation, NetworkId, Parachain, XcmContext, XcmError, XcmHash, XcmResult, X1, }; use xcm_builder::HandleFee; @@ -173,7 +173,8 @@ fn handle_fee_success() { fn handle_fee_success_but_not_for_ethereum() { let fee: MultiAssets = MultiAsset::from((MultiLocation::parent(), 10_u128)).into(); let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; - let reason = FeeReason::Export { network: Rococo, destination: Here }; + // invalid network not for ethereum + let reason = FeeReason::Export { network: Kusama, destination: Here }; let result = XcmExportFeeToSibling::< u128, u64, @@ -186,3 +187,62 @@ fn handle_fee_success_but_not_for_ethereum() { // assert fee not touched and just forward to the next handler assert_eq!(result, fee) } + +#[test] +fn handle_fee_fail_for_invalid_location() { + let fee: MultiAssets = MultiAsset::from((MultiLocation::parent(), 10_u128)).into(); + // invalid origin not from sibling chain + let ctx = XcmContext { origin: None, message_id: XcmHash::default(), topic: None }; + let reason = FeeReason::Export { network: EthereumNetwork::get(), destination: Here }; + let result = XcmExportFeeToSibling::< + u128, + u64, + TokenLocation, + EthereumNetwork, + SuccessfulTransactor, + MockOkOutboundQueue, + >::handle_fee(fee.clone(), Some(&ctx), reason); + assert_eq!(result, Err(XcmError::InvalidLocation)) +} + +#[test] +fn handle_fee_fail_for_fees_not_met() { + // insufficient fee not met + let fee: MultiAssets = MultiAsset::from((MultiLocation::parent(), 1_u128)).into(); + let ctx = XcmContext { + origin: Some(MultiLocation { parents: 1, interior: X1(Parachain(1000)) }), + message_id: XcmHash::default(), + topic: None, + }; + let reason = FeeReason::Export { network: EthereumNetwork::get(), destination: Here }; + let result = XcmExportFeeToSibling::< + u128, + u64, + TokenLocation, + EthereumNetwork, + SuccessfulTransactor, + MockOkOutboundQueue, + >::handle_fee(fee.clone(), Some(&ctx), reason); + assert_eq!(result, Err(XcmError::FeesNotMet)) +} + +#[test] +fn handle_fee_fail_for_transact() { + let fee: MultiAssets = MultiAsset::from((MultiLocation::parent(), 10_u128)).into(); + let ctx = XcmContext { + origin: Some(MultiLocation { parents: 1, interior: X1(Parachain(1000)) }), + message_id: XcmHash::default(), + topic: None, + }; + let reason = FeeReason::Export { network: EthereumNetwork::get(), destination: Here }; + let result = XcmExportFeeToSibling::< + u128, + u64, + TokenLocation, + EthereumNetwork, + // invalid transactor + NotFoundTransactor, + MockOkOutboundQueue, + >::handle_fee(fee.clone(), Some(&ctx), reason); + assert_eq!(result, Err(XcmError::AssetNotFound)) +}