diff --git a/Cargo.lock b/Cargo.lock index a612c239b0f..6ea9485d194 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12428,6 +12428,7 @@ dependencies = [ "sp-std", "sp-transaction-pool", "sp-version", + "sp-weights", "substrate-wasm-builder", "xcm", "xcm-builder", @@ -12494,6 +12495,7 @@ dependencies = [ "sp-std", "sp-transaction-pool", "sp-version", + "sp-weights", "substrate-wasm-builder", "xcm", "xcm-builder", diff --git a/parachains/common/src/xcm_config.rs b/parachains/common/src/xcm_config.rs index 753aa97c6fe..04f73c6b7e7 100644 --- a/parachains/common/src/xcm_config.rs +++ b/parachains/common/src/xcm_config.rs @@ -3,7 +3,7 @@ use core::{marker::PhantomData, ops::ControlFlow}; use frame_support::{ log, traits::{fungibles::Inspect, tokens::BalanceConversion, ContainsPair}, - weights::{Weight, WeightToFee, WeightToFeePolynomial}, + weights::Weight, }; use sp_runtime::traits::Get; use xcm::{latest::prelude::*, CreateMatcher, MatchXcm}; @@ -95,7 +95,7 @@ impl > for AssetFeeAsExistentialDepositMultiplier where Runtime: pallet_assets::Config, - WeightToFee: WeightToFeePolynomial, + WeightToFee: frame_support::weights::WeightToFee, BalanceConverter: BalanceConversion< CurrencyBalance, >::AssetId, diff --git a/parachains/runtimes/assets/statemine/Cargo.toml b/parachains/runtimes/assets/statemine/Cargo.toml index 0f0921976a8..d114d06ba02 100644 --- a/parachains/runtimes/assets/statemine/Cargo.toml +++ b/parachains/runtimes/assets/statemine/Cargo.toml @@ -28,6 +28,7 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", default-fea pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } +pallet-state-trie-migration = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master", optional = true } pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } pallet-transaction-payment = { 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" } @@ -44,7 +45,7 @@ sp-session = { git = "https://github.com/paritytech/substrate", default-features sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } -pallet-state-trie-migration = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master", optional = true } +sp-weights = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } # Polkadot kusama-runtime-constants = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } diff --git a/parachains/runtimes/assets/statemine/src/constants.rs b/parachains/runtimes/assets/statemine/src/constants.rs index 6dccf0089ca..95e8c166a96 100644 --- a/parachains/runtimes/assets/statemine/src/constants.rs +++ b/parachains/runtimes/assets/statemine/src/constants.rs @@ -34,8 +34,8 @@ pub mod currency { /// Fee-related. pub mod fee { use frame_support::weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, + constants::ExtrinsicBaseWeight, FeePolynomial, Weight, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, }; use polkadot_core_primitives::Balance; use smallvec::smallvec; @@ -55,13 +55,46 @@ pub mod fee { /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference 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 q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// 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 = super::currency::CENTS; + let q = 10_000; + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, diff --git a/parachains/runtimes/assets/statemine/src/lib.rs b/parachains/runtimes/assets/statemine/src/lib.rs index 446ae77bc2b..d27796b8aed 100644 --- a/parachains/runtimes/assets/statemine/src/lib.rs +++ b/parachains/runtimes/assets/statemine/src/lib.rs @@ -1125,3 +1125,59 @@ fn ensure_key_ss58() { assert_eq!(acc, RootMigController::sorted_members()[0]); //panic!("{:x?}", acc); } + +#[cfg(test)] +mod tests { + use super::{constants::fee, *}; + use crate::{CENTS, MILLICENTS}; + use sp_runtime::traits::Zero; + use sp_weights::WeightToFee; + + /// We can fit at least 1000 transfers in a block. + #[test] + fn sane_block_weight() { + use pallet_balances::WeightInfo; + let block = RuntimeBlockWeights::get().max_block; + let base = RuntimeBlockWeights::get().get(DispatchClass::Normal).base_extrinsic; + let transfer = base + weights::pallet_balances::WeightInfo::::transfer(); + + let fit = block.checked_div_per_component(&transfer).unwrap_or_default(); + assert!(fit >= 1000, "{} should be at least 1000", fit); + } + + /// The fee for one transfer is at most 1 CENT. + #[test] + fn sane_transfer_fee() { + use pallet_balances::WeightInfo; + let base = RuntimeBlockWeights::get().get(DispatchClass::Normal).base_extrinsic; + let transfer = base + weights::pallet_balances::WeightInfo::::transfer(); + + let fee: Balance = fee::WeightToFee::weight_to_fee(&transfer); + assert!(fee <= CENTS, "{} MILLICENTS should be at most 1000", fee / MILLICENTS); + } + + /// Weight is being charged for both dimensions. + #[test] + fn weight_charged_for_both_components() { + let fee: Balance = fee::WeightToFee::weight_to_fee(&Weight::from_parts(10_000, 0)); + assert!(!fee.is_zero(), "Charges for ref time"); + + let fee: Balance = fee::WeightToFee::weight_to_fee(&Weight::from_parts(0, 10_000)); + assert_eq!(fee, CENTS, "10kb maps to CENT"); + } + + /// Filling up a block by proof size is at most 30 times more expensive than ref time. + /// + /// This is just a sanity check. + #[test] + fn full_block_fee_ratio() { + let block = RuntimeBlockWeights::get().max_block; + let time_fee: Balance = fee::WeightToFee::weight_to_fee(&block.without_proof_size()); + let proof_fee: Balance = fee::WeightToFee::weight_to_fee(&block.without_ref_time()); + + let proof_o_time = proof_fee.checked_div(time_fee).unwrap_or_default(); + assert!(proof_o_time <= 30, "{} should be at most 30", proof_o_time); + let time_o_proof = time_fee.checked_div(proof_fee).unwrap_or_default(); + assert!(time_o_proof <= 30, "{} should be at most 30", time_o_proof); + } +} diff --git a/parachains/runtimes/assets/statemint/Cargo.toml b/parachains/runtimes/assets/statemint/Cargo.toml index f6d54cbd85f..89d08d23ab3 100644 --- a/parachains/runtimes/assets/statemint/Cargo.toml +++ b/parachains/runtimes/assets/statemint/Cargo.toml @@ -44,6 +44,7 @@ sp-session = { git = "https://github.com/paritytech/substrate", default-features sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } +sp-weights = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } # Polkadot pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } diff --git a/parachains/runtimes/assets/statemint/src/constants.rs b/parachains/runtimes/assets/statemint/src/constants.rs index 393f62858cd..35e7f03695b 100644 --- a/parachains/runtimes/assets/statemint/src/constants.rs +++ b/parachains/runtimes/assets/statemint/src/constants.rs @@ -34,12 +34,13 @@ pub mod currency { /// Fee-related. pub mod fee { use frame_support::weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, + constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, }; use polkadot_core_primitives::Balance; use smallvec::smallvec; pub use sp_runtime::Perbill; + use sp_weights::Weight; /// The block saturation level. Fees will be updates based on this value. pub const TARGET_BLOCK_FULLNESS: Perbill = Perbill::from_percent(25); @@ -55,13 +56,46 @@ pub mod fee { /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: // in Statemint, we map to 1/10 of that, or 1/100 CENT let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// 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 = super::currency::CENTS; + let q = 10_000; + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, diff --git a/parachains/runtimes/assets/statemint/src/lib.rs b/parachains/runtimes/assets/statemint/src/lib.rs index c3813d2a7f4..7bc1dbbc160 100644 --- a/parachains/runtimes/assets/statemint/src/lib.rs +++ b/parachains/runtimes/assets/statemint/src/lib.rs @@ -1077,3 +1077,59 @@ cumulus_pallet_parachain_system::register_validate_block! { BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, CheckInherents = CheckInherents, } + +#[cfg(test)] +mod tests { + use super::{constants::fee, *}; + use crate::{CENTS, MILLICENTS}; + use sp_runtime::traits::Zero; + use sp_weights::WeightToFee; + + /// We can fit at least 1000 transfers in a block. + #[test] + fn sane_block_weight() { + use pallet_balances::WeightInfo; + let block = RuntimeBlockWeights::get().max_block; + let base = RuntimeBlockWeights::get().get(DispatchClass::Normal).base_extrinsic; + let transfer = base + weights::pallet_balances::WeightInfo::::transfer(); + + let fit = block.checked_div_per_component(&transfer).unwrap_or_default(); + assert!(fit >= 1000, "{} should be at least 1000", fit); + } + + /// The fee for one transfer is at most 1 CENT. + #[test] + fn sane_transfer_fee() { + use pallet_balances::WeightInfo; + let base = RuntimeBlockWeights::get().get(DispatchClass::Normal).base_extrinsic; + let transfer = base + weights::pallet_balances::WeightInfo::::transfer(); + + let fee: Balance = fee::WeightToFee::weight_to_fee(&transfer); + assert!(fee <= CENTS, "{} MILLICENTS should be at most 1000", fee / MILLICENTS); + } + + /// Weight is being charged for both dimensions. + #[test] + fn weight_charged_for_both_components() { + let fee: Balance = fee::WeightToFee::weight_to_fee(&Weight::from_parts(10_000, 0)); + assert!(!fee.is_zero(), "Charges for ref time"); + + let fee: Balance = fee::WeightToFee::weight_to_fee(&Weight::from_parts(0, 10_000)); + assert_eq!(fee, CENTS, "10kb maps to CENT"); + } + + /// Filling up a block by proof size is at most 30 times more expensive than ref time. + /// + /// This is just a sanity check. + #[test] + fn full_block_fee_ratio() { + let block = RuntimeBlockWeights::get().max_block; + let time_fee: Balance = fee::WeightToFee::weight_to_fee(&block.without_proof_size()); + let proof_fee: Balance = fee::WeightToFee::weight_to_fee(&block.without_ref_time()); + + let proof_o_time = proof_fee.checked_div(time_fee).unwrap_or_default(); + assert!(proof_o_time <= 30, "{} should be at most 30", proof_o_time); + let time_o_proof = time_fee.checked_div(proof_fee).unwrap_or_default(); + assert!(time_o_proof <= 30, "{} should be at most 30", time_o_proof); + } +} diff --git a/parachains/runtimes/assets/westmint/src/constants.rs b/parachains/runtimes/assets/westmint/src/constants.rs index 8a94ad2ad9f..11e6d1bf35b 100644 --- a/parachains/runtimes/assets/westmint/src/constants.rs +++ b/parachains/runtimes/assets/westmint/src/constants.rs @@ -33,9 +33,12 @@ pub mod currency { /// Fee-related. pub mod fee { - use frame_support::weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, + use frame_support::{ + pallet_prelude::Weight, + weights::{ + constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, }; use polkadot_core_primitives::Balance; use smallvec::smallvec; @@ -55,13 +58,46 @@ pub mod fee { /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in Statemint, we map to 1/10 of that, or 1/100 CENT + // in Westend, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + // in Westmint, we map to 1/10 of that, or 1/100 CENT let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// 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 = super::currency::CENTS; + let q = 10_000; + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, diff --git a/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/constants.rs b/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/constants.rs index c4943f85232..257d0da755b 100644 --- a/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/constants.rs +++ b/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/constants.rs @@ -32,9 +32,12 @@ pub mod currency { /// Fee-related. pub mod fee { - use frame_support::weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, + use frame_support::{ + pallet_prelude::Weight, + weights::{ + constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, }; use polkadot_core_primitives::Balance; use smallvec::smallvec; @@ -51,13 +54,46 @@ pub mod fee { /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference 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 BridgeHub, we map to 1/10 of that, or 1/100 CENT + // in Bridge Hub, we map to 1/10 of that, or 1/100 CENT let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// 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 = super::currency::CENTS; + let q = 10_000; + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, diff --git a/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/constants.rs b/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/constants.rs index de22cf7883a..388d23e6441 100644 --- a/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/constants.rs +++ b/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/constants.rs @@ -32,9 +32,12 @@ pub mod currency { /// Fee-related. pub mod fee { - use frame_support::weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, + use frame_support::{ + pallet_prelude::Weight, + weights::{ + constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, }; use polkadot_core_primitives::Balance; use smallvec::smallvec; @@ -51,13 +54,46 @@ pub mod fee { /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in BridgeHub, we map to 1/10 of that, or 1/100 CENT + // in Bridge Hub, we map to 1/10 of that, or 1/100 CENT let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// 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 = super::currency::CENTS; + let q = 10_000; + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, diff --git a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/constants.rs b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/constants.rs index 549e549d38a..86cf8d6f7d3 100644 --- a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/constants.rs +++ b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/constants.rs @@ -30,9 +30,12 @@ pub mod currency { } pub mod fee { - use frame_support::weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, + use frame_support::{ + pallet_prelude::Weight, + weights::{ + constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, }; use polkadot_core_primitives::Balance; use smallvec::smallvec; @@ -52,13 +55,46 @@ pub mod fee { /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - // in BridgeHub, we map to 1/10 of that, or 1/100 CENT + // in Bridge Hub, we map to 1/10 of that, or 1/100 CENT let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// 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 = super::currency::CENTS; + let q = 10_000; + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, diff --git a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index bf86b16dcef..6957edc8998 100644 --- a/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -46,10 +46,11 @@ use constants::currency::*; use frame_support::{ construct_runtime, dispatch::DispatchClass, + pallet_prelude::Weight, parameter_types, traits::{ConstU32, ConstU64, ConstU8, Everything}, weights::{ - ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, + ConstantMultiplier, FeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }, PalletId, @@ -129,13 +130,44 @@ pub type Executive = frame_executive::Executive< /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } +} + +/// Maps the reference time component of `Weight` to a fee. +pub struct RefTimeToFee; +impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: - // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT let p = MILLIUNIT / 10; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} + +/// 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/10 MILLIUNIT. + let p = MILLIUNIT / 10; + let q = 10_000; + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, diff --git a/parachains/runtimes/collectives/collectives-polkadot/src/constants.rs b/parachains/runtimes/collectives/collectives-polkadot/src/constants.rs index cc41d5c6378..e9709519827 100644 --- a/parachains/runtimes/collectives/collectives-polkadot/src/constants.rs +++ b/parachains/runtimes/collectives/collectives-polkadot/src/constants.rs @@ -43,9 +43,12 @@ pub mod currency { /// Fee-related. pub mod fee { - use frame_support::weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, + use frame_support::{ + pallet_prelude::Weight, + weights::{ + constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, }; use polkadot_core_primitives::Balance; use smallvec::smallvec; @@ -65,13 +68,46 @@ pub mod fee { /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { // in Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: // in a parachain, we map to 1/10 of that, or 1/100 CENT let p = super::currency::CENTS; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// 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 = super::currency::CENTS; + let q = 10_000; + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, diff --git a/parachains/runtimes/contracts/contracts-rococo/src/constants.rs b/parachains/runtimes/contracts/contracts-rococo/src/constants.rs index 6dccf0089ca..4598ddaa264 100644 --- a/parachains/runtimes/contracts/contracts-rococo/src/constants.rs +++ b/parachains/runtimes/contracts/contracts-rococo/src/constants.rs @@ -33,9 +33,12 @@ pub mod currency { /// Fee-related. pub mod fee { - use frame_support::weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, + use frame_support::{ + pallet_prelude::Weight, + weights::{ + constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, }; use polkadot_core_primitives::Balance; use smallvec::smallvec; @@ -55,13 +58,46 @@ pub mod fee { /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference 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 q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// 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 = super::currency::CENTS; + let q = 10_000; + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, diff --git a/parachains/runtimes/testing/penpal/src/lib.rs b/parachains/runtimes/testing/penpal/src/lib.rs index a727bb27dba..b3cf2e5a654 100644 --- a/parachains/runtimes/testing/penpal/src/lib.rs +++ b/parachains/runtimes/testing/penpal/src/lib.rs @@ -34,11 +34,12 @@ use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::{ construct_runtime, dispatch::DispatchClass, + pallet_prelude::Weight, parameter_types, traits::{AsEnsureOriginWithArg, ConstU32, ConstU64, ConstU8, Everything}, weights::{ - constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, Weight, WeightToFeeCoefficient, - WeightToFeeCoefficients, WeightToFeePolynomial, + constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, FeePolynomial, + WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, }, PalletId, }; @@ -149,13 +150,26 @@ pub type Executive = frame_executive::Executive< /// - Setting it to `0` will essentially disable the weight fee. /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } +} + +/// Maps the reference time component of `Weight` to a fee. +pub struct RefTimeToFee; +impl WeightToFeePolynomial for RefTimeToFee { type Balance = Balance; fn polynomial() -> WeightToFeeCoefficients { - // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: - // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT let p = MILLIUNIT / 10; let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + smallvec![WeightToFeeCoefficient { degree: 1, negative: false, @@ -165,6 +179,23 @@ impl WeightToFeePolynomial for WeightToFee { } } +/// 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 = MILLIUNIT / 10; + let q = 10_000; + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades