From 85b99033f0635738e1017d41af0d8806a9a1778f Mon Sep 17 00:00:00 2001 From: Valentin Fernandez <33705477+valentinfernandez1@users.noreply.github.com> Date: Thu, 15 Jun 2023 12:39:17 -0300 Subject: [PATCH] Refactor `WeightToFee` to include ProofSize (#215) * Removed FixedRateOfFungibles * fmt * added comments * fmt * removed unused imports * fmt * removed allow unpaid execution from rockmine following PR #211 * Include new traders from PR #221 * minor fixes * minor fixes * fmt --- Cargo.lock | 1 + Cargo.toml | 1 + runtime/stout/src/xcm_config.rs | 19 +++------- runtime/trappist/Cargo.toml | 1 + runtime/trappist/src/constants.rs | 61 +++++++++++++++++++++++++++--- runtime/trappist/src/impls.rs | 33 +++++++++++++++- runtime/trappist/src/xcm_config.rs | 41 +++++++++++--------- 7 files changed, 118 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71dac2c7..5b4f3fd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12440,6 +12440,7 @@ dependencies = [ "serde", "smallvec", "sp-api", + "sp-arithmetic", "sp-block-builder", "sp-consensus-aura", "sp-core", diff --git a/Cargo.toml b/Cargo.toml index bf8244ff..e4f2f1f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,6 +99,7 @@ sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", bra # Substrate Runtime sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40", default-features = false } sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" } sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" } sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" } diff --git a/runtime/stout/src/xcm_config.rs b/runtime/stout/src/xcm_config.rs index 0ced3959..f11165c2 100644 --- a/runtime/stout/src/xcm_config.rs +++ b/runtime/stout/src/xcm_config.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{constants::fee::default_fee_per_second, AllPalletsWithSystem}; +use crate::AllPalletsWithSystem; use super::{ AccountId, Assets, Balance, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, @@ -45,9 +45,9 @@ use xcm::latest::{prelude::*, Fungibility::Fungible, MultiAsset, MultiLocation}; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex, - ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, - FungiblesAdapter, IsConcrete, MintLocation, NativeAsset, NoChecking, ParentAsSuperuser, - ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, + IsConcrete, MintLocation, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, }; @@ -194,11 +194,6 @@ parameter_types! { // Statemine's Assets pallet index pub StatemineAssetsPalletLocation: MultiLocation = MultiLocation::new(1, X2(Parachain(1000), PalletInstance(50))); - pub XUsdPerSecond: (AssetId, u128, u128) = ( - MultiLocation::new(1, X3(Parachain(1000), PalletInstance(50), GeneralIndex(1))).into(), - default_fee_per_second() * 10, - 0 - ); } //- From PR https://github.com/paritytech/cumulus/pull/936 @@ -240,10 +235,8 @@ impl xcm_executor::Config for XcmConfig { type IsTeleporter = (); // Teleporting is disabled. type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = ( - FixedRateOfFungible, - UsingComponents>, - ); + type Trader = + UsingComponents>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; type AssetClaims = PolkadotXcm; diff --git a/runtime/trappist/Cargo.toml b/runtime/trappist/Cargo.toml index 72aeddc1..2f380526 100644 --- a/runtime/trappist/Cargo.toml +++ b/runtime/trappist/Cargo.toml @@ -24,6 +24,7 @@ smallvec = { workspace = true } # Substrate Dependencies ## Substrate Primitive Dependencies sp-api = { workspace = true } +sp-arithmetic = { workspace = true } sp-block-builder = { workspace = true } sp-consensus-aura = { workspace = true } sp-core = { workspace = true } diff --git a/runtime/trappist/src/constants.rs b/runtime/trappist/src/constants.rs index 8fdb7b30..3ce0eb41 100644 --- a/runtime/trappist/src/constants.rs +++ b/runtime/trappist/src/constants.rs @@ -37,20 +37,21 @@ pub mod currency { pub mod fee { use frame_support::weights::{ constants::{ExtrinsicBaseWeight, WEIGHT_REF_TIME_PER_SECOND}, - WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, + Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }; use polkadot_core_primitives::Balance; use smallvec::smallvec; + pub use sp_runtime::Perbill; + use sp_runtime::SaturatedConversion; + + use crate::impls::WeightCoefficientCalc; use super::currency::CENTS; /// The block saturation level. Fees will be updates based on this value. pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); - //TODO: Update WeightToFee functionality to match cummulus implementation (Should be done in a - // separated issue) - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the /// node's balance type. /// @@ -61,13 +62,43 @@ pub mod fee { /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. + /// + /// TODO: Once the runtime is upgraded to polkadot v0.9.42 or above refactor this using + /// the FeePolynomial struct that already includes the methods to make this calculations + /// and remove the custom WeightCoefficientCalc inside ./trappist/src/impls.rs pub struct WeightToFee; - impl WeightToFeePolynomial for WeightToFee { + impl frame_support::weights::WeightToFee for WeightToFee { + type Balance = Balance; + + fn weight_to_fee(weight: &Weight) -> Self::Balance { + let ref_time = Balance::saturated_from(weight.ref_time()); + let proof_size = Balance::saturated_from(weight.proof_size()); + + let ref_polynomial = RefTimeToFee::polynomial(); + let proof_polynomial = ProofSizeToFee::polynomial(); + + // Get fee amount from ref_time based on the RefTime polynomial + let ref_fee: Balance = + ref_polynomial.iter().fold(0, |acc, term| term.saturating_eval(acc, ref_time)); + + // Get fee amount from proof_size based on the ProofSize polynomial + let proof_fee: Balance = proof_polynomial + .iter() + .fold(0, |acc, term| term.saturating_eval(acc, proof_size)); + + // Take the maximum instead of the sum to charge by the more scarce resource. + ref_fee.max(proof_fee) + } + } + + /// Maps the Ref time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { // in Kusama, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: // in Statemine, we map to 1/10 of that, or 1/100 CENT - let p = super::currency::CENTS; + let p = CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); smallvec![WeightToFeeCoefficient { degree: 1, @@ -78,6 +109,24 @@ pub mod fee { } } + /// Maps the proof size component of `Weight` to a fee. + pub struct ProofSizeToFee; + impl WeightToFeePolynomial for ProofSizeToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // Map 10kb proof to 1 CENT. + let p = CENTS; + let q = 10_000; + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + pub fn base_tx_fee() -> Balance { CENTS / 10 } diff --git a/runtime/trappist/src/impls.rs b/runtime/trappist/src/impls.rs index 74fbc6ed..2ef2fb10 100644 --- a/runtime/trappist/src/impls.rs +++ b/runtime/trappist/src/impls.rs @@ -22,10 +22,11 @@ use super::*; use cumulus_primitives_core::{relay_chain::BlockNumber as RelayBlockNumber, DmpMessageHandler}; use frame_support::{ traits::{Contains, Currency, Imbalance, OnUnbalanced}, - weights::Weight, + weights::{Weight, WeightToFeeCoefficient}, }; pub use log; -use sp_runtime::DispatchResult; +use sp_arithmetic::traits::{BaseArithmetic, Unsigned}; +use sp_runtime::{DispatchResult, SaturatedConversion}; use sp_std::marker::PhantomData; @@ -112,6 +113,34 @@ impl xcm_primitives::PauseXcmExecution for XcmExecutionManager { XcmpQueue::resume_xcm_execution(RuntimeOrigin::root()) } } + +pub trait WeightCoefficientCalc { + fn saturating_eval(&self, result: Balance, x: Balance) -> Balance; +} + +impl WeightCoefficientCalc for WeightToFeeCoefficient +where + Balance: BaseArithmetic + From + Copy + Unsigned + SaturatedConversion, +{ + fn saturating_eval(&self, mut result: Balance, x: Balance) -> Balance { + let power = x.saturating_pow(self.degree.into()); + + let frac = self.coeff_frac * power; // Overflow safe since coeff_frac is strictly less than 1. + let integer = self.coeff_integer.saturating_mul(power); + // Do not add them together here to avoid an underflow. + + if self.negative { + result = result.saturating_sub(frac); + result = result.saturating_sub(integer); + } else { + result = result.saturating_add(frac); + result = result.saturating_add(integer); + } + + result + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/runtime/trappist/src/xcm_config.rs b/runtime/trappist/src/xcm_config.rs index 32a0059b..96e616f6 100644 --- a/runtime/trappist/src/xcm_config.rs +++ b/runtime/trappist/src/xcm_config.rs @@ -16,13 +16,15 @@ // limitations under the License. use crate::{ - constants::fee::default_fee_per_second, impls::ToAuthor, weights::TrappistDropAssetsWeigher, + constants::fee::{default_fee_per_second, WeightToFee}, + impls::ToAuthor, + weights::TrappistDropAssetsWeigher, AllPalletsWithSystem, }; use super::{ AccountId, AssetRegistry, Assets, Balance, Balances, ParachainInfo, ParachainSystem, - PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, + PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, XcmpQueue, }; use frame_support::{ match_types, parameter_types, @@ -47,12 +49,11 @@ use xcm::latest::{prelude::*, Fungibility::Fungible, MultiAsset, MultiLocation}; use xcm_builder::{ AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex, - ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, - FungiblesAdapter, IsConcrete, MintLocation, NativeAsset, NoChecking, ParentAsSuperuser, - ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - UsingComponents, WeightInfoBounds, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter, EnsureXcmOrigin, + FixedRateOfFungible, FungiblesAdapter, IsConcrete, MintLocation, NativeAsset, NoChecking, + ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WeightInfoBounds, }; use xcm_executor::XcmExecutor; @@ -208,7 +209,6 @@ pub type Barrier = DenyThenTry< AllowTopLevelPaidExecutionFrom, // Parent and its exec plurality get free execution AllowUnpaidExecutionFrom, - AllowUnpaidExecutionFrom, // Expected responses are OK. AllowKnownQueryResponses, // Subscriptions for version tracking are OK. @@ -222,11 +222,13 @@ parameter_types! { // Rockmine's Assets pallet index pub RockmineAssetsPalletLocation: MultiLocation = MultiLocation::new(1, X2(Parachain(1000), PalletInstance(50))); - pub XUsdPerSecond: (xcm::v3::AssetId, u128, u128) = ( - MultiLocation::new(1, X3(Parachain(1000), PalletInstance(50), GeneralIndex(1))).into(), + pub RUsdPerSecond: (xcm::v3::AssetId, u128, u128) = ( + MultiLocation::new(1, X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984))).into(), default_fee_per_second() * 10, - 0 + 0u128 ); + /// Roc = 7 RUSD + pub RocPerSecond: (xcm::v3::AssetId, u128,u128) = (MultiLocation::parent().into(), default_fee_per_second() * 70, 0u128); } //- From PR https://github.com/paritytech/cumulus/pull/936 @@ -253,7 +255,14 @@ impl> ContainsPair for ReserveA } } -//-- +pub type Traders = ( + // RUSD + FixedRateOfFungible, + // Roc + FixedRateOfFungible, + // Everything else + UsingComponents>, +); pub type Reserves = (NativeAsset, ReserveAssetsFrom); @@ -271,11 +280,7 @@ impl xcm_executor::Config for XcmConfig { RuntimeCall, MaxInstructions, >; - //TODO: Modify current config of Trader removing XUsdPerSecond Implementation - type Trader = ( - FixedRateOfFungible, - UsingComponents>, - ); + type Trader = Traders; type ResponseHandler = PolkadotXcm; type AssetTrap = TrappistDropAssets< AssetIdForTrustBackedAssets,