1
// This file is part of Substrate.
2

            
3
// Copyright (C) Parity Technologies (UK) Ltd.
4
// SPDX-License-Identifier: Apache-2.0
5

            
6
// Licensed under the Apache License, Version 2.0 (the "License");
7
// you may not use this file except in compliance with the License.
8
// You may obtain a copy of the License at
9
//
10
// 	http://www.apache.org/licenses/LICENSE-2.0
11
//
12
// Unless required by applicable law or agreed to in writing, software
13
// distributed under the License is distributed on an "AS IS" BASIS,
14
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
// See the License for the specific language governing permissions and
16
// limitations under the License.
17

            
18
//! # Transaction Payment Pallet
19
//!
20
//! This pallet provides the basic logic needed to pay the absolute minimum amount needed for a
21
//! transaction to be included. This includes:
22
//!   - _base fee_: This is the minimum amount a user pays for a transaction. It is declared
23
//! 	as a base _weight_ in the runtime and converted to a fee using `WeightToFee`.
24
//!   - _weight fee_: A fee proportional to amount of weight a transaction consumes.
25
//!   - _length fee_: A fee proportional to the encoded length of the transaction.
26
//!   - _tip_: An optional tip. Tip increases the priority of the transaction, giving it a higher
27
//!     chance to be included by the transaction queue.
28
//!
29
//! The base fee and adjusted weight and length fees constitute the _inclusion fee_, which is
30
//! the minimum fee for a transaction to be included in a block.
31
//!
32
//! The formula of final fee:
33
//!   ```ignore
34
//!   inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee];
35
//!   final_fee = inclusion_fee + tip;
36
//!   ```
37
//!
38
//!   - `targeted_fee_adjustment`: This is a multiplier that can tune the final fee based on
39
//! 	the congestion of the network.
40
//!
41
//! Additionally, this pallet allows one to configure:
42
//!   - The mapping between one unit of weight to one unit of fee via [`Config::WeightToFee`].
43
//!   - A means of updating the fee for the next block, via defining a multiplier, based on the
44
//!     final state of the chain at the end of the previous block. This can be configured via
45
//!     [`Config::FeeMultiplierUpdate`]
46
//!   - How the fees are paid via [`Config::OnChargeTransaction`].
47

            
48
#![cfg_attr(not(feature = "std"), no_std)]
49

            
50
use codec::{Decode, Encode, MaxEncodedLen};
51
use scale_info::TypeInfo;
52

            
53
use frame_support::{
54
	dispatch::{
55
		DispatchClass, DispatchInfo, DispatchResult, GetDispatchInfo, Pays, PostDispatchInfo,
56
	},
57
	traits::{Defensive, EstimateCallFee, Get},
58
	weights::{Weight, WeightToFee},
59
};
60
pub use pallet::*;
61
pub use payment::*;
62
use sp_runtime::{
63
	traits::{
64
		Convert, DispatchInfoOf, Dispatchable, One, PostDispatchInfoOf, SaturatedConversion,
65
		Saturating, SignedExtension, Zero,
66
	},
67
	transaction_validity::{
68
		TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction,
69
	},
70
	FixedPointNumber, FixedU128, Perbill, Perquintill, RuntimeDebug,
71
};
72
pub use types::{FeeDetails, InclusionFee, RuntimeDispatchInfo};
73

            
74
#[cfg(test)]
75
mod mock;
76
#[cfg(test)]
77
mod tests;
78

            
79
mod payment;
80
mod types;
81

            
82
/// Fee multiplier.
83
pub type Multiplier = FixedU128;
84

            
85
type BalanceOf<T> = <<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::Balance;
86

            
87
/// A struct to update the weight multiplier per block. It implements `Convert<Multiplier,
88
/// Multiplier>`, meaning that it can convert the previous multiplier to the next one. This should
89
/// be called on `on_finalize` of a block, prior to potentially cleaning the weight data from the
90
/// system pallet.
91
///
92
/// given:
93
/// 	s = previous block weight
94
/// 	s'= ideal block weight
95
/// 	m = maximum block weight
96
/// 		diff = (s - s')/m
97
/// 		v = 0.00001
98
/// 		t1 = (v * diff)
99
/// 		t2 = (v * diff)^2 / 2
100
/// 	then:
101
/// 	next_multiplier = prev_multiplier * (1 + t1 + t2)
102
///
103
/// Where `(s', v)` must be given as the `Get` implementation of the `T` generic type. Moreover, `M`
104
/// must provide the minimum allowed value for the multiplier. Note that a runtime should ensure
105
/// with tests that the combination of this `M` and `V` is not such that the multiplier can drop to
106
/// zero and never recover.
107
///
108
/// Note that `s'` is interpreted as a portion in the _normal transaction_ capacity of the block.
109
/// For example, given `s' == 0.25` and `AvailableBlockRatio = 0.75`, then the target fullness is
110
/// _0.25 of the normal capacity_ and _0.1875 of the entire block_.
111
///
112
/// Since block weight is multi-dimension, we use the scarcer resource, referred as limiting
113
/// dimension, for calculation of fees. We determine the limiting dimension by comparing the
114
/// dimensions using the ratio of `dimension_value / max_dimension_value` and selecting the largest
115
/// ratio. For instance, if a block is 30% full based on `ref_time` and 25% full based on
116
/// `proof_size`, we identify `ref_time` as the limiting dimension, indicating that the block is 30%
117
/// full.
118
///
119
/// This implementation implies the bound:
120
/// - `v ≤ p / k * (s − s')`
121
/// - or, solving for `p`: `p >= v * k * (s - s')`
122
///
123
/// where `p` is the amount of change over `k` blocks.
124
///
125
/// Hence:
126
/// - in a fully congested chain: `p >= v * k * (1 - s')`.
127
/// - in an empty chain: `p >= v * k * (-s')`.
128
///
129
/// For example, when all blocks are full and there are 28800 blocks per day (default in
130
/// `substrate-node`) and v == 0.00001, s' == 0.1875, we'd have:
131
///
132
/// p >= 0.00001 * 28800 * 0.8125
133
/// p >= 0.234
134
///
135
/// Meaning that fees can change by around ~23% per day, given extreme congestion.
136
///
137
/// More info can be found at:
138
/// <https://research.web3.foundation/en/latest/polkadot/overview/2-token-economics.html>
139
pub struct TargetedFeeAdjustment<T, S, V, M, X>(core::marker::PhantomData<(T, S, V, M, X)>);
140

            
141
/// Something that can convert the current multiplier to the next one.
142
pub trait MultiplierUpdate: Convert<Multiplier, Multiplier> {
143
	/// Minimum multiplier. Any outcome of the `convert` function should be at least this.
144
	fn min() -> Multiplier;
145
	/// Maximum multiplier. Any outcome of the `convert` function should be less or equal this.
146
	fn max() -> Multiplier;
147
	/// Target block saturation level
148
	fn target() -> Perquintill;
149
	/// Variability factor
150
	fn variability() -> Multiplier;
151
}
152

            
153
impl MultiplierUpdate for () {
154
	fn min() -> Multiplier {
155
		Default::default()
156
	}
157
	fn max() -> Multiplier {
158
		<Multiplier as sp_runtime::traits::Bounded>::max_value()
159
	}
160
	fn target() -> Perquintill {
161
		Default::default()
162
	}
163
	fn variability() -> Multiplier {
164
		Default::default()
165
	}
166
}
167

            
168
impl<T, S, V, M, X> MultiplierUpdate for TargetedFeeAdjustment<T, S, V, M, X>
169
where
170
	T: frame_system::Config,
171
	S: Get<Perquintill>,
172
	V: Get<Multiplier>,
173
	M: Get<Multiplier>,
174
	X: Get<Multiplier>,
175
{
176
53637
	fn min() -> Multiplier {
177
53637
		M::get()
178
53637
	}
179
	fn max() -> Multiplier {
180
		X::get()
181
	}
182
53637
	fn target() -> Perquintill {
183
53637
		S::get()
184
53637
	}
185
	fn variability() -> Multiplier {
186
		V::get()
187
	}
188
}
189

            
190
impl<T, S, V, M, X> Convert<Multiplier, Multiplier> for TargetedFeeAdjustment<T, S, V, M, X>
191
where
192
	T: frame_system::Config,
193
	S: Get<Perquintill>,
194
	V: Get<Multiplier>,
195
	M: Get<Multiplier>,
196
	X: Get<Multiplier>,
197
{
198
248400
	fn convert(previous: Multiplier) -> Multiplier {
199
248400
		// Defensive only. The multiplier in storage should always be at most positive. Nonetheless
200
248400
		// we recover here in case of errors, because any value below this would be stale and can
201
248400
		// never change.
202
248400
		let min_multiplier = M::get();
203
248400
		let max_multiplier = X::get();
204
248400
		let previous = previous.max(min_multiplier);
205
248400

            
206
248400
		let weights = T::BlockWeights::get();
207
248400
		// the computed ratio is only among the normal class.
208
248400
		let normal_max_weight =
209
248400
			weights.get(DispatchClass::Normal).max_total.unwrap_or(weights.max_block);
210
248400
		let current_block_weight = <frame_system::Pallet<T>>::block_weight();
211
248400
		let normal_block_weight =
212
248400
			current_block_weight.get(DispatchClass::Normal).min(normal_max_weight);
213
248400

            
214
248400
		// Normalize dimensions so they can be compared. Ensure (defensive) max weight is non-zero.
215
248400
		let normalized_ref_time = Perbill::from_rational(
216
248400
			normal_block_weight.ref_time(),
217
248400
			normal_max_weight.ref_time().max(1),
218
248400
		);
219
248400
		let normalized_proof_size = Perbill::from_rational(
220
248400
			normal_block_weight.proof_size(),
221
248400
			normal_max_weight.proof_size().max(1),
222
248400
		);
223

            
224
		// Pick the limiting dimension. If the proof size is the limiting dimension, then the
225
		// multiplier is adjusted by the proof size. Otherwise, it is adjusted by the ref time.
226
248400
		let (normal_limiting_dimension, max_limiting_dimension) =
227
248400
			if normalized_ref_time < normalized_proof_size {
228
				(normal_block_weight.proof_size(), normal_max_weight.proof_size())
229
			} else {
230
248400
				(normal_block_weight.ref_time(), normal_max_weight.ref_time())
231
			};
232

            
233
248400
		let target_block_fullness = S::get();
234
248400
		let adjustment_variable = V::get();
235
248400

            
236
248400
		let target_weight = (target_block_fullness * max_limiting_dimension) as u128;
237
248400
		let block_weight = normal_limiting_dimension as u128;
238
248400

            
239
248400
		// determines if the first_term is positive
240
248400
		let positive = block_weight >= target_weight;
241
248400
		let diff_abs = block_weight.max(target_weight) - block_weight.min(target_weight);
242
248400

            
243
248400
		// defensive only, a test case assures that the maximum weight diff can fit in Multiplier
244
248400
		// without any saturation.
245
248400
		let diff = Multiplier::saturating_from_rational(diff_abs, max_limiting_dimension.max(1));
246
248400
		let diff_squared = diff.saturating_mul(diff);
247
248400

            
248
248400
		let v_squared_2 = adjustment_variable.saturating_mul(adjustment_variable) /
249
248400
			Multiplier::saturating_from_integer(2);
250
248400

            
251
248400
		let first_term = adjustment_variable.saturating_mul(diff);
252
248400
		let second_term = v_squared_2.saturating_mul(diff_squared);
253
248400

            
254
248400
		if positive {
255
53637
			let excess = first_term.saturating_add(second_term).saturating_mul(previous);
256
53637
			previous.saturating_add(excess).clamp(min_multiplier, max_multiplier)
257
		} else {
258
			// Defensive-only: first_term > second_term. Safe subtraction.
259
194763
			let negative = first_term.saturating_sub(second_term).saturating_mul(previous);
260
194763
			previous.saturating_sub(negative).clamp(min_multiplier, max_multiplier)
261
		}
262
248400
	}
263
}
264

            
265
/// A struct to make the fee multiplier a constant
266
pub struct ConstFeeMultiplier<M: Get<Multiplier>>(core::marker::PhantomData<M>);
267

            
268
impl<M: Get<Multiplier>> MultiplierUpdate for ConstFeeMultiplier<M> {
269
	fn min() -> Multiplier {
270
		M::get()
271
	}
272
	fn max() -> Multiplier {
273
		M::get()
274
	}
275
	fn target() -> Perquintill {
276
		Default::default()
277
	}
278
	fn variability() -> Multiplier {
279
		Default::default()
280
	}
281
}
282

            
283
impl<M> Convert<Multiplier, Multiplier> for ConstFeeMultiplier<M>
284
where
285
	M: Get<Multiplier>,
