diff --git a/evm-template/Cargo.lock b/evm-template/Cargo.lock index 356071a5..3b003755 100644 --- a/evm-template/Cargo.lock +++ b/evm-template/Cargo.lock @@ -3000,6 +3000,7 @@ dependencies = [ "fp-self-contained", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -6056,6 +6057,20 @@ dependencies = [ "hash-db", ] +[[package]] +name = "merkleized-metadata" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f313fcff1d2a4bcaa2deeaa00bf7530d77d5f7bd0467a117dde2e29a75a7a17a" +dependencies = [ + "array-bytes", + "blake3", + "frame-metadata", + "parity-scale-codec", + "scale-decode", + "scale-info", +] + [[package]] name = "merlin" version = "3.0.0" @@ -12153,6 +12168,29 @@ dependencies = [ "sp-arithmetic", ] +[[package]] +name = "scale-bits" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57b1e7f6b65ed1f04e79a85a57d755ad56d76fdf1e9bddcc9ae14f71fcdcf54" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98f3262c250d90e700bb802eb704e1f841e03331c2eb815e46516c4edbf5b27" +dependencies = [ + "derive_more", + "parity-scale-codec", + "scale-bits", + "scale-type-resolver", + "smallvec", +] + [[package]] name = "scale-info" version = "2.11.3" @@ -12179,6 +12217,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "scale-type-resolver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" + [[package]] name = "schannel" version = "0.1.24" @@ -13955,13 +13999,22 @@ name = "substrate-wasm-builder" version = "24.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-stable2407-1#16b0fd09d9e9281c20ee0c1d8b87d011e3e3454e" dependencies = [ + "array-bytes", "build-helper", "cargo_metadata", "console", "filetime", + "frame-metadata", + "merkleized-metadata", + "parity-scale-codec", "parity-wasm", "polkavm-linker", + "sc-executor", + "sp-core", + "sp-io", "sp-maybe-compressed-blob", + "sp-tracing", + "sp-version", "strum 0.26.3", "tempfile", "toml 0.8.19", diff --git a/evm-template/zombienet-config/devnet.toml b/evm-template/zombienet-config/devnet.toml index 0be2b612..4b482ac3 100644 --- a/evm-template/zombienet-config/devnet.toml +++ b/evm-template/zombienet-config/devnet.toml @@ -1,5 +1,5 @@ [relaychain] -chain = "paseo-local" +chain = "rococo-local" default_command = "./bin-stable2407-1/polkadot" [[relaychain.nodes]] diff --git a/generic-template/Cargo.lock b/generic-template/Cargo.lock index c3600a64..7065c1b8 100644 --- a/generic-template/Cargo.lock +++ b/generic-template/Cargo.lock @@ -3627,6 +3627,7 @@ dependencies = [ "cumulus-primitives-utility", "frame-benchmarking", "frame-executive", + "frame-metadata-hash-extension", "frame-support", "frame-system", "frame-system-benchmarking", @@ -3634,6 +3635,9 @@ dependencies = [ "frame-try-runtime", "hex-literal", "log", + "orml-traits", + "orml-xcm-support", + "orml-xtokens", "pallet-asset-manager", "pallet-assets", "pallet-aura", @@ -3656,6 +3660,7 @@ dependencies = [ "pallet-utility", "pallet-whitelist", "pallet-xcm", + "pallet-xcm-weight-trader", "parachains-common", "parity-scale-codec", "polkadot-parachain-primitives", @@ -3681,6 +3686,7 @@ dependencies = [ "staging-xcm-builder", "staging-xcm-executor", "substrate-wasm-builder", + "xcm-primitives", ] [[package]] @@ -5627,6 +5633,20 @@ dependencies = [ "hash-db", ] +[[package]] +name = "merkleized-metadata" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f313fcff1d2a4bcaa2deeaa00bf7530d77d5f7bd0467a117dde2e29a75a7a17a" +dependencies = [ + "array-bytes", + "blake3", + "frame-metadata", + "parity-scale-codec", + "scale-decode", + "scale-info", +] + [[package]] name = "merlin" version = "3.0.0" @@ -6374,7 +6394,7 @@ dependencies = [ [[package]] name = "orml-traits" version = "0.10.0" -source = "git+https://github.com/openzeppelin/open-runtime-module-library?branch=polkadot-stable2407-1#aafe9077c9ec61dd8b3a42e899ef8353b2b050c0" +source = "git+https://github.com/OpenZeppelin/open-runtime-module-library?branch=polkadot-stable2407-1#aafe9077c9ec61dd8b3a42e899ef8353b2b050c0" dependencies = [ "frame-support", "impl-trait-for-tuples", @@ -6383,6 +6403,7 @@ dependencies = [ "parity-scale-codec", "paste", "scale-info", + "serde", "sp-core", "sp-io", "sp-runtime", @@ -6393,17 +6414,53 @@ dependencies = [ [[package]] name = "orml-utilities" version = "0.10.0" -source = "git+https://github.com/openzeppelin/open-runtime-module-library?branch=polkadot-stable2407-1#aafe9077c9ec61dd8b3a42e899ef8353b2b050c0" +source = "git+https://github.com/OpenZeppelin/open-runtime-module-library?branch=polkadot-stable2407-1#aafe9077c9ec61dd8b3a42e899ef8353b2b050c0" dependencies = [ "frame-support", "parity-scale-codec", "scale-info", + "serde", "sp-core", "sp-io", "sp-runtime", "sp-std", ] +[[package]] +name = "orml-xcm-support" +version = "0.10.0" +source = "git+https://github.com/OpenZeppelin/open-runtime-module-library?branch=polkadot-stable2407-1#aafe9077c9ec61dd8b3a42e899ef8353b2b050c0" +dependencies = [ + "frame-support", + "orml-traits", + "parity-scale-codec", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-executor", +] + +[[package]] +name = "orml-xtokens" +version = "0.10.0" +source = "git+https://github.com/OpenZeppelin/open-runtime-module-library?branch=polkadot-stable2407-1#aafe9077c9ec61dd8b3a42e899ef8353b2b050c0" +dependencies = [ + "frame-support", + "frame-system", + "log", + "orml-traits", + "orml-xcm-support", + "pallet-xcm", + "parity-scale-codec", + "scale-info", + "serde", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-executor", +] + [[package]] name = "overload" version = "0.1.1" @@ -7534,6 +7591,27 @@ dependencies = [ "staging-xcm-executor", ] +[[package]] +name = "pallet-xcm-weight-trader" +version = "0.1.0" +source = "git+https://github.com/OpenZeppelin/moonbeam.git?branch=polkadot-stable2407-1#fab6e72fbaaeaa065ad983556d09d4c0e8755dfa" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "staging-xcm", + "staging-xcm-executor", + "xcm-runtime-apis", +] + [[package]] name = "parachains-common" version = "17.0.0" @@ -9341,7 +9419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.5.0", + "heck 0.4.1", "itertools 0.12.1", "log", "multimap 0.10.0", @@ -11474,6 +11552,29 @@ dependencies = [ "sp-arithmetic", ] +[[package]] +name = "scale-bits" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57b1e7f6b65ed1f04e79a85a57d755ad56d76fdf1e9bddcc9ae14f71fcdcf54" +dependencies = [ + "parity-scale-codec", + "scale-type-resolver", +] + +[[package]] +name = "scale-decode" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98f3262c250d90e700bb802eb704e1f841e03331c2eb815e46516c4edbf5b27" +dependencies = [ + "derive_more", + "parity-scale-codec", + "scale-bits", + "scale-type-resolver", + "smallvec", +] + [[package]] name = "scale-info" version = "2.11.3" @@ -11500,6 +11601,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "scale-type-resolver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" + [[package]] name = "schannel" version = "0.1.23" @@ -13153,13 +13260,22 @@ name = "substrate-wasm-builder" version = "24.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-stable2407-1#16b0fd09d9e9281c20ee0c1d8b87d011e3e3454e" dependencies = [ + "array-bytes", "build-helper", "cargo_metadata", "console", "filetime", + "frame-metadata", + "merkleized-metadata", + "parity-scale-codec", "parity-wasm", "polkavm-linker", + "sc-executor", + "sp-core", + "sp-io", "sp-maybe-compressed-blob", + "sp-tracing", + "sp-version", "strum 0.26.3", "tempfile", "toml 0.8.19", diff --git a/generic-template/Cargo.toml b/generic-template/Cargo.toml index dfe8d5e4..304b3a5f 100644 --- a/generic-template/Cargo.toml +++ b/generic-template/Cargo.toml @@ -132,6 +132,13 @@ parachains-common = { git = "https://github.com/paritytech/polkadot-sdk", defaul # Moonbeam pallet-asset-manager = { git = "https://github.com/OpenZeppelin/moonbeam.git", branch = "polkadot-stable2407-1", default-features = false } +pallet-xcm-weight-trader = { git = "https://github.com/OpenZeppelin/moonbeam.git", branch = "polkadot-stable2407-1", default-features = false } +xcm-primitives = { git = "https://github.com/OpenZeppelin/moonbeam.git", branch = "polkadot-stable2407-1", default-features = false } + +# ORML +orml-traits = { git = "https://github.com/OpenZeppelin/open-runtime-module-library", branch = "polkadot-stable2407-1", default-features = false } +orml-xcm-support = { git = "https://github.com/OpenZeppelin/open-runtime-module-library", branch = "polkadot-stable2407-1", default-features = false } +orml-xtokens = { git = "https://github.com/OpenZeppelin/open-runtime-module-library", branch = "polkadot-stable2407-1", default-features = false } # Fuzzer ziggy = { version = "1.0.2", default-features = false } diff --git a/generic-template/runtime/Cargo.toml b/generic-template/runtime/Cargo.toml index e4bccb4d..9a12a301 100644 --- a/generic-template/runtime/Cargo.toml +++ b/generic-template/runtime/Cargo.toml @@ -84,6 +84,13 @@ parachains-common = { workspace = true } # Moonbeam pallet-asset-manager = { workspace = true } +pallet-xcm-weight-trader = { workspace = true } +xcm-primitives = { workspace = true } + +# ORML +orml-traits = { workspace = true } +orml-xcm-support = { workspace = true } +orml-xtokens = { workspace = true } [dev-dependencies] sp-io = { workspace = true } @@ -92,7 +99,6 @@ sp-io = { workspace = true } substrate-wasm-builder = { workspace = true } [features] -default = [ "std" ] std = [ "assets-common/std", "cumulus-pallet-aura-ext/std", @@ -113,6 +119,7 @@ std = [ "frame-system/std", "frame-try-runtime?/std", "log/std", + "orml-xtokens/std", "pallet-asset-manager/std", "pallet-assets/std", "pallet-aura/std", @@ -134,6 +141,7 @@ std = [ "pallet-treasury/std", "pallet-utility/std", "pallet-whitelist/std", + "pallet-xcm-weight-trader/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", @@ -156,10 +164,10 @@ std = [ "sp-version/std", "xcm-builder/std", "xcm-executor/std", + "xcm-primitives/std", "xcm/std", ] -async-backing = [] -metadata-hash = [ "substrate-wasm-builder/metadata-hash" ] + runtime-benchmarks = [ "assets-common/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", @@ -187,6 +195,7 @@ runtime-benchmarks = [ "pallet-treasury/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-whitelist/runtime-benchmarks", + "pallet-xcm-weight-trader/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", @@ -205,6 +214,7 @@ try-runtime = [ "frame-support/try-runtime", "frame-system/try-runtime", "frame-try-runtime/try-runtime", + "orml-xtokens/try-runtime", "pallet-asset-manager/try-runtime", "pallet-assets/try-runtime", "pallet-aura/try-runtime", @@ -226,6 +236,7 @@ try-runtime = [ "pallet-treasury/try-runtime", "pallet-utility/try-runtime", "pallet-whitelist/try-runtime", + "pallet-xcm-weight-trader/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", @@ -236,3 +247,9 @@ try-runtime = [ # deployment. This will disable stuff that shouldn't be part of the on-chain wasm # to make it smaller, like logging for example. on-chain-release-build = [ "sp-api/disable-logging" ] + +async-backing = [] + +default = [ "std" ] + +metadata-hash = [ "substrate-wasm-builder/metadata-hash" ] diff --git a/generic-template/runtime/src/configs/asset_config.rs b/generic-template/runtime/src/configs/asset_config.rs index cb83a12a..3b8c1d2c 100644 --- a/generic-template/runtime/src/configs/asset_config.rs +++ b/generic-template/runtime/src/configs/asset_config.rs @@ -181,12 +181,12 @@ pub trait AccountIdAssetIdConversion { fn asset_id_to_account(prefix: &[u8], asset_id: AssetId) -> Account; } +// needs to be 28 bytes due to `data` is 4 bytes const FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[255u8; 28]; // Instruct how to go from an H256 to an AssetID impl AccountIdAssetIdConversion for Runtime { /// The way to convert an account to assetId is by ensuring that the prefix is 0XFFFFFFFF - /// and by taking the lowest 128 bits as the assetId fn account_to_asset_id(account: AccountId) -> Option<(Vec, AssetId)> { let bytes: [u8; 32] = account.into(); let h256_account: H256 = bytes.into(); @@ -194,6 +194,7 @@ impl AccountIdAssetIdConversion for Runtime { let (prefix_part, id_part) = h256_account.as_fixed_bytes().split_at(28); if prefix_part == FOREIGN_ASSET_PRECOMPILE_ADDRESS_PREFIX { data.copy_from_slice(id_part); + // we use `data` to create a u32 -> data needs to be 4 bytes let asset_id: AssetId = u32::from_be_bytes(data); Some((prefix_part.to_vec(), asset_id)) } else { diff --git a/generic-template/runtime/src/configs/mod.rs b/generic-template/runtime/src/configs/mod.rs index 8df70d2a..f94b8663 100644 --- a/generic-template/runtime/src/configs/mod.rs +++ b/generic-template/runtime/src/configs/mod.rs @@ -1,4 +1,5 @@ pub mod asset_config; +pub use asset_config::AssetType; pub mod governance; pub mod xcm_config; diff --git a/generic-template/runtime/src/configs/xcm_config.rs b/generic-template/runtime/src/configs/xcm_config.rs index 352c7e21..9fe19bda 100644 --- a/generic-template/runtime/src/configs/xcm_config.rs +++ b/generic-template/runtime/src/configs/xcm_config.rs @@ -1,43 +1,59 @@ +use core::marker::PhantomData; + use frame_support::{ + pallet_prelude::Get, parameter_types, - traits::{ConstU32, Contains, Everything, Nothing, PalletInfoAccess}, + traits::{ConstU32, Contains, ContainsPair, Everything, Nothing, PalletInfoAccess}, weights::Weight, }; use frame_system::EnsureRoot; +use orml_traits::{location::Reserve, parameter_type_with_key}; +use orml_xcm_support::MultiNativeAsset; use pallet_xcm::XcmPassthrough; +use parity_scale_codec::{Decode, Encode}; use polkadot_parachain_primitives::primitives::{self, Sibling}; -use polkadot_runtime_common::impls::ToAuthor; +use scale_info::TypeInfo; +use sp_runtime::traits::Convert; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, Case, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, IsChildSystemParachain, - IsConcrete, NativeAsset, NoChecking, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, - UsingComponents, WithComputedOrigin, WithUniqueTopic, XcmFeeManagerFromComponents, - XcmFeeToAccount, + IsConcrete, NoChecking, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, WithComputedOrigin, + WithUniqueTopic, XcmFeeManagerFromComponents, XcmFeeToAccount, }; use xcm_executor::XcmExecutor; +use xcm_primitives::{AbsoluteAndRelativeReserve, AsAssetType}; use super::TreasuryAccount; use crate::{ configs::{ - weights, Balances, ParachainSystem, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, - WeightToFee, XcmpQueue, + weights, AssetType, Balances, ParachainSystem, + Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmpQueue, }, - types::{AccountId, Balance}, - AllPalletsWithSystem, Assets, ParachainInfo, PolkadotXcm, + types::{AccountId, AssetId, Balance}, + AllPalletsWithSystem, AssetManager, Assets, ParachainInfo, PolkadotXcm, }; parameter_types! { - pub const RelayLocation: Location = Location::parent(); pub const RelayNetwork: Option = None; pub PlaceholderAccount: AccountId = PolkadotXcm::check_account(); pub AssetsPalletLocation: Location = PalletInstance(::index() as u8).into(); pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorLocation = Parachain(ParachainInfo::parachain_id().into()).into(); + // 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 Location: (Self Balances pallet index) + // We use the RELATIVE multilocation + pub SelfReserve: Location = Location { + parents:0, + interior: [ + PalletInstance(::index() as u8) + ].into() + }; } /// `AssetId/Balancer` converter for `TrustBackedAssets` @@ -145,6 +161,48 @@ pub type Barrier = TrailingSetTopicAsId< >, >; +/// Matches foreign assets from a given origin. +/// Foreign assets are assets bridged from other consensus systems. i.e parents > 1. +pub struct IsBridgedConcreteAssetFrom(PhantomData); +impl ContainsPair for IsBridgedConcreteAssetFrom +where + Origin: Get, +{ + fn contains(asset: &Asset, origin: &Location) -> bool { + let loc = Origin::get(); + &loc == origin + && matches!( + asset, + Asset { id: AssetId(Location { parents: 2, .. }), fun: Fungibility::Fungible(_) }, + ) + } +} + +parameter_types! { + /// Location of Asset Hub + pub AssetHubLocation: Location = Location::new(1, [Parachain(1000)]); + pub const RelayLocation: Location = Location::parent(); + pub RelayLocationFilter: AssetFilter = Wild(AllOf { + fun: WildFungible, + id: xcm::prelude::AssetId(RelayLocation::get()), + }); + pub RelayChainNativeAssetFromAssetHub: (AssetFilter, Location) = ( + RelayLocationFilter::get(), + AssetHubLocation::get() + ); +} + +type Reserves = ( + // Assets bridged from different consensus systems held in reserve on Asset Hub. + IsBridgedConcreteAssetFrom, + // Relaychain (DOT) from Asset Hub + Case, + // Assets which the reserve is the same as the origin. + MultiNativeAsset>, +); + +pub type XcmWeigher = FixedWeightBounds; + pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type Aliasers = Nothing; @@ -165,7 +223,7 @@ impl xcm_executor::Config for XcmConfig { type HrmpChannelClosingHandler = (); type HrmpNewChannelOpenRequestHandler = (); /// Please, keep these two configs (`IsReserve` and `IsTeleporter`) mutually exclusive - type IsReserve = NativeAsset; + type IsReserve = Reserves; type IsTeleporter = (); type MaxAssetsIntoHolding = MaxAssetsIntoHolding; type MessageExporter = (); @@ -175,13 +233,12 @@ impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; type SafeCallFilter = Everything; type SubscriptionService = PolkadotXcm; - type Trader = - UsingComponents>; + type Trader = pallet_xcm_weight_trader::Trader; type TransactionalProcessor = FrameTransactionalProcessor; type UniversalAliases = Nothing; // Teleporting is disabled. type UniversalLocation = UniversalLocation; - type Weigher = FixedWeightBounds; + type Weigher = XcmWeigher; type XcmRecorder = PolkadotXcm; type XcmSender = XcmRouter; } @@ -220,7 +277,7 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type TrustedLockers = (); type UniversalLocation = UniversalLocation; - type Weigher = FixedWeightBounds; + type Weigher = XcmWeigher; /// Rerun benchmarks if you are making changes to runtime configuration. type WeightInfo = weights::pallet_xcm::WeightInfo; #[cfg(feature = "runtime-benchmarks")] @@ -240,3 +297,195 @@ impl cumulus_pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; } + +parameter_types! { + pub const BaseXcmWeight: Weight = Weight::from_parts(200_000_000u64, 0); + pub const MaxAssetsForTransfer: usize = 2; + + // This is how we are going to detect whether the asset is a Reserve asset + // This however is the chain part only + pub SelfLocation: Location = Location::here(); + // We need this to be able to catch when someone is trying to execute a non- + // cross-chain transfer in xtokens through the absolute path way + pub SelfLocationAbsolute: Location = Location { + parents:1, + interior: [ + Parachain(ParachainInfo::parachain_id().into()) + ].into() + }; +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: Location| -> Option { + match (location.parents, location.first_interior()) { + // Polkadot AssetHub fee + (1, Some(Parachain(1000u32))) => Some(50_000_000u128), + _ => None, + } + }; +} + +// Our currencyId. We distinguish for now between SelfReserve, and Others, defined by their Id. +#[derive(Clone, Eq, Debug, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] +pub enum CurrencyId { + // Our native token + SelfReserve, + // Assets representing other chains native tokens + ForeignAsset(AssetId), +} + +parameter_types! { + pub PolkadotXcmLocation: Location = Location { + parents:0, + interior: [ + PalletInstance(::index() as u8) + ].into() + }; +} + +// How to convert from CurrencyId to Location +pub struct CurrencyIdToLocation(sp_std::marker::PhantomData); +impl sp_runtime::traits::Convert> + for CurrencyIdToLocation +where + AssetXConverter: sp_runtime::traits::MaybeEquivalence, +{ + fn convert(currency: CurrencyId) -> Option { + match currency { + CurrencyId::SelfReserve => { + let multi: Location = SelfReserve::get(); + Some(multi) + } + CurrencyId::ForeignAsset(asset) => AssetXConverter::convert_back(&asset), + } + } +} + +pub struct AccountIdToLocation; +impl Convert for AccountIdToLocation { + fn convert(account: AccountId) -> Location { + AccountId32 { network: None, id: account.into() }.into() + } +} + +/// The `DOTReserveProvider` overrides the default reserve location for DOT (Polkadot's native token). +/// +/// DOT can exist in multiple locations, and this provider ensures that the reserve is correctly set +/// to the AssetHub parachain. +/// +/// - **Default Location:** `{ parents: 1, location: Here }` +/// - **Reserve Location on AssetHub:** `{ parents: 1, location: X1(Parachain(AssetHubParaId)) }` +/// +/// This provider ensures that if the asset's ID points to the default "Here" location, +/// it will instead be mapped to the AssetHub parachain. +pub struct DOTReserveProvider; + +impl Reserve for DOTReserveProvider { + fn reserve(asset: &Asset) -> Option { + let AssetId(location) = &asset.id; + + let dot_here = Location::new(1, Here); + let dot_asset_hub = AssetHubLocation::get(); + + if location == &dot_here { + Some(dot_asset_hub) // Reserve is on AssetHub. + } else { + None + } + } +} + +/// The `BridgedAssetReserveProvider` handles assets that are bridged from external consensus systems +/// (e.g., Ethereum) and may have multiple valid reserve locations. +/// +/// Specifically, these bridged assets can have two known reserves: +/// 1. **Ethereum-based Reserve:** +/// `{ parents: 1, location: X1(GlobalConsensus(Ethereum{ chain_id: 1 })) }` +/// 2. **AssetHub Parachain Reserve:** +/// `{ parents: 1, location: X1(Parachain(AssetHubParaId)) }` +/// +/// This provider maps the reserve for bridged assets to AssetHub when the asset originates +/// from a global consensus system, such as Ethereum. +pub struct BridgedAssetReserveProvider; + +impl Reserve for BridgedAssetReserveProvider { + fn reserve(asset: &Asset) -> Option { + let AssetId(location) = &asset.id; + + let asset_hub_reserve = AssetHubLocation::get(); + + // any asset that has parents > 1 and interior that starts with GlobalConsensus(_) pattern + // can be considered a bridged asset. + // + // `split_global` will return an `Err` if the first item is not a `GlobalConsensus` + if location.parents > 1 && location.interior.clone().split_global().is_ok() { + Some(asset_hub_reserve) + } else { + None + } + } +} + +pub struct ReserveProviders; + +impl Reserve for ReserveProviders { + fn reserve(asset: &Asset) -> Option { + // Try each provider's reserve method in sequence. + DOTReserveProvider::reserve(asset) + .or_else(|| BridgedAssetReserveProvider::reserve(asset)) + .or_else(|| AbsoluteAndRelativeReserve::::reserve(asset)) + } +} + +impl orml_xtokens::Config for Runtime { + type AccountIdToLocation = AccountIdToLocation; + type Balance = Balance; + type BaseXcmWeight = BaseXcmWeight; + type CurrencyId = CurrencyId; + type CurrencyIdConvert = CurrencyIdToLocation>; + type LocationsFilter = Everything; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type RateLimiter = (); + type RateLimiterId = (); + type ReserveProvider = ReserveProviders; + type RuntimeEvent = RuntimeEvent; + type SelfLocation = SelfLocation; + type UniversalLocation = UniversalLocation; + type Weigher = XcmWeigher; + type XcmExecutor = XcmExecutor; +} + +pub struct AssetFeesFilter; +impl frame_support::traits::Contains for AssetFeesFilter { + fn contains(location: &Location) -> bool { + location.parent_count() > 0 + && location.first_interior() != PolkadotXcmLocation::get().first_interior() + } +} + +// implement your own business logic for who can add/edit/remove/resume supported assets +pub type AddSupportedAssetOrigin = EnsureRoot; +pub type EditSupportedAssetOrigin = EnsureRoot; +pub type RemoveSupportedAssetOrigin = EnsureRoot; +pub type ResumeSupportedAssetOrigin = EnsureRoot; + +impl pallet_xcm_weight_trader::Config for Runtime { + type AccountIdToLocation = AccountIdToLocation; + type AddSupportedAssetOrigin = AddSupportedAssetOrigin; + type AssetLocationFilter = AssetFeesFilter; + type AssetTransactor = AssetTransactors; + type Balance = Balance; + type EditSupportedAssetOrigin = EditSupportedAssetOrigin; + type NativeLocation = SelfReserve; + #[cfg(feature = "runtime-benchmarks")] + type NotFilteredLocation = RelayLocation; + type PauseSupportedAssetOrigin = EditSupportedAssetOrigin; + type RemoveSupportedAssetOrigin = RemoveSupportedAssetOrigin; + type ResumeSupportedAssetOrigin = ResumeSupportedAssetOrigin; + type RuntimeEvent = RuntimeEvent; + // TODO: update this when we update benchmarks + type WeightInfo = weights::pallet_xcm_weight_trader::WeightInfo; + type WeightToFee = ::WeightToFee; + type XcmFeesAccount = TreasuryAccount; +} diff --git a/generic-template/runtime/src/lib.rs b/generic-template/runtime/src/lib.rs index 4112ce40..5b9fed58 100644 --- a/generic-template/runtime/src/lib.rs +++ b/generic-template/runtime/src/lib.rs @@ -185,6 +185,10 @@ mod runtime { pub type CumulusXcm = cumulus_pallet_xcm; #[runtime::pallet_index(33)] pub type MessageQueue = pallet_message_queue; + #[runtime::pallet_index(34)] + pub type XTokens = orml_xtokens; + #[runtime::pallet_index(35)] + pub type XcmWeightTrader = pallet_xcm_weight_trader; } cumulus_pallet_parachain_system::register_validate_block! { diff --git a/generic-template/runtime/src/weights/mod.rs b/generic-template/runtime/src/weights/mod.rs index deb5a8a4..22bd7d55 100644 --- a/generic-template/runtime/src/weights/mod.rs +++ b/generic-template/runtime/src/weights/mod.rs @@ -39,6 +39,7 @@ pub mod pallet_treasury; pub mod pallet_utility; pub mod pallet_whitelist; pub mod pallet_xcm; +pub mod pallet_xcm_weight_trader; pub mod paritydb_weights; pub mod rocksdb_weights; diff --git a/generic-template/runtime/src/weights/pallet_xcm_weight_trader.rs b/generic-template/runtime/src/weights/pallet_xcm_weight_trader.rs new file mode 100644 index 00000000..93d88a64 --- /dev/null +++ b/generic-template/runtime/src/weights/pallet_xcm_weight_trader.rs @@ -0,0 +1,104 @@ +// Copyright 2024 Moonbeam foundation +// This file is part of Moonbeam. + +// Moonbeam is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Moonbeam is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Moonbeam. If not, see . + +//! Autogenerated weights for `pallet_xcm_weight_trader` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-09-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `ip-10-0-0-176`, CPU: `Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz` +//! WASM-EXECUTION: Compiled, CHAIN: Some("moonbase-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/production/moonbeam +// benchmark +// pallet +// --chain=moonbase-dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_xcm_weight_trader +// --extrinsic=* +// --wasm-execution=compiled +// --header=./file_header.txt +// --template=./benchmarking/frame-weight-template.hbs +// --output=./runtime/common/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weights for `pallet_xcm_weight_trader`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_weight_trader::WeightInfo for WeightInfo { + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn add_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `42` + // Estimated: `4100` + // Minimum execution time: 9_432_000 picoseconds. + Weight::from_parts(9_644_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn edit_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `102` + // Estimated: `4100` + // Minimum execution time: 10_261_000 picoseconds. + Weight::from_parts(10_540_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn resume_asset_support() -> Weight { + // Proof Size summary in bytes: + // Measured: `102` + // Estimated: `4100` + // Minimum execution time: 10_153_000 picoseconds. + Weight::from_parts(10_537_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn pause_asset_support() -> Weight { + // Proof Size summary in bytes: + // Measured: `102` + // Estimated: `4100` + // Minimum execution time: 10_029_000 picoseconds. + Weight::from_parts(10_456_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `XcmWeightTrader::SupportedAssets` (r:1 w:1) + /// Proof: `XcmWeightTrader::SupportedAssets` (`max_values`: None, `max_size`: Some(635), added: 3110, mode: `MaxEncodedLen`) + fn remove_asset() -> Weight { + // Proof Size summary in bytes: + // Measured: `102` + // Estimated: `4100` + // Minimum execution time: 9_844_000 picoseconds. + Weight::from_parts(10_218_000, 4100) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +}