Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Statemint Reserve Asset Transfer #552

Merged
merged 23 commits into from
Oct 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f136467
add AssetId type alias in statemint-common
apopiak Jul 20, 2021
dc61f89
add FungiblesAdapter to allow for asset transactions via XCM
apopiak Jul 20, 2021
4dac01d
use custom Polkadot
apopiak Jul 20, 2021
a5c468e
fix FungiblesAdapter usage and add CheckingAccount
apopiak Jul 20, 2021
64d0fd9
update deps
apopiak Jul 20, 2021
8233057
remove polkadot overrides
apopiak Jul 27, 2021
dd089ee
Merge branch 'master' of github.com:paritytech/cumulus into apopiak/r…
apopiak Jul 27, 2021
388d6aa
update deps
apopiak Jul 27, 2021
7729b04
Merge branch 'master' of github.com:paritytech/cumulus into apopiak/r…
apopiak Aug 1, 2021
ea632c8
pull NonZeroIssuance struct into common + add FungiblesTransactor to …
apopiak Aug 16, 2021
222972d
Merge branch 'master' of github.com:paritytech/cumulus into apopiak/r…
apopiak Aug 17, 2021
daa2991
Merge branch 'master' of github.com:paritytech/cumulus into apopiak/r…
apopiak Aug 19, 2021
af3ced3
remove unnecessary tuple wrapping + adjust asset transactor comments
apopiak Aug 19, 2021
a190d76
Merge branch 'master' into apopiak/reserve-asset-transfer
Aug 25, 2021
5756831
Merge branch 'master' into apopiak/reserve-asset-transfer
shawntabrizi Aug 31, 2021
03f7783
Merge branch 'master' of github.com:paritytech/cumulus into apopiak/r…
apopiak Sep 1, 2021
10a56e4
Merge branch 'master' of github.com:paritytech/cumulus into apopiak/r…
apopiak Sep 9, 2021
cf2e1d2
accept statemint as reserve in rococo test parachain
apopiak Sep 9, 2021
f7d216e
Merge branch 'apopiak/reserve-asset-transfer' of github.com:paritytec…
apopiak Sep 9, 2021
66aa186
adjust parachain config (add Statemint as reserve)
apopiak Sep 21, 2021
ef75ea7
add test and docs for AssetsFrom
apopiak Sep 28, 2021
a3b9843
cargo fmt
apopiak Sep 28, 2021
b4209f5
Merge branch 'master' of github.com:paritytech/cumulus into apopiak/r…
apopiak Sep 28, 2021
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
3 changes: 3 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions polkadot-parachains/parachains-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ node-primitives = { git = 'https://github.com/paritytech/substrate', branch = "m
# Polkadot dependencies
polkadot-runtime-common = { git = 'https://github.com/paritytech/polkadot', branch = "master", default-features = false }
polkadot-primitives = { git = 'https://github.com/paritytech/polkadot', branch = "master", default-features = false }
xcm = { git = 'https://github.com/paritytech/polkadot', branch = "master", default-features = false }
xcm-executor = { git = 'https://github.com/paritytech/polkadot', branch = "master", default-features = false }

# Local dependencies
pallet-collator-selection = { path = '../../pallets/collator-selection', default-features = false }
Expand Down
51 changes: 50 additions & 1 deletion polkadot-parachains/parachains-common/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
//! Auxillary struct/enums for parachain runtimes.
//! Taken from polkadot/runtime/common (at a21cd64) and adapted for parachains.

use frame_support::traits::{Currency, Imbalance, OnUnbalanced};
use frame_support::traits::{fungibles, Contains, Currency, Get, Imbalance, OnUnbalanced};
use sp_runtime::traits::Zero;
use sp_std::marker::PhantomData;
use xcm::latest::{AssetId, Fungibility::Fungible, MultiAsset, MultiLocation};
use xcm_executor::traits::FilterAssetLocation;

pub type NegativeImbalance<T> = <pallet_balances::Pallet<T> as Currency<
<T as frame_system::Config>::AccountId,
Expand All @@ -42,6 +46,7 @@ where
}
}

/// Merge the fees into one item and pass them on to the staking pot.
pub struct DealWithFees<R>(sp_std::marker::PhantomData<R>);
impl<R> OnUnbalanced<NegativeImbalance<R>> for DealWithFees<R>
where
Expand All @@ -60,6 +65,29 @@ where
}
}

/// Allow checking in assets that have issuance > 0.
pub struct NonZeroIssuance<AccountId, Assets>(PhantomData<(AccountId, Assets)>);
impl<AccountId, Assets> Contains<<Assets as fungibles::Inspect<AccountId>>::AssetId>
for NonZeroIssuance<AccountId, Assets>
where
Assets: fungibles::Inspect<AccountId>,
{
fn contains(id: &<Assets as fungibles::Inspect<AccountId>>::AssetId) -> bool {
!Assets::total_issuance(*id).is_zero()
}
}