286
{
287
	fn convert(_previous: Multiplier) -> Multiplier {
288
		Self::min()
289
	}
290
}
291

            
292
/// Storage releases of the pallet.
293
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
294
enum Releases {
295
	/// Original version of the pallet.
296
	V1Ancient,
297
	/// One that bumps the usage to FixedU128 from FixedI128.
298
	V2,
299
}
300

            
301
impl Default for Releases {
302
	fn default() -> Self {
303
		Releases::V1Ancient
304
	}
305
}
306

            
307
/// Default value for NextFeeMultiplier. This is used in genesis and is also used in
308
/// NextFeeMultiplierOnEmpty() to provide a value when none exists in storage.
309
const MULTIPLIER_DEFAULT_VALUE: Multiplier = Multiplier::from_u32(1);
310

            
311
#[frame_support::pallet]
312
pub mod pallet {
313
	use frame_support::pallet_prelude::*;
314
	use frame_system::pallet_prelude::*;
315

            
316
	use super::*;
317

            
318
1698
	#[pallet::pallet]
319
	pub struct Pallet<T>(_);
320

            
321
	pub mod config_preludes {
322
		use super::*;
323
		use frame_support::derive_impl;
324

            
325
		/// Default prelude sensible to be used in a testing environment.
326
		pub struct TestDefaultConfig;
327

            
328
		#[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
329
		impl frame_system::DefaultConfig for TestDefaultConfig {}
330

            
331
		#[frame_support::register_default_impl(TestDefaultConfig)]
332
		impl DefaultConfig for TestDefaultConfig {
333
			#[inject_runtime_type]
334
			type RuntimeEvent = ();
335
			type FeeMultiplierUpdate = ();
336
			type OperationalFeeMultiplier = ();
337
		}
338
	}
339

            
340
	#[pallet::config(with_default)]
341
	pub trait Config: frame_system::Config {
342
		/// The overarching event type.
343
		#[pallet::no_default_bounds]
344
		type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
345

            
346
		/// Handler for withdrawing, refunding and depositing the transaction fee.
347
		/// Transaction fees are withdrawn before the transaction is executed.
348
		/// After the transaction was executed the transaction weight can be
349
		/// adjusted, depending on the used resources by the transaction. If the
350
		/// transaction weight is lower than expected, parts of the transaction fee
351
		/// might be refunded. In the end the fees can be deposited.
352
		#[pallet::no_default]
353
		type OnChargeTransaction: OnChargeTransaction<Self>;
354

            
355
		/// Convert a weight value into a deductible fee based on the currency type.
356
		#[pallet::no_default]
357
		type WeightToFee: WeightToFee<Balance = BalanceOf<Self>>;
358

            
359
		/// Convert a length value into a deductible fee based on the currency type.
360
		#[pallet::no_default]
361
		type LengthToFee: WeightToFee<Balance = BalanceOf<Self>>;
362

            
363
		/// Update the multiplier of the next block, based on the previous block's weight.
364
		type FeeMultiplierUpdate: MultiplierUpdate;
365

            
366
		/// A fee multiplier for `Operational` extrinsics to compute "virtual tip" to boost their
367
		/// `priority`
368
		///
369
		/// This value is multiplied by the `final_fee` to obtain a "virtual tip" that is later
370
		/// added to a tip component in regular `priority` calculations.
371
		/// It means that a `Normal` transaction can front-run a similarly-sized `Operational`
372
		/// extrinsic (with no tip), by including a tip value greater than the virtual tip.
373
		///
374
		/// ```rust,ignore
375
		/// // For `Normal`
376
		/// let priority = priority_calc(tip);
377
		///
378
		/// // For `Operational`
379
		/// let virtual_tip = (inclusion_fee + tip) * OperationalFeeMultiplier;
380
		/// let priority = priority_calc(tip + virtual_tip);
381
		/// ```
382
		///
383
		/// Note that since we use `final_fee` the multiplier applies also to the regular `tip`
384
		/// sent with the transaction. So, not only does the transaction get a priority bump based
385
		/// on the `inclusion_fee`, but we also amplify the impact of tips applied to `Operational`
386
		/// transactions.
387
		#[pallet::constant]
388
		type OperationalFeeMultiplier: Get<u8>;
389
	}
390

            
391
	#[pallet::type_value]
392
	pub fn NextFeeMultiplierOnEmpty() -> Multiplier {
393
		MULTIPLIER_DEFAULT_VALUE
394
	}
395

            
396
779058
	#[pallet::storage]
397
	#[pallet::getter(fn next_fee_multiplier)]
398
	pub type NextFeeMultiplier<T: Config> =
399
		StorageValue<_, Multiplier, ValueQuery, NextFeeMultiplierOnEmpty>;
400

            
401
6
	#[pallet::storage]
402
	pub(super) type StorageVersion<T: Config> = StorageValue<_, Releases, ValueQuery>;
403

            
404
	#[pallet::genesis_config]
405
	pub struct GenesisConfig<T: Config> {
406
		pub multiplier: Multiplier,
407
		#[serde(skip)]
408
		pub _config: core::marker::PhantomData<T>,
409
	}
410

            
411
	impl<T: Config> Default for GenesisConfig<T> {
412
3
		fn default() -> Self {
413
3
			Self { multiplier: MULTIPLIER_DEFAULT_VALUE, _config: Default::default() }
414
3
		}
415
	}
416

            
417
	#[pallet::genesis_build]
418
	impl<T: Config> BuildGenesisConfig for GenesisConfig<T> {
419
3
		fn build(&self) {
420
3
			StorageVersion::<T>::put(Releases::V2);
421
3
			NextFeeMultiplier::<T>::put(self.multiplier);
422
3
		}
423
	}
424

            
425
	#[pallet::event]
426
	#[pallet::generate_deposit(pub(super) fn deposit_event)]
427
	pub enum Event<T: Config> {
428
		/// A transaction fee `actual_fee`, of which `tip` was added to the minimum inclusion fee,
429
		/// has been paid by `who`.
430
		TransactionFeePaid { who: T::AccountId, actual_fee: BalanceOf<T>, tip: BalanceOf<T> },
431
	}
432

            
433
554367
	#[pallet::hooks]
434
	impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
435
194763
		fn on_finalize(_: frame_system::pallet_prelude::BlockNumberFor<T>) {
436
259684
			<NextFeeMultiplier<T>>::mutate(|fm| {
437
194763
				*fm = T::FeeMultiplierUpdate::convert(*fm);
438
259684
			});
439
194763
		}
440

            
441
		#[cfg(feature = "std")]
442
53637
		fn integrity_test() {
443
53637
			// given weight == u64, we build multipliers from `diff` of two weight values, which can
444
53637
			// at most be maximum block weight. Make sure that this can fit in a multiplier without
445
53637
			// loss.
446
53637
			assert!(
447
53637
				<Multiplier as sp_runtime::traits::Bounded>::max_value() >=
448
53637
					Multiplier::checked_from_integer::<u128>(
449
53637
						T::BlockWeights::get().max_block.ref_time().try_into().unwrap()
450
53637
					)
451
53637
					.unwrap(),
452
53637
			);
453

            
454
53637
			let target = T::FeeMultiplierUpdate::target() *
455
53637
				T::BlockWeights::get().get(DispatchClass::Normal).max_total.expect(
456
53637
					"Setting `max_total` for `Normal` dispatch class is not compatible with \
457
53637
					`transaction-payment` pallet.",
458
53637
				);
459
53637
			// add 1 percent;
460
53637
			let addition = target / 100;
461
53637
			if addition == Weight::zero() {
462
				// this is most likely because in a test setup we set everything to ()
463
				// or to `ConstFeeMultiplier`.
464
				return
465
53637
			}
466
53637

            
467
53637
			// This is the minimum value of the multiplier. Make sure that if we collapse to this
468
53637
			// value, we can recover with a reasonable amount of traffic. For this test we assert
469
53637
			// that if we collapse to minimum, the trend will be positive with a weight value which
470
53637
			// is 1% more than the target.
471
53637
			let min_value = T::FeeMultiplierUpdate::min();
472
53637
			let target = target + addition;
473
53637

            
474
53637
			<frame_system::Pallet<T>>::set_block_consumed_resources(target, 0);
475
53637
			let next = T::FeeMultiplierUpdate::convert(min_value);
476
53637
			assert!(
477
53637
				next > min_value,
478
				"The minimum bound of the multiplier is too low. When \
479
				block saturation is more than target by 1% and multiplier is minimal then \
480
				the multiplier doesn't increase."
481
			);
482
53637
		}
483
	}
