From 015eed1796b1d34f95a74ae8552a55fabf231517 Mon Sep 17 00:00:00 2001 From: Guantong Date: Wed, 4 Jan 2023 13:12:25 +0800 Subject: [PATCH] Adjust XCM trader (#143) * init LocalAssetTrader * LocalAssetTrader * Update trader for pangolin & crab * format * Update comments * Update logs * format * Format * Simplify code Co-authored-by: fisher Co-authored-by: Xavier Lau --- Cargo.lock | 2 + runtime/common/Cargo.toml | 14 +-- runtime/common/src/xcm_configs.rs | 94 ++++++++++++++++++-- runtime/crab/src/pallets/polkadot_xcm.rs | 26 +++++- runtime/darwinia/src/pallets/polkadot_xcm.rs | 26 +++++- runtime/pangolin/src/pallets/mod.rs | 1 + runtime/pangolin/src/pallets/polkadot_xcm.rs | 26 +++++- 7 files changed, 167 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c5b6a8c3..75c4a101b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2333,8 +2333,10 @@ dependencies = [ "pallet-collective", "parity-scale-codec", "sp-io", + "sp-runtime", "sp-std", "xcm", + "xcm-builder", "xcm-executor", ] diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 9815fc937..6a8206c45 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -24,14 +24,16 @@ account = { default-features = false, git = "https://github.com/darwinia-network # polkadot xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +xcm-builder = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } # substrate -frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -pallet-collective = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +pallet-collective = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } [features] default = ["std"] @@ -47,6 +49,7 @@ std = [ # polkadot "xcm/std", + "xcm-builder/std", "xcm-executor/std", # substrate @@ -54,5 +57,6 @@ std = [ "frame-system/std", "pallet-collective/std", "sp-io/std", + "sp-runtime/std", "sp-std/std", ] diff --git a/runtime/common/src/xcm_configs.rs b/runtime/common/src/xcm_configs.rs index c60aa7dc9..9c690a3d8 100644 --- a/runtime/common/src/xcm_configs.rs +++ b/runtime/common/src/xcm_configs.rs @@ -23,12 +23,23 @@ use codec::Encode; // darwinia use dc_primitives::GWEI; // polkadot -use xcm::latest::{prelude::*, Weight as XCMWeight}; -use xcm_executor::traits::{Convert, ShouldExecute}; +use xcm::latest::{prelude::*, Weight as XcmWeight}; +use xcm_builder::TakeRevenue; +use xcm_executor::{ + traits::{Convert, ShouldExecute, WeightTrader}, + Assets, +}; // substrate -use frame_support::{log, traits::ConstU128}; +use frame_support::{ + log, + traits::{ + tokens::currency::Currency as CurrencyT, ConstU128, Get, OnUnbalanced as OnUnbalancedT, + }, + weights::{Weight, WeightToFee as WeightToFeeT}, +}; use sp_io::hashing::blake2_256; -use sp_std::borrow::Borrow; +use sp_runtime::traits::{SaturatedConversion, Saturating, Zero}; +use sp_std::{borrow::Borrow, result::Result}; /// Base balance required for the XCM unit weight. pub type XcmBaseWeightFee = ConstU128; @@ -60,8 +71,8 @@ where fn should_execute( origin: &MultiLocation, message: &mut Xcm, - max_weight: XCMWeight, - weight_credit: &mut XCMWeight, + max_weight: XcmWeight, + weight_credit: &mut XcmWeight, ) -> Result<(), ()> { Deny::should_execute(origin, message, max_weight, weight_credit)?; Allow::should_execute(origin, message, max_weight, weight_credit) @@ -75,8 +86,8 @@ impl ShouldExecute for DenyReserveTransferToRelayChain { origin: &MultiLocation, message: &mut Xcm, - _max_weight: XCMWeight, - _weight_credit: &mut XCMWeight, + _max_weight: XcmWeight, + _weight_credit: &mut XcmWeight, ) -> Result<(), ()> { if message.0.iter().any(|inst| { matches!( @@ -126,3 +137,70 @@ impl + Into<[u8; 20]> + Clone> Convert, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + R: TakeRevenue, +>( + XcmWeight, + Currency::Balance, + PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced, R)>, +); +impl< + WeightToFee: WeightToFeeT, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + R: TakeRevenue, + > WeightTrader for LocalAssetTrader +{ + fn new() -> Self { + Self(0, Zero::zero(), PhantomData) + } + + fn buy_weight(&mut self, weight: XcmWeight, payment: Assets) -> Result { + log::trace!(target: "xcm::weight", "LocalAssetTrader::buy_weight weight: {:?}, payment: {:?}", weight, payment); + let amount = WeightToFee::weight_to_fee(&Weight::from_ref_time(weight)); + let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?; + let required: MultiAsset = (Concrete(AssetId::get()), u128_amount).into(); + let unused = payment.checked_sub(required.clone()).map_err(|_| XcmError::TooExpensive)?; + self.0 = self.0.saturating_add(weight); + self.1 = self.1.saturating_add(amount); + R::take_revenue(required); + Ok(unused) + } + + fn refund_weight(&mut self, weight: XcmWeight) -> Option { + log::trace!(target: "xcm::weight", "LocalAssetTrader::refund_weight weight: {:?}", weight); + let weight = weight.min(self.0); + let amount = WeightToFee::weight_to_fee(&Weight::from_ref_time(weight)); + self.0 -= weight; + self.1 = self.1.saturating_sub(amount); + let amount: u128 = amount.saturated_into(); + if amount > 0 { + Some((AssetId::get(), amount).into()) + } else { + None + } + } +} +impl< + WeightToFee: WeightToFeeT, + AssetId: Get, + AccountId, + Currency: CurrencyT, + OnUnbalanced: OnUnbalancedT, + R: TakeRevenue, + > Drop for LocalAssetTrader +{ + fn drop(&mut self) { + OnUnbalanced::on_unbalanced(Currency::issue(self.1)); + } +} diff --git a/runtime/crab/src/pallets/polkadot_xcm.rs b/runtime/crab/src/pallets/polkadot_xcm.rs index 9d3dcc7f1..5046b8de2 100644 --- a/runtime/crab/src/pallets/polkadot_xcm.rs +++ b/runtime/crab/src/pallets/polkadot_xcm.rs @@ -18,6 +18,8 @@ // darwinia use crate::*; +// substrate +use frame_support::traits::Currency; /// Means for transacting assets on this chain. pub type LocalAssetTransactor = xcm_builder::CurrencyAdapter< @@ -98,6 +100,25 @@ frame_support::parameter_types! { pub UnitWeightCost: u64 = 1_000_000_000; } +pub struct ToTreasury; +impl xcm_builder::TakeRevenue for ToTreasury { + fn take_revenue(revenue: xcm::latest::prelude::MultiAsset) { + if let xcm::latest::prelude::MultiAsset { + id: xcm::latest::prelude::Concrete(_location), + fun: xcm::latest::prelude::Fungible(amount), + } = revenue + { + let treasury_account = Treasury::account_id(); + let _ = Balances::deposit_creating(&treasury_account, amount); + + frame_support::log::trace!( + target: "xcm::weight", + "LocalAssetTrader::to_treasury amount: {amount:?}, treasury: {treasury_account:?}" + ); + } + } +} + pub struct XcmExecutorConfig; impl xcm_executor::Config for XcmExecutorConfig { type AssetClaims = PolkadotXcm; @@ -113,12 +134,13 @@ impl xcm_executor::Config for XcmExecutorConfig { type ResponseHandler = PolkadotXcm; type RuntimeCall = RuntimeCall; type SubscriptionService = PolkadotXcm; - type Trader = xcm_builder::UsingComponents< + type Trader = xcm_configs::LocalAssetTrader< ConstantMultiplier, AnchoringSelfReserve, AccountId, Balances, DealWithFees, + ToTreasury, >; type Weigher = xcm_builder::FixedWeightBounds; type XcmSender = XcmRouter; @@ -147,8 +169,6 @@ impl pallet_xcm::Config for Runtime { type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; type Weigher = xcm_builder::FixedWeightBounds; type XcmExecuteFilter = frame_support::traits::Everything; - // ^ Disable dispatchable execute on the XCM pallet. - // Needs to be `Everything` for local testing. type XcmExecutor = xcm_executor::XcmExecutor; type XcmReserveTransferFilter = frame_support::traits::Everything; type XcmRouter = XcmRouter; diff --git a/runtime/darwinia/src/pallets/polkadot_xcm.rs b/runtime/darwinia/src/pallets/polkadot_xcm.rs index b135b513b..907858780 100644 --- a/runtime/darwinia/src/pallets/polkadot_xcm.rs +++ b/runtime/darwinia/src/pallets/polkadot_xcm.rs @@ -18,6 +18,8 @@ // darwinia use crate::*; +// substrate +use frame_support::traits::Currency; /// Means for transacting assets on this chain. pub type LocalAssetTransactor = xcm_builder::CurrencyAdapter< @@ -98,6 +100,25 @@ frame_support::parameter_types! { pub UnitWeightCost: u64 = 1_000_000_000; } +pub struct ToTreasury; +impl xcm_builder::TakeRevenue for ToTreasury { + fn take_revenue(revenue: xcm::latest::prelude::MultiAsset) { + if let xcm::latest::prelude::MultiAsset { + id: xcm::latest::prelude::Concrete(_location), + fun: xcm::latest::prelude::Fungible(amount), + } = revenue + { + let treasury_account = Treasury::account_id(); + let _ = Balances::deposit_creating(&treasury_account, amount); + + frame_support::log::trace!( + target: "xcm::weight", + "LocalAssetTrader::to_treasury amount: {amount:?}, treasury: {treasury_account:?}" + ); + } + } +} + pub struct XcmExecutorConfig; impl xcm_executor::Config for XcmExecutorConfig { type AssetClaims = PolkadotXcm; @@ -113,12 +134,13 @@ impl xcm_executor::Config for XcmExecutorConfig { type ResponseHandler = PolkadotXcm; type RuntimeCall = RuntimeCall; type SubscriptionService = PolkadotXcm; - type Trader = xcm_builder::UsingComponents< + type Trader = xcm_configs::LocalAssetTrader< ConstantMultiplier, AnchoringSelfReserve, AccountId, Balances, DealWithFees, + ToTreasury, >; type Weigher = xcm_builder::FixedWeightBounds; type XcmSender = XcmRouter; @@ -147,8 +169,6 @@ impl pallet_xcm::Config for Runtime { type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; type Weigher = xcm_builder::FixedWeightBounds; type XcmExecuteFilter = frame_support::traits::Everything; - // ^ Disable dispatchable execute on the XCM pallet. - // Needs to be `Everything` for local testing. type XcmExecutor = xcm_executor::XcmExecutor; type XcmReserveTransferFilter = frame_support::traits::Everything; type XcmRouter = XcmRouter; diff --git a/runtime/pangolin/src/pallets/mod.rs b/runtime/pangolin/src/pallets/mod.rs index a1a9c5694..496d6304b 100644 --- a/runtime/pangolin/src/pallets/mod.rs +++ b/runtime/pangolin/src/pallets/mod.rs @@ -69,6 +69,7 @@ mod elections_phragmen; mod membership; mod treasury; +pub use treasury::*; mod tips; diff --git a/runtime/pangolin/src/pallets/polkadot_xcm.rs b/runtime/pangolin/src/pallets/polkadot_xcm.rs index 528bfc531..7a0c8f6d4 100644 --- a/runtime/pangolin/src/pallets/polkadot_xcm.rs +++ b/runtime/pangolin/src/pallets/polkadot_xcm.rs @@ -18,6 +18,8 @@ // darwinia use crate::*; +// substrate +use frame_support::traits::Currency; /// Means for transacting assets on this chain. pub type LocalAssetTransactor = xcm_builder::CurrencyAdapter< @@ -98,6 +100,25 @@ frame_support::parameter_types! { pub UnitWeightCost: u64 = 1_000_000_000; } +pub struct ToTreasury; +impl xcm_builder::TakeRevenue for ToTreasury { + fn take_revenue(revenue: xcm::latest::prelude::MultiAsset) { + if let xcm::latest::prelude::MultiAsset { + id: xcm::latest::prelude::Concrete(_location), + fun: xcm::latest::prelude::Fungible(amount), + } = revenue + { + let treasury_account = Treasury::account_id(); + let _ = Balances::deposit_creating(&treasury_account, amount); + + frame_support::log::trace!( + target: "xcm::weight", + "LocalAssetTrader::to_treasury amount: {amount:?}, treasury: {treasury_account:?}" + ); + } + } +} + pub struct XcmExecutorConfig; impl xcm_executor::Config for XcmExecutorConfig { type AssetClaims = PolkadotXcm; @@ -113,12 +134,13 @@ impl xcm_executor::Config for XcmExecutorConfig { type ResponseHandler = PolkadotXcm; type RuntimeCall = RuntimeCall; type SubscriptionService = PolkadotXcm; - type Trader = xcm_builder::UsingComponents< + type Trader = xcm_configs::LocalAssetTrader< ConstantMultiplier, AnchoringSelfReserve, AccountId, Balances, DealWithFees, + ToTreasury, >; type Weigher = xcm_builder::FixedWeightBounds; type XcmSender = XcmRouter; @@ -147,8 +169,6 @@ impl pallet_xcm::Config for Runtime { type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; type Weigher = xcm_builder::FixedWeightBounds; type XcmExecuteFilter = frame_support::traits::Everything; - // ^ Disable dispatchable execute on the XCM pallet. - // Needs to be `Everything` for local testing. type XcmExecutor = xcm_executor::XcmExecutor; type XcmReserveTransferFilter = frame_support::traits::Everything; type XcmRouter = XcmRouter;