From 1f831194eb0b5f23a1f943db091445c09d4b55d3 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Tue, 26 Aug 2025 10:37:22 +0200 Subject: [PATCH 1/5] add local fee to XcmFeePrarams --- porteer/src/benchmarking.rs | 2 +- porteer/src/lib.rs | 5 +++++ porteer/src/tests.rs | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/porteer/src/benchmarking.rs b/porteer/src/benchmarking.rs index e44dadae..db6969a9 100644 --- a/porteer/src/benchmarking.rs +++ b/porteer/src/benchmarking.rs @@ -49,7 +49,7 @@ benchmarks! { assert_eq!(LastHeartBeat::::get(), now); } set_xcm_fee_params { - let fee_params = XcmFeeParams { hop1: 1u32.into(), hop2: 2u32.into(), hop3: 3u32.into() }; + let fee_params = XcmFeeParams { local: 6u32.into(), hop1: 1u32.into(), hop2: 2u32.into(), hop3: 3u32.into() }; }: _(RawOrigin::Root, fee_params) verify { assert_eq!(XcmFeeConfig::::get(), fee_params); diff --git a/porteer/src/lib.rs b/porteer/src/lib.rs index a4396cc9..4242cb14 100644 --- a/porteer/src/lib.rs +++ b/porteer/src/lib.rs @@ -112,8 +112,13 @@ pub mod pallet { /// or /// 2. AHP -> AHK -> IK pub struct XcmFeeParams { + /// to be paid by the `port_tokens` caller to cover all subsequent fees + pub local: Balance, + /// fees to be paid by sovereign account for source side Asset Hub execution involving swapping to KSM/DOT [TEER] pub hop1: Balance, + /// fees to be paid by sovereign account for destination side Asset Hub execution involving swapping to DOT/KSM [KSM/DOT] pub hop2: Balance, + /// fees to be paid by sovereign account for destination side Integritee execution involving swapping to TEER [DOT/KSM] pub hop3: Balance, } diff --git a/porteer/src/tests.rs b/porteer/src/tests.rs index 38ce88b5..3bdd3b31 100644 --- a/porteer/src/tests.rs +++ b/porteer/src/tests.rs @@ -121,7 +121,7 @@ fn set_xcm_fee_params_works() { assert_eq!(XcmFeeConfig::::get(), XcmFeeParams::default()); - let new_fee_params = XcmFeeParams { hop1: 1, hop2: 2, hop3: 3 }; + let new_fee_params = XcmFeeParams { local: 6, hop1: 1, hop2: 2, hop3: 3 }; assert_ok!(Porteer::set_xcm_fee_params( RuntimeOrigin::signed(alice.clone()), new_fee_params From 09f6a67050b2928351819cae90420bbf6b847465 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Tue, 26 Aug 2025 11:36:09 +0200 Subject: [PATCH 2/5] charge fees and unit test --- porteer/src/lib.rs | 9 +++++++++ porteer/src/mock.rs | 2 ++ porteer/src/tests.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/porteer/src/lib.rs b/porteer/src/lib.rs index 4242cb14..2deb7484 100644 --- a/porteer/src/lib.rs +++ b/porteer/src/lib.rs @@ -153,6 +153,7 @@ pub mod pallet { Location = Self::Location, >; + type FeeCollectorAccount: Get>; /// The location representation used by this pallet. type Location: Parameter + Member + MaybeSerializeDeserialize + Debug + Ord + MaxEncodedLen; @@ -386,6 +387,14 @@ pub mod pallet { return Err(Error::::WatchdogHeartbeatIsTooOld.into()); }; + let user_fee = Self::xcm_fee_config().local; + >::transfer( + &signer, + &T::FeeCollectorAccount::get(), + user_fee, + Preservation::Preserve, + )?; + >::burn_from( &signer, amount, diff --git a/porteer/src/mock.rs b/porteer/src/mock.rs index 067ba909..286b24ed 100644 --- a/porteer/src/mock.rs +++ b/porteer/src/mock.rs @@ -82,6 +82,7 @@ impl pallet_balances::Config for Test { ord_parameter_types! { pub const Alice: AccountId = AccountId::new(hex2array!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d")); + pub const Ferdie: AccountId = AccountId::new(hex2array!("1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c")); } parameter_types! { @@ -106,6 +107,7 @@ impl crate::Config for Test { EitherOfDiverse, EnsureRoot>; type PortTokensToDestination = MockPortTokens; type ForwardPortedTokensToDestinations = MockPortTokens; + type FeeCollectorAccount = Ferdie; type Location = TestLocation; type Fungible = Balances; #[cfg(feature = "runtime-benchmarks")] diff --git a/porteer/src/tests.rs b/porteer/src/tests.rs index 3bdd3b31..47e8bf32 100644 --- a/porteer/src/tests.rs +++ b/porteer/src/tests.rs @@ -259,6 +259,32 @@ fn port_tokens_works_at_timeout_threshold() { }) } +#[test] +fn port_tokens_charges_fees_if_port_possible() { + new_test_ext().execute_with(|| { + let alice = Keyring::Alice.to_account_id(); + let bob = Keyring::Bob.to_account_id(); + let ferdie = Keyring::Ferdie.to_account_id(); + let bob_free: BalanceOf = 15_000_000_000_000u128; + ::Fungible::make_free_balance_be(&bob, bob_free); + ::Fungible::make_free_balance_be(&ferdie, 0); + + assert_eq!(XcmFeeConfig::::get(), XcmFeeParams::default()); + + let new_fee_params = XcmFeeParams { local: 600_000_000_000, hop1: 1, hop2: 2, hop3: 3 }; + assert_ok!(Porteer::set_xcm_fee_params( + RuntimeOrigin::signed(alice.clone()), + new_fee_params + )); + + let port_amount: BalanceOf = 10_000_000_000_000u128; + + assert_ok!(Porteer::port_tokens(RuntimeOrigin::signed(bob.clone()), port_amount, None)); + assert_eq!(Balances::free_balance(bob), bob_free - port_amount - new_fee_params.local); + assert_eq!(Balances::free_balance(ferdie), new_fee_params.local); + }) +} + #[test] fn port_tokens_system_test_works() { // This test tests the whole logic: From d9b52e72914dccf0942160aadeb1b27f34b2f570 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Tue, 26 Aug 2025 13:48:15 +0200 Subject: [PATCH 3/5] rename field for clarity --- porteer/src/lib.rs | 4 ++-- porteer/src/tests.rs | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/porteer/src/lib.rs b/porteer/src/lib.rs index 2deb7484..e23b9063 100644 --- a/porteer/src/lib.rs +++ b/porteer/src/lib.rs @@ -113,7 +113,7 @@ pub mod pallet { /// 2. AHP -> AHK -> IK pub struct XcmFeeParams { /// to be paid by the `port_tokens` caller to cover all subsequent fees - pub local: Balance, + pub local_equivalent_sum: Balance, /// fees to be paid by sovereign account for source side Asset Hub execution involving swapping to KSM/DOT [TEER] pub hop1: Balance, /// fees to be paid by sovereign account for destination side Asset Hub execution involving swapping to DOT/KSM [KSM/DOT] @@ -387,7 +387,7 @@ pub mod pallet { return Err(Error::::WatchdogHeartbeatIsTooOld.into()); }; - let user_fee = Self::xcm_fee_config().local; + let user_fee = Self::xcm_fee_config().local_equivalent_sum; >::transfer( &signer, &T::FeeCollectorAccount::get(), diff --git a/porteer/src/tests.rs b/porteer/src/tests.rs index 47e8bf32..641cc281 100644 --- a/porteer/src/tests.rs +++ b/porteer/src/tests.rs @@ -121,7 +121,7 @@ fn set_xcm_fee_params_works() { assert_eq!(XcmFeeConfig::::get(), XcmFeeParams::default()); - let new_fee_params = XcmFeeParams { local: 6, hop1: 1, hop2: 2, hop3: 3 }; + let new_fee_params = XcmFeeParams { local_equivalent_sum: 6, hop1: 1, hop2: 2, hop3: 3 }; assert_ok!(Porteer::set_xcm_fee_params( RuntimeOrigin::signed(alice.clone()), new_fee_params @@ -271,7 +271,8 @@ fn port_tokens_charges_fees_if_port_possible() { assert_eq!(XcmFeeConfig::::get(), XcmFeeParams::default()); - let new_fee_params = XcmFeeParams { local: 600_000_000_000, hop1: 1, hop2: 2, hop3: 3 }; + let new_fee_params = + XcmFeeParams { local_equivalent_sum: 600_000_000_000, hop1: 1, hop2: 2, hop3: 3 }; assert_ok!(Porteer::set_xcm_fee_params( RuntimeOrigin::signed(alice.clone()), new_fee_params @@ -280,8 +281,11 @@ fn port_tokens_charges_fees_if_port_possible() { let port_amount: BalanceOf = 10_000_000_000_000u128; assert_ok!(Porteer::port_tokens(RuntimeOrigin::signed(bob.clone()), port_amount, None)); - assert_eq!(Balances::free_balance(bob), bob_free - port_amount - new_fee_params.local); - assert_eq!(Balances::free_balance(ferdie), new_fee_params.local); + assert_eq!( + Balances::free_balance(bob), + bob_free - port_amount - new_fee_params.local_equivalent_sum + ); + assert_eq!(Balances::free_balance(ferdie), new_fee_params.local_equivalent_sum); }) } From bf3c76145609a0035daabc0e3a6d85b2cf932893 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Tue, 26 Aug 2025 13:50:06 +0200 Subject: [PATCH 4/5] compact encoding for fee config --- porteer/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/porteer/src/lib.rs b/porteer/src/lib.rs index e23b9063..0925687c 100644 --- a/porteer/src/lib.rs +++ b/porteer/src/lib.rs @@ -113,12 +113,16 @@ pub mod pallet { /// 2. AHP -> AHK -> IK pub struct XcmFeeParams { /// to be paid by the `port_tokens` caller to cover all subsequent fees + #[codec(compact)] pub local_equivalent_sum: Balance, /// fees to be paid by sovereign account for source side Asset Hub execution involving swapping to KSM/DOT [TEER] + #[codec(compact)] pub hop1: Balance, /// fees to be paid by sovereign account for destination side Asset Hub execution involving swapping to DOT/KSM [KSM/DOT] + #[codec(compact)] pub hop2: Balance, /// fees to be paid by sovereign account for destination side Integritee execution involving swapping to TEER [DOT/KSM] + #[codec(compact)] pub hop3: Balance, } From dd4d219c03226a5d1c3911c2d0958e33ada308c3 Mon Sep 17 00:00:00 2001 From: Alain Brenzikofer Date: Tue, 26 Aug 2025 13:53:39 +0200 Subject: [PATCH 5/5] fix benchmarks --- porteer/src/benchmarking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/porteer/src/benchmarking.rs b/porteer/src/benchmarking.rs index db6969a9..5e2375b8 100644 --- a/porteer/src/benchmarking.rs +++ b/porteer/src/benchmarking.rs @@ -49,7 +49,7 @@ benchmarks! { assert_eq!(LastHeartBeat::::get(), now); } set_xcm_fee_params { - let fee_params = XcmFeeParams { local: 6u32.into(), hop1: 1u32.into(), hop2: 2u32.into(), hop3: 3u32.into() }; + let fee_params = XcmFeeParams { local_equivalent_sum: 6u32.into(), hop1: 1u32.into(), hop2: 2u32.into(), hop3: 3u32.into() }; }: _(RawOrigin::Root, fee_params) verify { assert_eq!(XcmFeeConfig::::get(), fee_params);