484
}
485

            
486
impl<T: Config> Pallet<T> {
487
	/// Query the data that we know about the fee of a given `call`.
488
	///
489
	/// This pallet is not and cannot be aware of the internals of a signed extension, for example
490
	/// a tip. It only interprets the extrinsic as some encoded value and accounts for its weight
491
	/// and length, the runtime's extrinsic base weight, and the current fee multiplier.
492
	///
493
	/// All dispatchables must be annotated with weight and will have some fee info. This function
494
	/// always returns.
495
	pub fn query_info<Extrinsic: sp_runtime::traits::Extrinsic + GetDispatchInfo>(
496
		unchecked_extrinsic: Extrinsic,
497
		len: u32,
498
	) -> RuntimeDispatchInfo<BalanceOf<T>>
499
	where
500
		T::RuntimeCall: Dispatchable<Info = DispatchInfo>,
501
	{
502
		// NOTE: we can actually make it understand `ChargeTransactionPayment`, but would be some
503
		// hassle for sure. We have to make it aware of the index of `ChargeTransactionPayment` in
504
		// `Extra`. Alternatively, we could actually execute the tx's per-dispatch and record the
505
		// balance of the sender before and after the pipeline.. but this is way too much hassle for
506
		// a very very little potential gain in the future.
507
		let dispatch_info = <Extrinsic as GetDispatchInfo>::get_dispatch_info(&unchecked_extrinsic);
508

            
509
		let partial_fee = if unchecked_extrinsic.is_signed().unwrap_or(false) {
510
			Self::compute_fee(len, &dispatch_info, 0u32.into())
511
		} else {
512
			// Unsigned extrinsics have no partial fee.
513
			0u32.into()
514
		};
515

            
516
		let DispatchInfo { weight, class, .. } = dispatch_info;
517

            
518
		RuntimeDispatchInfo { weight, class, partial_fee }
519
	}
520

            
521
	/// Query the detailed fee of a given `call`.
522
	pub fn query_fee_details<Extrinsic: sp_runtime::traits::Extrinsic + GetDispatchInfo>(
523
		unchecked_extrinsic: Extrinsic,
524
		len: u32,
525
	) -> FeeDetails<BalanceOf<T>>
526
	where
527
		T::RuntimeCall: Dispatchable<Info = DispatchInfo>,
528
	{
529
		let dispatch_info = <Extrinsic as GetDispatchInfo>::get_dispatch_info(&unchecked_extrinsic);
530

            
531
		let tip = 0u32.into();
532

            
533
		if unchecked_extrinsic.is_signed().unwrap_or(false) {
534
			Self::compute_fee_details(len, &dispatch_info, tip)
535
		} else {
536
			// Unsigned extrinsics have no inclusion fee.
537
			FeeDetails { inclusion_fee: None, tip }
538
		}
539
	}
540

            
541
	/// Query information of a dispatch class, weight, and fee of a given encoded `Call`.
542
	pub fn query_call_info(call: T::RuntimeCall, len: u32) -> RuntimeDispatchInfo<BalanceOf<T>>
543
	where
544
		T::RuntimeCall: Dispatchable<Info = DispatchInfo> + GetDispatchInfo,
545
	{
546
		let dispatch_info = <T::RuntimeCall as GetDispatchInfo>::get_dispatch_info(&call);
547
		let DispatchInfo { weight, class, .. } = dispatch_info;
548

            
549
		RuntimeDispatchInfo {
550
			weight,
551
			class,
552
			partial_fee: Self::compute_fee(len, &dispatch_info, 0u32.into()),
553
		}
554
	}
555

            
556
	/// Query fee details of a given encoded `Call`.
557
	pub fn query_call_fee_details(call: T::RuntimeCall, len: u32) -> FeeDetails<BalanceOf<T>>
558
	where
559
		T::RuntimeCall: Dispatchable<Info = DispatchInfo> + GetDispatchInfo,
560
	{
561
		let dispatch_info = <T::RuntimeCall as GetDispatchInfo>::get_dispatch_info(&call);
562
		let tip = 0u32.into();
563

            
564
		Self::compute_fee_details(len, &dispatch_info, tip)
565
	}
566

            
567
	/// Compute the final fee value for a particular transaction.
568
	pub fn compute_fee(
569
		len: u32,
570
		info: &DispatchInfoOf<T::RuntimeCall>,
571
		tip: BalanceOf<T>,
572
	) -> BalanceOf<T>
573
	where
574
		T::RuntimeCall: Dispatchable<Info = DispatchInfo>,
575
	{
576
		Self::compute_fee_details(len, info, tip).final_fee()
577
	}
578

            
579
	/// Compute the fee details for a particular transaction.
580
	pub fn compute_fee_details(
581
		len: u32,
582
		info: &DispatchInfoOf<T::RuntimeCall>,
583
		tip: BalanceOf<T>,
584
	) -> FeeDetails<BalanceOf<T>>
585
	where
586
		T::RuntimeCall: Dispatchable<Info = DispatchInfo>,
587
	{
588
		Self::compute_fee_raw(len, info.weight, tip, info.pays_fee, info.class)
589
	}
590

            
591
	/// Compute the actual post dispatch fee for a particular transaction.
592
	///
593
	/// Identical to `compute_fee` with the only difference that the post dispatch corrected
594
	/// weight is used for the weight fee calculation.
595
	pub fn compute_actual_fee(
596
		len: u32,
597
		info: &DispatchInfoOf<T::RuntimeCall>,
598
		post_info: &PostDispatchInfoOf<T::RuntimeCall>,
599
		tip: BalanceOf<T>,
600
	) -> BalanceOf<T>
601
	where
602
		T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
603
	{
604
		Self::compute_actual_fee_details(len, info, post_info, tip).final_fee()
605
	}
606

            
607
	/// Compute the actual post dispatch fee details for a particular transaction.
608
	pub fn compute_actual_fee_details(
609
		len: u32,
610
		info: &DispatchInfoOf<T::RuntimeCall>,
611
		post_info: &PostDispatchInfoOf<T::RuntimeCall>,
612
		tip: BalanceOf<T>,
613
	) -> FeeDetails<BalanceOf<T>>
614
	where
615
		T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
616
	{
617
		Self::compute_fee_raw(
618
			len,
619
			post_info.calc_actual_weight(info),
620
			tip,
621
			post_info.pays_fee(info),
622
			info.class,
623
		)
624
	}
625

            
626
	fn compute_fee_raw(
627
		len: u32,
628
		weight: Weight,
629
		tip: BalanceOf<T>,
630
		pays_fee: Pays,
631
		class: DispatchClass,
632
	) -> FeeDetails<BalanceOf<T>> {
633
		if pays_fee == Pays::Yes {
634
			// the adjustable part of the fee.
635
			let unadjusted_weight_fee = Self::weight_to_fee(weight);
636
			let multiplier = Self::next_fee_multiplier();
637
			// final adjusted weight fee.
638
			let adjusted_weight_fee = multiplier.saturating_mul_int(unadjusted_weight_fee);
639

            
640
			// length fee. this is adjusted via `LengthToFee`.
641
			let len_fee = Self::length_to_fee(len);
642

            
643
			let base_fee = Self::weight_to_fee(T::BlockWeights::get().get(class).base_extrinsic);
644
			FeeDetails {
645
				inclusion_fee: Some(InclusionFee { base_fee, len_fee, adjusted_weight_fee }),
646
				tip,
647
			}
648
		} else {
649
			FeeDetails { inclusion_fee: None, tip }
650
		}
651
	}
652

            
653
	/// Compute the length portion of a fee by invoking the configured `LengthToFee` impl.
654
	pub fn length_to_fee(length: u32) -> BalanceOf<T> {
655
		T::LengthToFee::weight_to_fee(&Weight::from_parts(length as u64, 0))
656
	}
657

            
658
	/// Compute the unadjusted portion of the weight fee by invoking the configured `WeightToFee`
659
	/// impl. Note that the input `weight` is capped by the maximum block weight before computation.
660
	pub fn weight_to_fee(weight: Weight) -> BalanceOf<T> {
661
		// cap the weight to the maximum defined in runtime, otherwise it will be the
662
		// `Bounded` maximum of its data type, which is not desired.
663
		let capped_weight = weight.min(T::BlockWeights::get().max_block);
664
		T::WeightToFee::weight_to_fee(&capped_weight)
665
	}
666
}
667

            
668
impl<T> Convert<Weight, BalanceOf<T>> for Pallet<T>
669
where
670
	T: Config,
