Skip to content

Commit

Permalink
Add fee for incoming assets (#385)
Browse files Browse the repository at this point in the history
* wip first iteration

* fix modified tests

* remove UsingComponents Trader, fix pendulum integration tests with fees

* fix amplitude integration tests to account for xcm fees

* clean imports

* modification of existential deposits closure to handle native as well

* adjust valuations to base everything on native token

* fix test values for new relative values
  • Loading branch information
gianfra-t authored Jan 2, 2024
1 parent fbb86dc commit dabe1e9
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 81 deletions.
10 changes: 8 additions & 2 deletions runtime/amplitude/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,8 +776,14 @@ impl pallet_child_bounties::Config for Runtime {
}

parameter_type_with_key! {
pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance {
NANOUNIT
pub ExistentialDeposits: |currency_id: CurrencyId| -> Balance {
// Since the xcm trader uses Tokens to get the minimum
// balance of both it's assets and native, we need to
// handle native here
match currency_id{
CurrencyId::Native => EXISTENTIAL_DEPOSIT,
_ => NANOUNIT
}
};
}

Expand Down
106 changes: 96 additions & 10 deletions runtime/amplitude/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::marker::PhantomData;
use frame_support::{
log, match_types, parameter_types,
traits::{ContainsPair, Everything, Nothing},
weights::{Weight, WeightToFee as WeightToFeeTrait},
};
use orml_traits::{
location::{RelativeReserveProvider, Reserve},
Expand All @@ -11,18 +12,26 @@ use orml_traits::{
use orml_xcm_support::{DepositToAlternative, IsNativeConcrete, MultiCurrencyAdapter};
use pallet_xcm::XcmPassthrough;
use polkadot_parachain::primitives::Sibling;
use polkadot_runtime_common::impls::ToAuthor;
use sp_runtime::traits::Convert;
use xcm::latest::{prelude::*, Weight as XCMWeight};
use xcm_builder::{
AccountId32Aliases, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds,
ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, UsingComponents,
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, ConvertedConcreteId, EnsureXcmOrigin,
FixedWeightBounds, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit,
};
use xcm_executor::{
traits::{JustTry, ShouldExecute},
XcmExecutor,
};
use xcm_executor::{traits::ShouldExecute, XcmExecutor};

use runtime_common::parachains::kusama::asset_hub;

use cumulus_primitives_utility::{
ChargeWeightInFungibles, TakeFirstAssetTrader, XcmFeesTo32ByteAccount,
};

use crate::{
assets::{
native_locations::{native_location_external_pov, native_location_local_pov},
Expand All @@ -33,8 +42,8 @@ use crate::{

use super::{
AccountId, AmplitudeTreasuryAccount, Balance, Balances, Currencies, CurrencyId, ParachainInfo,
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee,
XcmpQueue,
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, Tokens,
WeightToFee, XcmpQueue,
};

parameter_types! {
Expand Down Expand Up @@ -104,6 +113,38 @@ impl Convert<MultiAsset, Option<CurrencyId>> for CurrencyIdConvert {
}
}

pub struct RelativeValue {
num: Balance,
denominator: Balance,
}

impl RelativeValue {
fn adjust_amount_by_relative_value(amount: Balance, relative_value: RelativeValue) -> Balance {
if relative_value.denominator == 0 {
// Or probably error
return amount
}
// Calculate the adjusted amount
let adjusted_amount = amount * relative_value.denominator / relative_value.num;
adjusted_amount
}
}

pub struct RelayRelativeValue;
impl RelayRelativeValue {
fn get_relative_value(id: CurrencyId) -> Option<RelativeValue> {
match id {
CurrencyId::XCM(index) => match index {
xcm_assets::RELAY_KSM => Some(RelativeValue { num: 100, denominator: 1 }),
xcm_assets::ASSETHUB_USDT => Some(RelativeValue { num: 20, denominator: 4 }),
_ => None,
},
CurrencyId::Native => Some(RelativeValue { num: 1, denominator: 1 }),
_ => Some(RelativeValue { num: 1, denominator: 1 }),
}
}
}

/// Convert an incoming `MultiLocation` into a `CurrencyId` if possible.
/// Here we need to know the canonical representation of all the tokens we handle in order to
/// correctly convert their `MultiLocation` representation into our internal `CurrencyId` type.
Expand Down Expand Up @@ -244,7 +285,53 @@ impl ShouldExecute for DenyReserveTransferToRelayChain {
}
}

pub type Barrier = AllowUnpaidExecutionFrom<Everything>;
match_types! {
pub type ParentOrParentsPlurality: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: Here } |
MultiLocation { parents: 1, interior: X1(Plurality { .. }) }
};
}

pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
// Parent and its plurality get free execution
AllowUnpaidExecutionFrom<ParentOrParentsPlurality>,
// Expected responses are OK.
AllowKnownQueryResponses<PolkadotXcm>,
// Subscriptions for version tracking are OK.
AllowSubscriptionsFrom<Everything>,
);

pub struct ChargeWeightInFungiblesImplementation;
impl ChargeWeightInFungibles<AccountId, Tokens> for ChargeWeightInFungiblesImplementation {
fn charge_weight_in_fungibles(
asset_id: CurrencyId,
weight: Weight,
) -> Result<Balance, XcmError> {
let amount = <WeightToFee as WeightToFeeTrait>::weight_to_fee(&weight);

if let Some(relative_value) = RelayRelativeValue::get_relative_value(asset_id) {
let adjusted_amount =
RelativeValue::adjust_amount_by_relative_value(amount, relative_value);
log::info!("amount to be charged: {:?} in asset: {:?}", adjusted_amount, asset_id);
return Ok(adjusted_amount)
} else {
log::info!("amount to be charged: {:?} in asset: {:?}", amount, asset_id);
return Ok(amount)
}
}
}

pub type Traders = (
TakeFirstAssetTrader<
AccountId,
ChargeWeightInFungiblesImplementation,
ConvertedConcreteId<CurrencyId, Balance, CurrencyIdConvert, JustTry>,
Tokens,
XcmFeesTo32ByteAccount<LocalAssetTransactor, AccountId, AmplitudeTreasuryAccount>,
>,
);

pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
Expand All @@ -259,8 +346,7 @@ impl xcm_executor::Config for XcmConfig {
type UniversalLocation = UniversalLocation;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, RuntimeCall, MaxInstructions>;
type Trader =
UsingComponents<WeightToFee, RelayLocation, AccountId, Balances, ToAuthor<Runtime>>;
type Trader = Traders;
type ResponseHandler = PolkadotXcm;
type AssetTrap = PolkadotXcm;
type AssetLocker = ();
Expand Down
18 changes: 2 additions & 16 deletions runtime/common/src/custom_transactor.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
use sp_runtime::{
codec::FullCodec,
traits::{Convert, MaybeSerializeDeserialize, SaturatedConversion},
};
use sp_std::{
cmp::{Eq, PartialEq},
fmt::Debug,
marker::PhantomData,
prelude::*,
result,
};
use sp_std::{marker::PhantomData, result};

use orml_xcm_support::{OnDepositFail, UnknownAsset as UnknownAssetT};
use xcm::v3::{prelude::*, Error as XcmError, MultiAsset, MultiLocation, Result};
use xcm_executor::{
traits::{Convert as MoreConvert, MatchesFungible, TransactAsset},
Assets,
};
use xcm_executor::{traits::TransactAsset, Assets};

pub struct AssetData {
pub length: u8,
Expand Down
10 changes: 8 additions & 2 deletions runtime/foucoco/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,8 +781,14 @@ impl pallet_child_bounties::Config for Runtime {
}

parameter_type_with_key! {
pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance {
NANOUNIT
pub ExistentialDeposits: |currency_id: CurrencyId| -> Balance {
// Since the xcm trader uses Tokens to get the minimum
// balance of both it's assets and native, we need to
// handle native here
match currency_id{
CurrencyId::Native => EXISTENTIAL_DEPOSIT,
_ => NANOUNIT
}
};
}

Expand Down
16 changes: 10 additions & 6 deletions runtime/integration-tests/src/amplitude_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use crate::{
mock::{kusama_relay_ext, para_ext, ParachainType, USDT_ASSET_ID},
sibling,
test_macros::{
moonbeam_transfers_token_and_handle_automation, parachain1_transfer_asset_to_parachain2,
parachain1_transfer_asset_to_parachain2_and_back,
parachain1_transfer_asset_to_parachain2, parachain1_transfer_asset_to_parachain2_and_back,
parachain1_transfer_incorrect_asset_to_parachain2_should_fail,
transfer_10_relay_token_from_parachain_to_relay_chain,
transfer_20_relay_token_from_relay_chain_to_parachain,
Expand All @@ -17,7 +16,9 @@ use statemine_runtime as kusama_asset_hub_runtime;
use xcm::latest::NetworkId;
use xcm_emulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt};

const KSM_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 3200000000;
const KSM_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 32000000;
const USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 640000000;
const NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 3200000000;

decl_test_relay_chain! {
pub struct KusamaRelay {
Expand Down Expand Up @@ -111,7 +112,8 @@ fn assethub_transfer_asset_to_amplitude() {
USDT_ASSET_ID,
amplitude_runtime,
AmplitudeParachain,
AMPLITUDE_ID
AMPLITUDE_ID,
USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN
);
}

Expand All @@ -127,7 +129,8 @@ fn assethub_transfer_asset_to_amplitude_and_back() {
amplitude_runtime,
AmplitudeParachain,
AMPLITUDE_ID,
network_id
network_id,
USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN
);
}

Expand All @@ -140,6 +143,7 @@ fn transfer_native_token_from_amplitude_to_sibling_parachain_and_back() {
sibling,
SiblingParachain,
AMPLITUDE_ID,
SIBLING_ID
SIBLING_ID,
NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN
);
}
17 changes: 12 additions & 5 deletions runtime/integration-tests/src/pendulum_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use statemint_runtime as polkadot_asset_hub_runtime;
use xcm::latest::NetworkId;
use xcm_emulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt};

const DOT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 3200000000; //The fees that relay chain will charge when transfer DOT to parachain. sovereign account of some parachain will receive transfer_amount - DOT_FEE
const DOT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 32653061; //The fees that relay chain will charge when transfer DOT to parachain. sovereign account of some parachain will receive transfer_amount - DOT_FEE
const MOONBEAM_BRZ_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 1391304347; //Fees that we will charge in incoming Moonbeam's BRZ. Depends on the RelativeValue struct implementation.
const USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 266666666;
const NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN: polkadot_core_primitives::Balance = 3200000000;

decl_test_relay_chain! {
pub struct PolkadotRelay {
Expand Down Expand Up @@ -123,7 +126,8 @@ fn assethub_transfer_asset_to_pendulum() {
USDT_ASSET_ID,
pendulum_runtime,
PendulumParachain,
PENDULUM_ID
PENDULUM_ID,
USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN
);
}

Expand All @@ -139,7 +143,8 @@ fn assethub_transfer_asset_to_pendulum_and_back() {
pendulum_runtime,
PendulumParachain,
PENDULUM_ID,
network_id
network_id,
USDT_FEE_WHEN_TRANSFER_TO_PARACHAIN
);
}

Expand All @@ -152,7 +157,8 @@ fn transfer_native_token_from_pendulum_to_sibling_parachain_and_back() {
sibling,
SiblingParachain,
PENDULUM_ID,
SIBLING_ID
SIBLING_ID,
NATIVE_FEE_WHEN_TRANSFER_TO_PARACHAIN
);
}

Expand All @@ -165,6 +171,7 @@ fn moonbeam_transfers_token_and_handle_automation() {
sibling,
MoonbeamParachain,
PENDULUM_ID,
MOONBEAM_PARA_ID
MOONBEAM_PARA_ID,
MOONBEAM_BRZ_FEE_WHEN_TRANSFER_TO_PARACHAIN
);
}
Loading

0 comments on commit dabe1e9

Please sign in to comment.