referrerpolicy=no-referrer-when-downgrade

polkadot_sdk_docs/reference_docs/
transaction_extensions.rs

1//! Transaction extensions are, briefly, a means for different chains to extend the "basic"
2//! extrinsic format with custom data that can be checked by the runtime.
3//!
4//! # FRAME provided transaction extensions
5//!
6//! FRAME by default already provides the following transaction extensions:
7//!
8//! - [`CheckGenesis`](frame_system::CheckGenesis): Ensures that a transaction was sent for the same
9//!   network. Determined based on genesis.
10//!
11//! - [`CheckMortality`](frame_system::CheckMortality): Extends a transaction with a configurable
12//!   mortality.
13//!
14//! - [`CheckNonZeroSender`](frame_system::CheckNonZeroSender): Ensures that the sender of a
15//!   transaction is not the *all zero account* (all bytes of the accountid are zero).
16//!
17//! - [`CheckNonce`](frame_system::CheckNonce): Extends a transaction with a nonce to prevent replay
18//!   of transactions and to provide ordering of transactions.
19//!
20//! - [`CheckSpecVersion`](frame_system::CheckSpecVersion): Ensures that a transaction was built for
21//!   the currently active runtime.
22//!
23//! - [`CheckTxVersion`](frame_system::CheckTxVersion): Ensures that the transaction signer used the
24//!   correct encoding of the call.
25//!
26//! - [`CheckWeight`](frame_system::CheckWeight): Ensures that the transaction fits into the block
27//!   before dispatching it.
28//!
29//! - [`ChargeTransactionPayment`](pallet_transaction_payment::ChargeTransactionPayment): Charges
30//!   transaction fees from the signer based on the weight of the call using the native token.
31//!
32//! - [`ChargeAssetTxPayment`](pallet_asset_tx_payment::ChargeAssetTxPayment): Charges transaction
33//!   fees from the signer based on the weight of the call using any supported asset (including the
34//!   native token).
35//!
36//! - [`ChargeAssetTxPayment`(using
37//!   conversion)](pallet_asset_conversion_tx_payment::ChargeAssetTxPayment): Charges transaction
38//!   fees from the signer based on the weight of the call using any supported asset (including the
39//!   native token). The asset is converted to the native token using a pool.
40//!
41//! - [`SkipCheckIfFeeless`](pallet_skip_feeless_payment::SkipCheckIfFeeless): Allows transactions
42//!   to be processed without paying any fee. This requires that the `call` that should be
43//!   dispatched is augmented with the [`feeless_if`](frame_support::pallet_macros::feeless_if)
44//!   attribute.
45//!
46//! - [`CheckMetadataHash`](frame_metadata_hash_extension::CheckMetadataHash): Extends transactions
47//!   to include the so-called metadata hash. This is required by chains to support the generic
48//!   Ledger application and other similar offline wallets.
49//!
50//! - [`WeightReclaim`](frame_system::WeightReclaim): A transaction extension for the relay chain
51//!   that reclaims unused weight after executing a transaction.
52//!
53//! - [`StorageWeightReclaim`](cumulus_pallet_weight_reclaim::StorageWeightReclaim): A transaction
54//!   extension for parachains that reclaims unused storage weight after executing a transaction.
55//!
56//! For more information about these extensions, follow the link to the type documentation.
57//!
58//! # Building a custom transaction extension
59//!
60//! Defining a couple of very simple transaction extensions looks like the following:
61#![doc = docify::embed!("./src/reference_docs/transaction_extensions.rs", transaction_extensions_example)]
62
63#[docify::export]
64pub mod transaction_extensions_example {
65	use codec::{Decode, DecodeWithMemTracking, Encode};
66	use scale_info::TypeInfo;
67	use sp_runtime::{
68		impl_tx_ext_default,
69		traits::{Dispatchable, TransactionExtension},
70		transaction_validity::TransactionValidityError,
71	};
72
73	// This doesn't actually check anything, but simply allows
74	// some arbitrary `u32` to be added to the extrinsic payload
75	#[derive(Debug, Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo)]
76	pub struct AddToPayload(pub u32);
77
78	impl<Call: Dispatchable> TransactionExtension<Call> for AddToPayload {
79		const IDENTIFIER: &'static str = "AddToPayload";
80		type Implicit = ();
81		type Pre = ();
82		type Val = ();
83
84		impl_tx_ext_default!(Call; weight validate prepare);
85	}
86
87	// This is the opposite; nothing will be added to the extrinsic payload,
88	// but the Implicit type (`1234u32`) will be added to the
89	// payload to be signed.
90	#[derive(Debug, Encode, Decode, DecodeWithMemTracking, Clone, Eq, PartialEq, TypeInfo)]
91	pub struct AddToSignaturePayload;
92
93	impl<Call: Dispatchable> TransactionExtension<Call> for AddToSignaturePayload {
94		const IDENTIFIER: &'static str = "AddToSignaturePayload";
95		type Implicit = u32;
96
97		fn implicit(&self) -> Result<Self::Implicit, TransactionValidityError> {
98			Ok(1234)
99		}
100		type Pre = ();
101		type Val = ();
102
103		impl_tx_ext_default!(Call; weight validate prepare);
104	}
105}