Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions runtime/moonriver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ log = "0.4"
rlp = { version = "0.5", optional = true, default-features = false }
serde = { version = "1.0.101", optional = true, default-features = false, features = [ "derive" ] }
sha3 = { version = "0.8", optional = true, default-features = false }
smallvec = "1.8.0"

# Moonbeam
account = { path = "../../primitives/account/", default-features = false }
Expand Down
102 changes: 92 additions & 10 deletions runtime/moonriver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ use frame_support::{
},
weights::{
constants::{RocksDbWeight, WEIGHT_PER_SECOND},
DispatchClass, GetDispatchInfo, IdentityFee, Weight,
DispatchClass, GetDispatchInfo, IdentityFee, Weight, WeightToFeeCoefficient,
WeightToFeeCoefficients, WeightToFeePolynomial,
},
PalletId,
};
Expand Down Expand Up @@ -82,16 +83,18 @@ use sp_std::{convert::TryFrom, prelude::*};

use xcm_builder::{
AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, ConvertedConcreteAssetId, EnsureXcmOrigin, FixedWeightBounds,
FungiblesAdapter, LocationInverter, ParentIsDefault, RelayChainAsNative,
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountKey20AsNative,
SovereignSignedViaLocation, TakeWeightCredit,
AllowTopLevelPaidExecutionFrom, ConvertedConcreteAssetId,
CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter,
LocationInverter, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountKey20AsNative, SovereignSignedViaLocation,
TakeWeightCredit, UsingComponents,
};

use xcm_executor::traits::JustTry;

use xcm::latest::prelude::*;

use smallvec::smallvec;
use xcm_primitives::{
AccountIdToCurrencyId, AccountIdToMultiLocation, AsAssetType, FirstAssetTrader,
MultiNativeAsset, SignedToAccountId20, UtilityAvailableCalls, UtilityEncodeCall, XcmTransact,
Expand Down Expand Up @@ -132,6 +135,7 @@ pub mod currency {

pub const TRANSACTION_BYTE_FEE: Balance = 10 * MICROMOVR * SUPPLY_FACTOR;
pub const STORAGE_BYTE_FEE: Balance = 100 * MICROMOVR * SUPPLY_FACTOR;
pub const WEIGHT_FEE: Balance = 50 * KILOWEI * SUPPLY_FACTOR;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do some basic testing to ensure this is reasonable for your use case. It appears to be taken from #1218, which is still a WIP.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right in the sense that a token transfer through XCM would cost 50_000_000_000_000, or essentially, 50microMOVR. Maybe this is too low since for KSM we are charging 0.1KSM. I will increase it to match it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I increased it to 100KILOWEI. This means that for 1e9 weight (roughly, the amount needed for a token transfer in XCM) we charge 0.1milliMOVR, which I think gets us closer to what we charge for other assets


pub const fn deposit(items: u32, bytes: u32) -> Balance {
items as Balance * 1 * MOVR * SUPPLY_FACTOR + (bytes as Balance) * STORAGE_BYTE_FEE
Expand Down Expand Up @@ -316,6 +320,28 @@ parameter_types! {
pub OperationalFeeMultiplier: u8 = 5;
}

pub struct WeightToFee;
impl WeightToFeePolynomial for WeightToFee {
type Balance = Balance;

/// Return a vec of coefficients. Here we just use one coefficient and reduce it to a constant
/// modifier in order to closely match Ethereum-based fees.
///
/// Calculation, per the documentation in `frame_support`:
///
/// ```ignore
/// coeff_integer * x^(degree) + coeff_frac * x^(degree)
/// ```
fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
smallvec![WeightToFeeCoefficient {
degree: 1,
coeff_frac: Perbill::zero(),
coeff_integer: currency::WEIGHT_FEE,
negative: false,
}]
}
}

impl pallet_transaction_payment::Config for Runtime {
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees<Runtime>>;
type TransactionByteFee = TransactionByteFee;
Expand Down Expand Up @@ -949,10 +975,11 @@ parameter_types! {
pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
// The ancestry, defines the multilocation describing this consensus system
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
// Self Reserve location, defines the multilocation identifiying the self-reserve currency
// Old Self Reserve location, defines the multilocation identifiying the self-reserve currency
// This is used to match it against our Balances pallet when we receive such a MultiLocation
// (Parent, Self Para Id, Self Balances pallet index)
pub SelfReserve: MultiLocation = MultiLocation {
// This is the old anchoring way
pub OldAnchoringSelfReserve: MultiLocation = MultiLocation {
parents:1,
interior: Junctions::X2(
Parachain(ParachainInfo::parachain_id().into()),
Expand All @@ -961,6 +988,23 @@ parameter_types! {
)
)
};
// Bew Self Reserve location, defines the multilocation identifiying the self-reserve currency
// This is used to match it also against our Balances pallet when we receive such
// a MultiLocation: (Self Balances pallet index)
// This is the new anchoring way
pub NewAnchoringSelfReserve: MultiLocation = MultiLocation {
parents:0,
interior: Junctions::X1(
PalletInstance(<Runtime as frame_system::Config>::PalletInfo::index::<Balances>().unwrap() as u8)
)
};

// The Locations we accept to refer to our own currency. We need to support both pre and
// post 0.9.16 versions, hence the reason for this being a Vec
pub SelfReserveRepresentations: Vec<MultiLocation> = vec![
OldAnchoringSelfReserve::get(),
NewAnchoringSelfReserve::get()
];
}

/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
Expand Down Expand Up @@ -999,10 +1043,24 @@ pub type FungiblesTransactor = FungiblesAdapter<
(),
>;

pub type LocalAssetTransactor = XcmCurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching any of the locations in
// SelfReserveRepresentations
xcm_primitives::MultiIsConcrete<SelfReserveRepresentations>,
// We can convert the MultiLocations with our converter above:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We dont allow teleport
(),
>;

// We use only fungiblesAdapter transactor for now
// The idea is that we only accept the relay token, hence no need to handle the local token
// As long as this does not contain the local transactor, we are good
pub type AssetTransactors = FungiblesTransactor;
pub type AssetTransactors = (LocalAssetTransactor, FungiblesTransactor);

/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
Expand Down Expand Up @@ -1079,9 +1137,28 @@ impl xcm_executor::Config for XcmExecutorConfig {
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = XcmBarrier;
type Weigher = XcmWeigher;
// We use three traders
// When we receive either representation of the self-reserve asset,
// we use UsingComponents and the local way of handling fees
// When we receive a non-reserve asset, we use AssetManager to fetch how many
// units per second we should charge
type Trader = FirstAssetTrader<AssetType, AssetManager, XcmFeesToAccount>;
type Trader = (
UsingComponents<
WeightToFee,
OldAnchoringSelfReserve,
AccountId,
Balances,
DealWithFees<Runtime>,
>,
UsingComponents<
WeightToFee,
NewAnchoringSelfReserve,
AccountId,
Balances,
DealWithFees<Runtime>,
>,
FirstAssetTrader<AssetType, AssetManager, XcmFeesToAccount>,
);
type ResponseHandler = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
type AssetTrap = PolkadotXcm;
Expand Down Expand Up @@ -1355,8 +1432,13 @@ where
{
fn convert(currency: CurrencyId) -> Option<MultiLocation> {
match currency {
// For now (and until we upgrade to 0.9.16 is adapted) we need to use the old anchoring
// here
// This is not a problem in either cases, since the view of the destination chain
// does not change
// TODO! change this to NewAnchoringSelfReserve once we uprade to 0.9.16
CurrencyId::SelfReserve => {
let multi: MultiLocation = SelfReserve::get();
let multi: MultiLocation = OldAnchoringSelfReserve::get();
Some(multi)
}
CurrencyId::OtherReserve(asset) => AssetXConverter::reverse_ref(asset).ok(),
Expand Down
1 change: 1 addition & 0 deletions runtime/moonriver/tests/xcm_mock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,4 @@ pub type XTokens = orml_xtokens::Pallet<parachain::Runtime>;
pub type RelayBalances = pallet_balances::Pallet<relay_chain::Runtime>;
pub type ParaBalances = pallet_balances::Pallet<parachain::Runtime>;
pub type XcmTransactor = xcm_transactor::Pallet<parachain::Runtime>;
pub type ParachainPalletXcm = pallet_xcm::Pallet<parachain::Runtime>;
73 changes: 66 additions & 7 deletions runtime/moonriver/tests/xcm_mock/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ use xcm::latest::{
};
use xcm_builder::{
AccountKey20Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, ConvertedConcreteAssetId, EnsureXcmOrigin, FixedWeightBounds,
AllowTopLevelPaidExecutionFrom, ConvertedConcreteAssetId,
CurrencyAdapter as XcmCurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds,
FungiblesAdapter, LocationInverter, ParentAsSuperuser, ParentIsDefault, RelayChainAsNative,
SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountKey20AsNative,
SovereignSignedViaLocation, TakeWeightCredit,
Expand Down Expand Up @@ -197,8 +198,22 @@ pub type FungiblesTransactor = FungiblesAdapter<
(),
>;

pub type LocalAssetTransactor = XcmCurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching any of the locations in
// SelfReserveRepresentations
xcm_primitives::MultiIsConcrete<SelfReserveRepresentations>,
// We can convert the MultiLocations with our converter above:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We dont allow teleport
(),
>;

// These will be our transactors
pub type AssetTransactors = FungiblesTransactor;
pub type AssetTransactors = (LocalAssetTransactor, FungiblesTransactor);
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;

pub type Barrier = (
Expand Down Expand Up @@ -233,20 +248,51 @@ pub type XcmFeesToAccount_ = xcm_primitives::XcmFeesToAccount<
parameter_types! {
// We cannot skip the native trader for some specific tests, so we will have to work with
// a native trader that charges same number of units as weight
pub ParaTokensPerSecond: (XcmAssetId, u128) = (Concrete(SelfReserve::get()), 1000000000000);
// We use both the old and new anchoring logics
pub ParaTokensPerSecondOld: (XcmAssetId, u128) = (
Concrete(OldAnchoringSelfReserve::get()),
1000000000000
);
pub ParaTokensPerSecondNew: (XcmAssetId, u128) = (
Concrete(NewAnchoringSelfReserve::get()),
1000000000000
);
}

parameter_types! {
pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
pub Ancestry: MultiLocation = Parachain(MsgQueue::parachain_id().into()).into();
pub SelfReserve: MultiLocation = MultiLocation {
// Old Self Reserve location, defines the multilocation identifiying the self-reserve currency
// This is used to match it against our Balances pallet when we receive such a MultiLocation
// (Parent, Self Para Id, Self Balances pallet index)
pub OldAnchoringSelfReserve: MultiLocation = MultiLocation {
parents:1,
interior: Junctions::X2(
Parachain(MsgQueue::parachain_id().into()),
PalletInstance(<Runtime as frame_system::Config>::PalletInfo::index::<Balances>().unwrap() as u8)
PalletInstance(
<Runtime as frame_system::Config>::PalletInfo::index::<Balances>().unwrap() as u8
)
)
};
// Bew Self Reserve location, defines the multilocation identifiying the self-reserve currency
// This is used to match it also against our Balances pallet when we receive such
// a MultiLocation: (Self Balances pallet index)
// This is the new anchoring way
pub NewAnchoringSelfReserve: MultiLocation = MultiLocation {
parents:0,
interior: Junctions::X1(
PalletInstance(
<Runtime as frame_system::Config>::PalletInfo::index::<Balances>().unwrap() as u8
)
)
};
// The Locations we accept to refer to our own currency. We need to support both pre and
// post 0.9.16 versions, hence the reason for this being a Vec
pub SelfReserveRepresentations: Vec<MultiLocation> = vec![
OldAnchoringSelfReserve::get(),
NewAnchoringSelfReserve::get()
];
}
pub struct XcmConfig;
impl Config for XcmConfig {
Expand All @@ -259,7 +305,15 @@ impl Config for XcmConfig {
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
type Trader = (xcm_primitives::FirstAssetTrader<AssetType, AssetManager, XcmFeesToAccount_>,);
// We use three traders
// When we receive either representation of the self-reserve asset,
// When we receive a non-reserve asset, we use AssetManager to fetch how many
// units per second we should charge
type Trader = (
FixedRateOfFungible<ParaTokensPerSecondOld, ()>,
FixedRateOfFungible<ParaTokensPerSecondNew, ()>,
xcm_primitives::FirstAssetTrader<AssetType, AssetManager, XcmFeesToAccount_>,
);

type ResponseHandler = PolkadotXcm;
type SubscriptionService = PolkadotXcm;
Expand Down Expand Up @@ -289,7 +343,12 @@ where
fn convert(currency: CurrencyId) -> Option<MultiLocation> {
match currency {
CurrencyId::SelfReserve => {
let multi: MultiLocation = SelfReserve::get();
// For now (and until we upgrade to 0.9.16 is adapted) we need to use
// the old anchoring here
// This is not a problem in either cases, since the view of the destination
// chain does not change
// TODO! change this to NewAnchoringSelfReserve once we uprade to 0.9.16
let multi: MultiLocation = OldAnchoringSelfReserve::get();
Some(multi)
}
CurrencyId::OtherReserve(asset) => AssetXConverter::reverse_ref(asset).ok(),
Expand Down
Loading