Polkadot Release Analysis: Polkadot stable2412
The following report is not an exhaustive list of changes included in the release, but a set of changes that we felt deserved to be highlighted due to their impact on the Polkadot ecosystem builders.
Please do not stop reading the release notes Polkadot stable2412. This report is complementary to the changelogs, not a replacement.
Highlights are categorized into High Impact, Medium Impact, and Low Impact for ease of navigation.
There is also a section related to all note worthy changes related to integration tooling.
Summary
In the following report, we are featuring some of the changes included in the Polkadot stable2412. This report highlights key updates across various pallets and modules in the Polkadot ecosystem, with a significant focus on enhancements to pallet-revive (e.g., Ethereum JSON-RPC integration, balance transfers, and API improvements) and XCM v5 (e.g., InitiateTransfer
and SetAssetClaimer
instructions). These changes emphasize improving cross-chain communication and refining specific pallet functionalities.
Runtime changes that are part of this release will be included in the corresponding runtime release done by the fellowship.
Next to every PR name you can find the code base related to these changes. The notation is as follows:
- [S]: Changes related to Substrate
- [P]: Changes related to Polkadot
- [C]: Changes related to Cumulus
- [S/P/C]: Changes related to a combination of the noted code bases.
Tooling & Documentation Updates
- Sidecar - v19.3.1
- TxWrapper - v7.5.3
- PolkadotJS - v15.0.2
- Asset Transfer Api - v0.4.5
- Update Templates Readme - Github Repo links - This PR fixes documentation issues to improve the reliability and comprehensiveness of setup instructions for Polkadot SDK templates, making it easier for developers to work with the SDK and its various templates (minimal, parachain, solochain).
- Templates: make node compilation optional - This PR addresses the issue described in #5940, aiming to make node compilation optional in the Polkadot SDK templates for minimal and parachain. It simplifies the development process when only working with the runtime and avoids unnecessary compilation of the node.
- Templates: add genesis config presets for minimal/solochain - This PR improves the development and testing process for Polkadot developers by adding genesis configuration presets for the minimal and solochain templates. It simplifies the initialization of nodes for testing and development, reuses existing node chain spec presets, and streamlines the process of generating chain-specs for these templates.
Medium Impact
[S] MBM try-runtime support
PR: MBM `try-runtime` support by liamaharon · Pull Request #4251 · paritytech/polkadot-sdk · GitHub
Why is this important?
This PR introduces try-runtime
support for Multi-Block Migrations (MBM), addressing the need for safe and robust testing of long-running migrations in Polkadot and Substrate-based blockchains. MBMs are crucial for complex state transitions that exceed the weight limits of a single block. Adding hooks for pre_upgrade and post_upgrade enables builders to simulate, test, and validate these migrations in a controlled environment before executing them on the live network.
This enhancement also integrates seamlessly with the try-runtime-CLI
tool, making it an essential feature for CI pipelines and improving the reliability of upgrades.
How does this impact Polkadot Builders?
To use the new try-runtime
hooks for MBMs, builders need to implement the pre_upgrade
and post_upgrade
functions in their migration code:
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, frame_support::sp_runtime::TryRuntimeError> {
// Perform checks and validations before the upgrade begins
// Return data required for the `post_upgrade` function
// Example:
ensure!(some_condition, "Pre-upgrade check failed");
Ok(vec![...]) // Pass required data
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(prev: Vec<u8>) -> Result<(), frame_support::sp_runtime::TryRuntimeError> {
// Validate the migration results using data from `pre_upgrade`
// Example:
ensure!(new_condition, "Post-upgrade check failed");
Ok(())
}
Steps to Integrate:
- Implement the hooks as shown above in your MBM migration.
- Enable the
try-runtime
feature when testing. - Run the migration using
try-runtime-CLI
to simulate the state changes and validate the results. - Fix any errors reported during the simulation and re-test until the migration passes.
This PR is a significant step forward for handling complex, long-running migrations on Substrate-based chains.
[C,P] [XCM-V5] : add new InitiateTransfer
instruction
Why is this important?
The InitiateTransfer
instruction introduced in this PR represents a significant enhancement for XCMv5. It allows for point-to-point asset transfers with more flexibility, efficiency, and composability than existing instructions like DepositReserveAsset
, InitiateReserveWithdraw
, and InitiateTeleport
. Here’s why it’s important:
- Unified Transfer Mechanism:
•InitiateTransfer
combines the functionality of existing transfer instructions into a single, versatile instruction.
• It provides the ability to define asset transfer types (Teleport
,ReserveDeposit
,ReserveWithdraw
) on a per-asset basis, making it more flexible for complex use cases. - Support for Remote Fees:
• Builders can specify an asset for paying execution fees on the destination chain (remote_fees
), improving the UX for cross-chain dApps by ensuring seamless execution on remote chains without requiring pre-funded accounts. - Remote XCM Integration:
• After transferring assets,InitiateTransfer
appends a user-defined XCM program (remote_xcm
) to the onward message, enabling further actions on the destination chain, such as calling smart contracts or executing transactions. - Composability Across Hops:
• For multi-hop asset transfers, builders can compose this instruction to handle each leg of the journey. This enables dApps to handle cross-chain interactions that span multiple intermediary chains. - Improved UX for Builders and dApps:
• By appendingBuyExecution
withWeightLimit::Unlimited
and using asset-based limits for fees, the instruction prioritizes ease of use for builders, making it easier to estimate and manage fees across chains.
How does this impact Polkadot Builders?
-
New Instruction Integration:
• Builders will need to incorporate theInitiateTransfer
instruction into their XCM programs where more granular control of asset transfers is required.
• Compared to existing instructions (DepositReserveAsset, InitiateReserveWithdraw, etc.), InitiateTransfer provides a consolidated and flexible alternative. -
Filter-Based Asset Handling:
• Builders can useAssetTransferFilter
to specify transfer types for different assets, offering more control over the transfer mechanism based on the chain’s role (e.g., reserve or non-reserve). -
Enhanced Fee Handling:
• By specifyingremote_fees
, builders can ensure fee payment on the destination chain, simplifying the setup required for cross-chain execution.Related Issue: #5209
[C,P] [XCM-V5] : InitiateTransfer
can alias XCM original origin on destination
Why is this important?
This PR builds upon the foundation established in #5876, enhancing and extending its functionality. It introduces the preserve_origin
parameter to the InitiateTransfer
XCMv5 instruction, which significantly enhances the flexibility of cross-chain interactions. Previously, asset transfer instructions would clear the origin on the remote chain for security reasons, limiting further operations in the same XCM message. By enabling the preservation of the original origin, developers can:
- Achieve Complex Cross-Chain Scenarios: Developers can now bundle asset transfers with other operations like
Transact
in a single XCM message without prefunding accounts on the destination chain. - Reduce Friction in Multi-Hop Transfers: This allows origin aliasing across intermediary hops, enabling seamless execution of complex XCM programs that span multiple chains.
- Broader Use Cases: Enables advanced patterns like transferring funds and executing remote transactions in a single step, enhancing usability for cross-chain applications like DeFi protocols.
How does this impact Polkadot Developers?
- New Parameter in
InitiateTransfer
: Developers must explicitly specifypreserve_origin
when constructing XCM messages. This requires understanding the trust relationships between the involved chains:
InitiateAssetsTransfer {
destination: Location,
assets: Vec<AssetTransferFilter>,
remote_fees: Option<AssetTransferFilter>,
+ preserve_origin: bool,
remote_xcm: Xcm<()>,
}
• preserve_origin
: true
enables origin aliasing but depends on the receiving chain’s configuration.
• preserve_origin
: false
retains the existing behavior (clearing the origin) and works universally.
- Incorporation of Alias Logic: Developers implementing runtime configurations for their parachains need to configure aliasing rules. Chains that want to support origin preservation must use adapters like
AliasChildLocation
orAliasOriginRootUsingFilter
.
[S] [Pallet-Revive] immutable data storage
Why is this important?
This PR introduces immutable data storage for smart contracts in the Polkadot ecosystem. Immutable variables are a common feature in Solidity and other contract-oriented programming languages. They enable developers to define variables whose values are set during contract deployment and remain unchanged throughout the contract’s lifetime. Here’s why this is important:
- Performance Considerations:
• The current implementation involves extra storage reads for contracts with immutable data, increasing execution costs. Builders must optimize contract logic to account for this.
• Future optimizations (e.g., caching) may reduce these costs but require careful design to avoid issues like potential DoS attacks. - Contract Design:
• Immutable variables provide a secure way to store deployment-time configuration, improving contract reliability and reducing potential attack vectors caused by mutable storage.
• This feature is particularly beneficial for builders transitioning from Solidity, allowing them to leverage existing patterns. - Polkadot Ecosystem Compatibility:
• The addition of immutable storage ensures that Polkadot smart contracts remain competitive with other ecosystems like Ethereum, fostering adoption and enabling new use cases.
How does this impact Polkadot Builders?
-
Immutable Data Storage API:
• Builders can now attach immutable data to contracts, making it accessible as part of theContractInfo
.• The data is stored in a separate storage map, so builders must account for the cost of additional storage reads.
-
set_code_hash
API Changes:
Theset_code_hash
API has been disabled. For builders, this means:
• Existing workflows relying onset_code_hash
will need adjustments.• In future updates, running the constructor during
set_code_hash
to initialize immutable data will provide a more robust implementation.
Low Impact
[S] Send balance when contract doesn’t exist
PR: https://github.com/paritytech/polkadot-sdk/pull/5664
Why is this important?
This PR introduces a significant improvement to pallet-revive, aligning its behavior with the EVM (Ethereum Virtual Machine) regarding balance transfers to non-contract addresses. The change ensures that if a call is made to an address that does not have an associated smart contract code, the operation will simply execute a balance transfer to that address.
How does this impact Polkadot Builders?
-
Simplifies Logic for Builders:
• Builders no longer need to manually check if the target address has associated contract code before initiating a balance transfer. This simplifies smart contract logic and reduces boilerplate code.
-
Enhanced compatibility:
• Aligning with EVM behavior makes it easier to migrate Ethereum-based dApps to Polkadot ecosystems using pallet-revive. Builders can reuse existing logic without needing to adapt to previously divergent behavior.
Related Issue: #5577
[S] [Pallet-Revive] Add Ethereum JSON-RPC server
Why is this important?
This PR is significant because it introduces a new Ethereum JSON-RPC server that integrates with a Substrate-based chain configured with the pallet-revive. This enhancement is particularly important for the following reasons:
-
Bridging Substrate and Ethereum Ecosystems:
• Ethereum is one of the most widely adopted blockchain ecosystems, and many decentralized applications (dApps) and services rely on the Ethereum JSON-RPC interface for interacting with Ethereum nodes. By introducing this JSON-RPC server for Substrate, it allows for easier integration and interaction with Ethereum-based tools and platforms, enhancing interoperability between Substrate and Ethereum.
-
Leveraging pallet-revive Functionality:
• The pallet-revive module allows Substrate chains to deploy and execute PolkaVM smart contracts. Integrating this with an Ethereum JSON-RPC server brings the capabilities of Ethereum’s interface, enabling developers to interact with the revived contracts through standard Ethereum methods.
[P] Improved TrustedQueryAPI signatures
Why is this important?
This PR improves the API design for XCM TrustedQueryAPI
, which plays a critical role in querying whether specific locations are trusted as reserves or teleporters for assets. By encapsulating the return type in a dedicated type alias, the PR achieves the following:
-
Improved Code Clarity:
• The new type alias
XcmTrustedQueryResult
replaces the verboseResult<bool, xcm_runtime_apis::trusted_query::Error>
in the API signatures. This makes the code more concise and easier to read. -
Enhances Maintainability:
• By centralizing the return type under a single alias, developers can easily update or extend the type in the future without needing to refactor individual method signatures across the codebase.
-
Encourages Consistency:
• This change enforces a standardized representation for the API’s return type, ensuring consistent usage across various runtime modules and reducing the likelihood of errors.
-
Improved Developer Experience:
• Developers using the API can now reference a semantically meaningful type (
XcmTrustedQueryResult
) rather than deciphering the raw `Result<bool, Error> `` signature, leading to better usability and reduced cognitive overhead.
[S] Implement try_append for StorageNMap
Why is this important?
This PR adds the missing try_append
functionality to StorageNMap
, aligning its API with other storage map types like StorageMap
. This is important for the following reasons:
-
Consistency Across Storage APIs:
•
try_append
already exists for StorageMap, allowing developers to append data to a bounded Vec stored in the map while respecting storage limits. This PR ensures that StorageNMap provides the same functionality, maintaining API consistency across all storage types. -
Enhanced Developer Productivity:
• Developers can now use the
try_append
API in StorageNMap without requiring custom workarounds or manual implementations. This reduces code complexity and improves productivity. -
Support for Complex Storage Use-Cases:
• StorageNMap is a powerful, flexible storage type that allows mapping over multiple keys. By adding try_append, developers can efficiently append to bounded Vec entries stored in complex N-dimensional maps, enabling better handling of dynamic storage requirements.
Related Issue: #5722
[P] Remove parachains_assigner code
Why is this important?
This PR removes the legacy parachains_assigner
pallet, which is no longer needed as the coretime assigner has been deployed across all production networks.
With parachains_assigner
removed, the focus shifts entirely to coretime, ensuring that all enhancements, bug fixes, and future improvements are targeted toward the new mechanism
Since coretime has been validated and deployed across production networks, removing the old code does not introduce compatibility issues.
Related Issue: #5970
[S] [Pallet-Revive] Update typeInfo
Why is this important?
This PR updates the typeInfo implementation in the experimental pallet-revive to ensure compatibility with Subxt, a Rust and WebAssembly library for interacting with Substrate-based nodes. This is critical because Subxt relies on accurate and transparent typeInfo metadata to generate strongly-typed bindings for interacting with Substrate pallets.
By making typeInfo transparent, this PR allows Subxt to accurately parse and reflect the metadata of pallet-revive. This enhances developer experience, as Subxt users can now programmatically interact with the pallet in a type-safe and ergonomic manner.
How does this impact Polkadot Builders?
Builders using Subxt
now gain type-safe bindings for pallet-revive
without needing to manually handle discrepancies in typeInfo. This reduces complexity and potential errors in building tools or applications around pallet-revive
.
[S] Remove pallet::getter from pallet-offences
Why is this important?
The PR removes the use of the pallet::getter
for accessing the Reports type in the pallet-offences module. To ensure that the retrieval of Reports continues to work correctly after this change, the PR adds a test to verify that storage::getter
can still properly retrieve the data from storage.
This change is part of a refactor to use more standardized and explicit methods for accessing pallet storage, promoting better clarity and maintainability in the codebase. The added test ensures that the new method of accessing the storage works as expected, providing confidence that the change does not break the functionality.
Related Issue: #3326
[S] [Pallet-NFTs, Pallet-Uniques] - Expose private structs
Why is this important?
This PR is significant as it enhances the extensibility of the pallet_nfts and pallet_uniques modules by exposing private structs and storage items, enabling other pallets to interact with and extend their functionalities. Specifically, it addresses the following needs:
-
Facilitates Cross-Chain NFT Functionality:
• By exposing private metadata and storage structs, developers can build universal cross-chain NFT bridging solutions. This ensures seamless NFT transfer and management across different parachains, regardless of whether they implement pallet_nfts or pallet_uniques. -
Enables Storage Access for Advanced Use Cases:
• Access to metadata and struct definitions allows developers to retrieve and parse on-chain storage directly, enabling advanced NFT operations, such as transferring entire collections or refunding deposits on the origin chain. -
Improves Builder Experience:
• Resolves limitations around private struct access, empowering developers to create interoperable NFT solutions without requiring complex workarounds or additional signer-based operations.
How does this impact Polkadot Builders?
Direct Access to Core Structs:
• Builders can now directly access the previously private storage and metadata of pallet_nfts and pallet_uniques, simplifying the integration of these pallets into custom solutions.
• Removes the need for duplicating data or implementing redundant logic to manage storage interactions.
Related Issue: #5959
[S] Introduce and Implement VestedTransfer
Trait
Why is this important?
This PR introduces a VestedTransfer
trait, a useful addition to Polkadot-based chains, which provides a clean, reusable interface for performing vested transfers. Instead of transferring funds immediately, this trait allows applying a vesting schedule to the transferred balance.
By introducing a trait, the PR decouples the vesting logic from specific implementations. This allows other pallets (e.g., Treasury) to easily integrate vested transfers without directly interacting with pallet_vesting.
How does this impact Polkadot Builders?
Builders can leverage the new VestedTransfer
trait to implement vested transfers in their custom pallets. Instead of duplicating vesting logic, they can reuse this interface to ensure standardized and error-free implementation.
[S] [Deprecation] deprecate treasury spend_local
call and related items
Why is this important?
The purpose of this PR is to deprecate the spend_local
call from the Treasury pallet along with its associated items. This is part of an effort to simplify the treasury functionality by consolidating the logic under the spend call. Key aspects include:
- Deprecation of spend_local and Associated Items:
- Deprecated items include:
Proposals
,ProposalCount
, andApprovals
storage items.- The
spend_local
andremove_approval
calls. - All public items linked exclusively to the above (e.g.,
MaxApprovals
).
- Introduction of
Paymaster
Configurations:
- To replicate the
spend_local
behavior, new configurations forPaymaster
andAssetKind
are introduced. These configurations allow for greater flexibility in handling native and non-native assets in treasury operations.
How does this impact Polkadot Builders
Builders:
• Must update their Treasury pallet configuration if they rely on spend_local.
• Migration is straightforward, with examples provided for native-only and mixed-asset configurations.
For Native-Only spend_local
Users:
To replace spend_local
, configure the Treasury pallet to use PayFromAccount
with AssetKind
set to ():
impl pallet_treasury::Config for Runtime {
type AssetKind = ();
type Paymaster = PayFromAccount<Self::Currency, TreasuryAccount>;
type BalanceConverter = UnityAssetBalanceConversion; // 1:1 balance conversion
}
For Mixed Native and Non-Native Asset Users:
For users already handling non-native assets via spend, extend the Treasury configuration to support both native and non-native assets using NativeOrWithId
and UnionOf
:
pub type NativeAndAssets =
UnionOf<Balances, Assets, NativeFromLeft, NativeOrWithId<u32>, AccountId>;
impl pallet_treasury::Config for Runtime {
type AssetKind = NativeOrWithId<u32>;
type Paymaster = PayAssetFromAccount<NativeAndAssets, TreasuryAccount>;
type BalanceConverter = AssetRate;
}
Additionally, configure the AssetRate pallet for balance conversions:
impl pallet_asset_rate::Config for Runtime {
type Currency = Balances;
type AssetKind = NativeOrWithId<u32>;
}
Related Issue: #5930