671
{
672
	/// Compute the fee for the specified weight.
673
	///
674
	/// This fee is already adjusted by the per block fee adjustment factor and is therefore the
675
	/// share that the weight contributes to the overall fee of a transaction. It is mainly
676
	/// for informational purposes and not used in the actual fee calculation.
677
	fn convert(weight: Weight) -> BalanceOf<T> {
678
		<NextFeeMultiplier<T>>::get().saturating_mul_int(Self::weight_to_fee(weight))
679
	}
680
}
681

            
682
/// Require the transactor pay for themselves and maybe include a tip to gain additional priority
683
/// in the queue.
684
///
685
/// # Transaction Validity
686
///
687
/// This extension sets the `priority` field of `TransactionValidity` depending on the amount
688
/// of tip being paid per weight unit.
689
///
690
/// Operational transactions will receive an additional priority bump, so that they are normally
691
/// considered before regular transactions.
692
#[derive(Encode, Decode, Clone, Eq, PartialEq, TypeInfo)]
693
#[scale_info(skip_type_params(T))]
694
pub struct ChargeTransactionPayment<T: Config>(#[codec(compact)] BalanceOf<T>);
695

            
696
impl<T: Config> ChargeTransactionPayment<T>
697
where
698
	T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
699
	BalanceOf<T>: Send + Sync,
700
{
701
	/// utility constructor. Used only in client/factory code.
702
	pub fn from(fee: BalanceOf<T>) -> Self {
703
		Self(fee)
704
	}
705

            
706
	/// Returns the tip as being chosen by the transaction sender.
707
	pub fn tip(&self) -> BalanceOf<T> {
708
		self.0
709
	}
710

            
711
	fn withdraw_fee(
712
		&self,
713
		who: &T::AccountId,
714
		call: &T::RuntimeCall,
715
		info: &DispatchInfoOf<T::RuntimeCall>,
716
		len: usize,
717
	) -> Result<
718
		(
719
			BalanceOf<T>,
720
			<<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::LiquidityInfo,
721
		),
722
		TransactionValidityError,
723
	> {
724
		let tip = self.0;
725
		let fee = Pallet::<T>::compute_fee(len as u32, info, tip);
726

            
727
		<<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::withdraw_fee(
728
			who, call, info, fee, tip,
729
		)
730
		.map(|i| (fee, i))
731
	}
732

            
733
	/// Get an appropriate priority for a transaction with the given `DispatchInfo`, encoded length
734
	/// and user-included tip.
735
	///
736
	/// The priority is based on the amount of `tip` the user is willing to pay per unit of either
737
	/// `weight` or `length`, depending which one is more limiting. For `Operational` extrinsics
738
	/// we add a "virtual tip" to the calculations.
739
	///
740
	/// The formula should simply be `tip / bounded_{weight|length}`, but since we are using
741
	/// integer division, we have no guarantees it's going to give results in any reasonable
742
	/// range (might simply end up being zero). Hence we use a scaling factor:
743
	/// `tip * (max_block_{weight|length} / bounded_{weight|length})`, since given current
744
	/// state of-the-art blockchains, number of per-block transactions is expected to be in a
745
	/// range reasonable enough to not saturate the `Balance` type while multiplying by the tip.
746
	pub fn get_priority(
747
		info: &DispatchInfoOf<T::RuntimeCall>,
748
		len: usize,
749
		tip: BalanceOf<T>,
750
		final_fee: BalanceOf<T>,
751
	) -> TransactionPriority {
752
		// Calculate how many such extrinsics we could fit into an empty block and take the
753
		// limiting factor.
754
		let max_block_weight = T::BlockWeights::get().max_block;
755
		let max_block_length = *T::BlockLength::get().max.get(info.class) as u64;
756

            
757
		// bounded_weight is used as a divisor later so we keep it non-zero.
758
		let bounded_weight = info.weight.max(Weight::from_parts(1, 1)).min(max_block_weight);
759
		let bounded_length = (len as u64).clamp(1, max_block_length);
760

            
761
		// returns the scarce resource, i.e. the one that is limiting the number of transactions.
762
		let max_tx_per_block_weight = max_block_weight
763
			.checked_div_per_component(&bounded_weight)
764
			.defensive_proof("bounded_weight is non-zero; qed")
765
			.unwrap_or(1);
766
		let max_tx_per_block_length = max_block_length / bounded_length;
767
		// Given our current knowledge this value is going to be in a reasonable range - i.e.
768
		// less than 10^9 (2^30), so multiplying by the `tip` value is unlikely to overflow the
769
		// balance type. We still use saturating ops obviously, but the point is to end up with some
770
		// `priority` distribution instead of having all transactions saturate the priority.
771
		let max_tx_per_block = max_tx_per_block_length
772
			.min(max_tx_per_block_weight)
773
			.saturated_into::<BalanceOf<T>>();
774
		let max_reward = |val: BalanceOf<T>| val.saturating_mul(max_tx_per_block);
775

            
776
		// To distribute no-tip transactions a little bit, we increase the tip value by one.
777
		// This means that given two transactions without a tip, smaller one will be preferred.
778
		let tip = tip.saturating_add(One::one());
779
		let scaled_tip = max_reward(tip);
780

            
781
		match info.class {
782
			DispatchClass::Normal => {
783
				// For normal class we simply take the `tip_per_weight`.
784
				scaled_tip
785
			},
786
			DispatchClass::Mandatory => {
787
				// Mandatory extrinsics should be prohibited (e.g. by the [`CheckWeight`]
788
				// extensions), but just to be safe let's return the same priority as `Normal` here.
789
				scaled_tip
790
			},
791
			DispatchClass::Operational => {
792
				// A "virtual tip" value added to an `Operational` extrinsic.
793
				// This value should be kept high enough to allow `Operational` extrinsics
794
				// to get in even during congestion period, but at the same time low
795
				// enough to prevent a possible spam attack by sending invalid operational
796
				// extrinsics which push away regular transactions from the pool.
797
				let fee_multiplier = T::OperationalFeeMultiplier::get().saturated_into();
798
				let virtual_tip = final_fee.saturating_mul(fee_multiplier);
799
				let scaled_virtual_tip = max_reward(virtual_tip);
800

            
801
				scaled_tip.saturating_add(scaled_virtual_tip)
802
			},
803
		}
804
		.saturated_into::<TransactionPriority>()
805
	}
806
}
807

            
808
impl<T: Config> core::fmt::Debug for ChargeTransactionPayment<T> {
809
	#[cfg(feature = "std")]
810
	fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
811
		write!(f, "ChargeTransactionPayment<{:?}>", self.0)
812
	}
813
	#[cfg(not(feature = "std"))]
814
	fn fmt(&self, _: &mut core::fmt::Formatter) -> core::fmt::Result {
815
		Ok(())
816
	}
817
}
818

            
819
impl<T: Config> SignedExtension for ChargeTransactionPayment<T>
820
where
821
	BalanceOf<T>: Send + Sync + From<u64>,