/// Asset filter that allows all assets from a certain location.
pub struct AssetsFrom<T>(PhantomData<T>);
impl<T: Get<MultiLocation>> FilterAssetLocation for AssetsFrom<T> {
fn filter_asset_location(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.match_and_split(&loc).is_some())
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -77,6 +105,7 @@ mod tests {
traits::{BlakeTwo256, IdentityLookup},
Perbill,
};
use xcm::prelude::*;

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
Expand Down Expand Up @@ -207,4 +236,24 @@ mod tests {
assert_eq!(Balances::free_balance(CollatorSelection::account_id()), 30);
});
}

#[test]
fn assets_from_filters_correctly() {
parameter_types! {
pub SomeSiblingParachain: MultiLocation = MultiLocation::new(1, X1(Parachain(1234)));
}

let asset_location = SomeSiblingParachain::get()
.clone()
.pushed_with_interior(GeneralIndex(42))
.expect("multilocation will only have 2 junctions; qed");
let asset = MultiAsset { id: Concrete(asset_location), fun: 1_000_000.into() };
assert!(
AssetsFrom::<SomeSiblingParachain>::filter_asset_location(
&asset,
&SomeSiblingParachain::get()
),
"AssetsFrom should allow assets from any of its interior locations"
);
}
}
3 changes: 3 additions & 0 deletions polkadot-parachains/parachains-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ mod types {

// Aura consensus authority.
pub type AuraId = sp_consensus_aura::sr25519::AuthorityId;

// Id used for identifying assets.
pub type AssetId = u32;
}

/// Common constants of parachains.
Expand Down
2 changes: 2 additions & 0 deletions polkadot-parachains/rococo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pallet-transaction-payment = { git = "https://github.com/paritytech/substrate",
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }

parachains-common = { path = "../parachains-common", default-features = false }

# Cumulus dependencies
cumulus-pallet-aura-ext = { path = "../../pallets/aura-ext", default-features = false }
cumulus-pallet-parachain-system = { path = "../../pallets/parachain-system", default-features = false }
Expand Down
63 changes: 57 additions & 6 deletions polkadot-parachains/rococo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,24 @@ pub use frame_support::{
},
StorageValue,
};
use frame_system::limits::{BlockLength, BlockWeights};
use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureOneOf, EnsureRoot,
};
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use sp_runtime::{Perbill, Permill};

use parachains_common::{
impls::{AssetsFrom, NonZeroIssuance},
AssetId,
};
use xcm_builder::{AsPrefixedGeneralIndex, ConvertedConcreteAssetId, FungiblesAdapter};
use xcm_executor::traits::JustTry;

// XCM imports
use pallet_xcm::{EnsureXcm, IsMajorityOfBody, XcmPassthrough};
use polkadot_parachain::primitives::Sibling;
Expand Down Expand Up @@ -258,6 +268,7 @@ parameter_types! {
pub const RococoNetwork: NetworkId = NetworkId::Polkadot;
pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
}

/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
Expand All @@ -273,7 +284,7 @@ pub type LocationToAccountId = (
);

/// Means for transacting assets on this chain.
pub type LocalAssetTransactor = CurrencyAdapter<
pub type CurrencyTransactor = CurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
Expand All @@ -286,6 +297,30 @@ pub type LocalAssetTransactor = CurrencyAdapter<
(),
>;

/// Means for transacting assets besides the native currency on this chain.
pub type FungiblesTransactor = FungiblesAdapter<
// Use this fungibles implementation:
Assets,
// Use this currency when it is a fungible asset matching the given location or name:
ConvertedConcreteAssetId<
AssetId,
u64,
AsPrefixedGeneralIndex<StatemintLocation, AssetId, JustTry>,
JustTry,
>,
// Convert an XCM MultiLocation into a local account id:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We only want to allow teleports of known assets. We use non-zero issuance as an indication
// that this asset is known.
NonZeroIssuance<AccountId, Assets>,
// The account to use for tracking teleports.
CheckingAccount,
>;
/// Means for transacting assets on this chain.
pub type AssetTransactors = (CurrencyTransactor, 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
/// biases the kind of local `Origin` it will become.
Expand Down Expand Up @@ -324,22 +359,34 @@ match_type! {
MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
};
}
match_type! {
pub type Statemint: impl Contains<MultiLocation> = {
MultiLocation { parents: 1, interior: X1(Parachain(1000)) }
};
}

pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
AllowUnpaidExecutionFrom<ParentOrParentsUnitPlurality>,
// ^^^ Parent & its unit plurality gets free execution
AllowUnpaidExecutionFrom<Statemint>,
);

parameter_types! {
pub StatemintLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(1000)));
}

pub type Reserves = (NativeAsset, AssetsFrom<StatemintLocation>);

