common_runtime/
fee.rs

1use crate::constants::currency::CENTS;
2
3use frame_support::{
4	sp_runtime::Perbill,
5	weights::{WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial},
6};
7
8use common_primitives::node::Balance;
9
10use super::weights::extrinsic_weights::ExtrinsicBaseWeight;
11
12use smallvec::smallvec;
13
14/// Handles converting a weight scalar to a fee value, based on the scale and granularity of the
15/// node's balance type.
16///
17/// This should typically create a mapping between the following ranges:
18///   - `[0, MAXIMUM_BLOCK_WEIGHT]` 1_000_000_000_000
19///   - `[Balance::min, Balance::max]`
20///
21/// Yet, it can be used for any other sort of change to weight-fee. Some examples being:
22///   - Setting it to `0` will essentially disable the weight fee.
23///   - Setting it to `1` will cause the literal `#[weight = x]` values to be charged.
24///
25/// Warning: Changing this function will also change the static capacity weights.
26pub struct WeightToFee;
27impl WeightToFeePolynomial for WeightToFee {
28	type Balance = Balance;
29	fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
30		// In Polkadot extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT
31		let p = CENTS;
32		let q = 10 * Balance::from(ExtrinsicBaseWeight::get().ref_time());
33		smallvec![WeightToFeeCoefficient {
34			degree: 1,
35			negative: false,
36			coeff_frac: Perbill::from_rational(p % q, q),
37			coeff_integer: p / q,
38		}]
39	}
40}
41
42#[cfg(test)]
43mod test {
44	use super::WeightToFee;
45	use crate::{
46		constants::{
47			currency::{CENTS, DOLLARS, MILLICENTS},
48			MAXIMUM_BLOCK_WEIGHT,
49		},
50		fee::Balance,
51		weights::extrinsic_weights::ExtrinsicBaseWeight,
52	};
53
54	use frame_support::weights::WeightToFee as WeightToFeeT;
55
56	#[test]
57	// Test that the fee for `MAXIMUM_BLOCK_WEIGHT` of weigh has sane bounds.
58	fn full_block_fee_is_correct() {
59		let full_block = WeightToFee::weight_to_fee(&MAXIMUM_BLOCK_WEIGHT);
60		// A bounded assertion to consider changes in generated extrinsic base weight.
61		assert!(full_block >= 2 * 150 * CENTS);
62		assert!(full_block <= 50 * DOLLARS);
63	}
64	#[test]
65	// This function tests that the fee for `ExtrinsicBaseWeight` of weight is correct
66	fn extrinsic_base_fee_is_correct() {
67		// `ExtrinsicBaseWeight` should cost 1/10 of a CENT
68		let x = WeightToFee::weight_to_fee(&ExtrinsicBaseWeight::get());
69		let y = CENTS / 10;
70		assert!(x.max(y) - x.min(y) < MILLICENTS);
71	}
72
73	#[test]
74	fn check_weight() {
75		let p = CENTS / 10;
76		let q = Balance::from(ExtrinsicBaseWeight::get().ref_time());
77
78		assert_eq!(p, 100_000);
79
80		assert!(q >= 75_000_000);
81		assert!(q <= 130_000_000);
82
83		assert_eq!(p / q, Balance::from(0u128));
84	}
85}