822
	T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
823
{
824
	const IDENTIFIER: &'static str = "ChargeTransactionPayment";
825
	type AccountId = T::AccountId;
826
	type Call = T::RuntimeCall;
827
	type AdditionalSigned = ();
828
	type Pre = (
829
		// tip
830
		BalanceOf<T>,
831
		// who paid the fee - this is an option to allow for a Default impl.
832
		Self::AccountId,
833
		// imbalance resulting from withdrawing the fee
834
		<<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::LiquidityInfo,
835
	);
836
	fn additional_signed(&self) -> core::result::Result<(), TransactionValidityError> {
837
		Ok(())
838
	}
839

            
840
	fn validate(
841
		&self,
842
		who: &Self::AccountId,
843
		call: &Self::Call,
844
		info: &DispatchInfoOf<Self::Call>,
845
		len: usize,
846
	) -> TransactionValidity {
847
		let (final_fee, _) = self.withdraw_fee(who, call, info, len)?;
848
		let tip = self.0;
849
		Ok(ValidTransaction {
850
			priority: Self::get_priority(info, len, tip, final_fee),
851
			..Default::default()
852
		})
853
	}
854

            
855
	fn pre_dispatch(
856
		self,
857
		who: &Self::AccountId,
858
		call: &Self::Call,
859
		info: &DispatchInfoOf<Self::Call>,
860
		len: usize,
861
	) -> Result<Self::Pre, TransactionValidityError> {
862
		let (_fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
863
		Ok((self.0, who.clone(), imbalance))
864
	}
865

            
866
194763
	fn post_dispatch(
867
194763
		maybe_pre: Option<Self::Pre>,
868
194763
		info: &DispatchInfoOf<Self::Call>,
869
194763
		post_info: &PostDispatchInfoOf<Self::Call>,
870
194763
		len: usize,
871
194763
		_result: &DispatchResult,
872
194763
	) -> Result<(), TransactionValidityError> {
873
194763
		if let Some((tip, who, imbalance)) = maybe_pre {
874
			let actual_fee = Pallet::<T>::compute_actual_fee(len as u32, info, post_info, tip);
875
			T::OnChargeTransaction::correct_and_deposit_fee(
876
				&who, info, post_info, actual_fee, tip, imbalance,
877
			)?;
878
			Pallet::<T>::deposit_event(Event::<T>::TransactionFeePaid { who, actual_fee, tip });
879
194763
		}
880
194763
		Ok(())
881
194763
	}
882
}
883

            
884
impl<T: Config, AnyCall: GetDispatchInfo + Encode> EstimateCallFee<AnyCall, BalanceOf<T>>
885
	for Pallet<T>
886
where
887
	T::RuntimeCall: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
888
{
889
	fn estimate_call_fee(call: &AnyCall, post_info: PostDispatchInfo) -> BalanceOf<T> {
890
		let len = call.encoded_size() as u32;
891
		let info = call.get_dispatch_info();
892
		Self::compute_actual_fee(len, &info, &post_info, Zero::zero())
893
	}
894
}