pub struct XcmConfig;
impl Config for XcmConfig {
type Call = Call;
type XcmSender = XcmRouter;
// How to withdraw and deposit an asset.
type AssetTransactor = LocalAssetTransactor;
type AssetTransactor = AssetTransactors;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = NativeAsset;
type IsReserve = Reserves;
type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of ROC
type LocationInverter = LocationInverter<Ancestry>;
type Barrier = Barrier;
Expand Down Expand Up @@ -416,12 +463,16 @@ parameter_types! {
}

/// A majority of the Unit body from Rococo over XCM is our required administration origin.
pub type AdminOrigin = EnsureXcm<IsMajorityOfBody<RocLocation, UnitBody>>;
pub type AdminOrigin = EnsureOneOf<
AccountId,
EnsureRoot<AccountId>,
EnsureXcm<IsMajorityOfBody<RocLocation, UnitBody>>,
>;

impl pallet_assets::Config for Runtime {
type Event = Event;
type Balance = u64;
type AssetId = u32;
type AssetId = AssetId;
type Currency = Balances;
type ForceOrigin = AdminOrigin;
type AssetDeposit = AssetDeposit;
Expand Down
54 changes: 40 additions & 14 deletions polkadot-parachains/statemine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdLookup, BlakeTwo256, Block as BlockT},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
ApplyExtrinsicResult, Perbill,
};

use sp_std::prelude::*;
Expand All @@ -56,11 +56,10 @@ use frame_system::{
};
pub use parachains_common as common;
use parachains_common::{
impls::DealWithFees, opaque, AccountId, AuraId, Balance, BlockNumber, Hash, Header, Index,
Signature, AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO,
SLOT_DURATION,
impls::{DealWithFees, NonZeroIssuance},
opaque, AccountId, AssetId, AuraId, Balance, BlockNumber, Hash, Header, Index, Signature,
AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION,
};
use sp_runtime::Perbill;

#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
Expand All @@ -71,13 +70,14 @@ use polkadot_parachain::primitives::Sibling;
use polkadot_runtime_common::{BlockHashCount, RocksDbWeight, SlowAdjustingFeeUpdate};
use xcm::latest::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset,
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom,
AsPrefixedGeneralIndex, ConvertedConcreteAssetId, CurrencyAdapter, EnsureXcmOrigin,
FixedWeightBounds, FungiblesAdapter, IsConcrete, LocationInverter, NativeAsset,
ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,
};
use xcm_executor::{Config, XcmExecutor};
use xcm_executor::{traits::JustTry, Config, XcmExecutor};

impl_opaque_keys! {
pub struct SessionKeys {
Expand Down Expand Up @@ -238,7 +238,7 @@ pub type AssetsForceOrigin = EnsureOneOf<
impl pallet_assets::Config for Runtime {
type Event = Event;
type Balance = Balance;
type AssetId = u32;
type AssetId = AssetId;
type Currency = Balances;
type ForceOrigin = AssetsForceOrigin;
type AssetDeposit = AssetDeposit;
Expand Down Expand Up @@ -465,6 +465,8 @@ parameter_types! {
pub const RelayNetwork: NetworkId = NetworkId::Kusama;
pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
pub const Local: MultiLocation = Here.into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
}

/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
Expand All @@ -479,20 +481,44 @@ pub type LocationToAccountId = (
AccountId32Aliases<RelayNetwork, AccountId>,
);

/// Means for transacting assets on this chain.
pub type LocalAssetTransactor = CurrencyAdapter<
/// Means for transacting the native currency on this chain.
pub type CurrencyTransactor = CurrencyAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete<KsmLocation>,
// Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
// Convert an XCM MultiLocation into a local account id:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We don't track any teleports.
// We don't track any teleports of `Balances`.
(),
>;

/// Means for transacting assets besides the native currency on this chain.
pub type FungiblesTransactor = FungiblesAdapter<
// Use this fungibles implementation:
Assets,
// Use this currency when it is a fungible asset matching the given location or name:
ConvertedConcreteAssetId<
AssetId,
Balance,
AsPrefixedGeneralIndex<Local, AssetId, JustTry>,
JustTry,
>,
// Convert an XCM MultiLocation into a local account id:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We only want to allow teleports of known assets. We use non-zero issuance as an indication
// that this asset is known.
NonZeroIssuance<AccountId, Assets>,
// The account to use for tracking teleports.
CheckingAccount,
>;
/// Means for transacting assets on this chain.
pub type AssetTransactors = (CurrencyTransactor, 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
/// biases the kind of local `Origin` it will become.
Expand Down Expand Up @@ -542,7 +568,7 @@ impl Config for XcmConfig {
type Call = Call;
type XcmSender = XcmRouter;
// How to withdraw and deposit an asset.
type AssetTransactor = LocalAssetTransactor;
type AssetTransactor = AssetTransactors;
type OriginConverter = XcmOriginToTransactDispatchOrigin;
type IsReserve = NativeAsset;
type IsTeleporter = NativeAsset; // <- should be enough to allow teleportation of KSM
Expand Down
Loading